From 371d4c453bfae97853a7a915281a84bee4f0693b Mon Sep 17 00:00:00 2001 From: suyash67 Date: Fri, 5 Dec 2025 11:42:22 +0000 Subject: [PATCH 01/29] init readme. --- TRANSLATOR_CIRCUIT_EXPLAINED.md | 1326 +++++++++++++++++++++++++++++++ 1 file changed, 1326 insertions(+) create mode 100644 TRANSLATOR_CIRCUIT_EXPLAINED.md diff --git a/TRANSLATOR_CIRCUIT_EXPLAINED.md b/TRANSLATOR_CIRCUIT_EXPLAINED.md new file mode 100644 index 000000000000..649b3f9e915e --- /dev/null +++ b/TRANSLATOR_CIRCUIT_EXPLAINED.md @@ -0,0 +1,1326 @@ +# The Translator Circuit: Complete Technical Specification + +## Table of Contents + +1. [Overview](#overview) +2. [The Statement Being Proven](#the-statement-being-proven) +3. [Architecture and Constants](#architecture-and-constants) +4. [Witness Polynomials (81 Total)](#witness-polynomials-81-total) +5. [Selector Polynomials](#selector-polynomials) +6. [The Seven Relations](#the-seven-relations) +7. [Proof System Details](#proof-system-details) +8. [Proof Size Analysis](#proof-size-analysis) +9. [Critical Components for Auditing](#critical-components-for-auditing) + +--- + +## Overview + +The **Translator Circuit** is a critical component of the Goblin Plonk proving system in Aztec. It serves as a **bridge between two elliptic curves**: +- **BN254** (used in Mega circuits and Ethereum) +- **Grumpkin** (used in ECCVM for efficient EC operations) + +### The Problem + +When proving recursive circuits, we accumulate elliptic curve operations in an `EccOpQueue`. These operations are performed over **BN254's base field (𝔽q)**. However, the circuit itself operates in **BN254's scalar field (𝔽r)**. + +**Key challenge:** We need to prove that polynomial evaluations computed in **𝔽r** (the circuit's native field) match the evaluations that should be computed in **𝔽q** (the curve's base field). + +### The Solution + +The Translator circuit: +1. **Receives** a batched polynomial evaluation problem from ECCVM (operating over Grumpkin/𝔽q) +2. **Proves** that the evaluation is correct using non-native field arithmetic in 𝔽r +3. **Outputs** the result for verification in the main proving system + +**Analogy:** Think of Translator as an interpreter between two languages (𝔽r and 𝔽q) that proves it translated correctly. + +--- + +## The Statement Being Proven + +### High-Level Statement + +Given: +- A sequence of `UltraOp` operations from the `EccOpQueue` +- An evaluation challenge `x ∈ 𝔽q` +- A batching challenge `v ∈ 𝔽q` + +**Prove:** +$$\boxed{\text{accumulator}_{\text{final}} = \sum_{i=0}^{n-1} x^{n-1-i} \cdot \left( \text{op}_i + v \cdot P_x^{(i)} + v^2 \cdot P_y^{(i)} + v^3 \cdot z_1^{(i)} + v^4 \cdot z_2^{(i)} \right) \pmod{q}}$$ + +Where: +- `q = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` (BN254 base field modulus) +- Each `UltraOp` contains: `(op, P.x, P.y, z₁, zβ‚‚)` +- The computation is performed **in integers** then reduced modulo `q` + +### Detailed Statement + +For each accumulation step (every 2 rows), prove: + +$$\text{acc}_{\text{curr}} = \text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ + +**Method:** Prove in integers using: +$$\text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \text{quotient} \cdot q - \text{acc}_{\text{curr}} = 0$$ + +This equation must hold: +1. **Modulo 2²⁷²** (proven via limb arithmetic) +2. **Modulo r** (proven in native field) +3. With proper **range constraints** (prevents overflow/underflow) + +**Soundness:** Since `2²⁷² Β· r > 2⁡¹⁴` (larger than maximum possible value), correctness in both moduli implies correctness in integers. + +--- + +## Architecture and Constants + +### Circuit Size Parameters + +```cpp +CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE = 13 // Mini-circuit: 2^13 = 8,192 rows +INTERLEAVING_GROUP_SIZE = 16 // Interleaving factor +CONST_TRANSLATOR_LOG_N = 13 + 4 = 17 // Full circuit: 2^17 = 131,072 rows +``` + +**Why interleaving?** To reduce the degree of the permutation argument polynomial for range constraints. + +### Field Moduli + +``` +BN254 Base Field (Fq): +q = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + β‰ˆ 2^254 + +BN254 Scalar Field (Fr): +r = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 + β‰ˆ 2^254 +``` + +**Key observation:** `q β‰  r` (they differ by ~2⁴⁷), so we cannot directly compute in 𝔽q using 𝔽r arithmetic. + +### Limb Decomposition Constants + +```cpp +NUM_LIMB_BITS = 68 // Each limb is 68 bits +NUM_LAST_LIMB_BITS = 50 // Top limb: 254 - 3*68 = 50 bits +NUM_BINARY_LIMBS = 4 // Total limbs per element + +NUM_Z_BITS = 128 // z₁ and zβ‚‚ are 128-bit +NUM_Z_LIMBS = 2 // z values use 2 limbs (68 + 60 bits) + +NUM_QUOTIENT_BITS = 256 // Quotient needs 256 bits +NUM_LAST_QUOTIENT_LIMB_BITS = 52 // 256 - 3*68 = 52 bits + +MICRO_LIMB_BITS = 14 // Range constraint granularity +NUM_MICRO_LIMBS = 6 // 68 / 14 β‰ˆ 5, plus 1 for shift +``` + +**Limb structure for P.x, P.y, accumulator:** +``` +Element = limb[0] + 2^68 Β· limb[1] + 2^136 Β· limb[2] + 2^204 Β· limb[3] +where: + limb[0], limb[1], limb[2] ∈ [0, 2^68) + limb[3] ∈ [0, 2^50) +``` + +### Opcode Values + +```cpp +Valid opcodes: {0, 1, 2, 3, 4, 8} +``` + +Encoding EC operations: +- `0`: No-op / NULL +- `1`: Add +- `2`: Mul (scalar multiplication) +- `3`: Equality check +- `4`: Reset accumulator +- `8`: [Special operation] + +### Range Constraint Constants + +```cpp +SORT_STEP = 3 // Max delta between sorted values +NUM_RANGE_CONSTRAINT_WIRES = 5 // ordered_range_constraints_{0,1,2,3,4} +SORTED_STEPS_COUNT = 2^14 / 3 + 1 // Number of "step" values inserted + = 5462 steps +``` + +Each microlimb must be ≀ 2¹⁴ - 1 = 16383. + +--- + +## Interleaving: The Key Optimization + +### Why Interleaving is Necessary + +The Translator needs to perform **range constraints on ~64 different microlimb sets** using a **permutation argument**. Without optimization, this creates a major problem with the **relation degree**. + +**The Core Issue: Permutation Argument Degree** + +In a permutation argument, the degree of the relation is determined by **how many columns** are being permuted simultaneously: + +``` +Grand product relation: +z_perm[i+1] Γ— ∏_{j=1}^{NUM_COLS} (ordered[j] + Ξ² + Ξ³) = +z_perm[i] Γ— ∏_{j=1}^{NUM_COLS} (interleaved[j] + Ξ² + Ξ³) + +Degree = 1 + NUM_COLS (polynomial z_perm Γ— product of NUM_COLS columns) +``` + +**The Translator's Challenge:** + +- We have **~64 different logical microlimb columns** that need range constraints: + - P.x: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns + - P.y: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns + - z₁, zβ‚‚: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns + - Accumulator: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns + - Quotient: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns + - Relation wide limbs: 2 Γ— 6 microlimbs = 12 microlimb columns + - **Total: ~130 logical microlimb columns** (many reuse physical wires) + +**Naive approach:** +If we tried to permute all ~64 active columns at once: +- Degree = 1 + 64 = **65** +- This is **prohibitively expensive** for sumcheck! +- The relation would dominate proof generation time +- Higher degree = more FFT operations, more commitment cost + +**The Solution: Interleaving to Reduce Column Count** + +Instead of checking 64 columns in one permutation, we: +1. **Group 16 logical columns together** and pack them into the circuit at different row segments +2. **Use only 5 physical wires** for each permutation check (4 interleaved + 1 extra numerator) +3. **Reuse these 5 wires across 16 different segments** of the circuit +4. Each segment checks a different subset of ~4 logical columns from the original 64 + +**Result:** +- Relation degree: 1 + 5 = **6** (plus Lagrange = 7 total) +- This is manageable for the proof system! +- We perform 16 separate permutation checks (one per segment), each with low degree + +### How Interleaving Works + +#### The Basic Concept + +**Mini-circuit vs. Full Circuit:** +``` +Mini-circuit size: 2^13 = 8,192 rows (where actual computation happens) +Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) + +Relationship: FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE + 131,072 = 8,192 Γ— 16 +``` + +**Key idea:** Instead of 64+ columns in one permutation check (degree 65+), we group logical columns together and reuse 5 physical columns across 16 circuit segments (degree 7). + +#### The Interleaving Structure + +For each **set of range constraint wires** (e.g., all P.x microlimbs), we create two types of polynomials: + +**1. Interleaved Polynomials** (in full circuit) +- Size: 131,072 (full circuit size) +- Contains microlimbs from **multiple mini-circuit rows** packed together + +**2. Ordered Polynomials** (in full circuit) +- Size: 131,072 (full circuit size) +- Contains the **sorted version** of the interleaved values + +### Detailed Interleaving Mapping + +Let's trace exactly how microlimbs from the mini-circuit map to the full circuit: + +#### Example: P.x Low Limbs Range Constraint 0 (First Microlimb) + +**In the mini-circuit:** Each even row i ∈ {0, 2, 4, ..., 8190} generates a microlimb value: +``` +mini_row 0 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[0] = micro_0_0 +mini_row 2 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[2] = micro_0_2 +mini_row 4 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[4] = micro_0_4 +... +mini_row 8190 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[8190] = micro_0_8190 +``` + +Total: ~4,096 microlimbs (half of 8,192 rows, since only even rows are active). + +**Interleaving into full circuit:** + +These 4,096 values are **interleaved** into 16 groups: + +``` +Group 0: mini_rows {0, 32, 64, 96, ...} β†’ full_circuit rows {0, 1, 2, 3, ...} +Group 1: mini_rows {2, 34, 66, 98, ...} β†’ full_circuit rows {8192, 8193, 8194, ...} +Group 2: mini_rows {4, 36, 68, 100, ...} β†’ full_circuit rows {16384, 16385, 16386, ...} +... +Group 15: mini_rows {30, 62, 94, 126, ...} β†’ full_circuit rows {122880, 122881, 122882, ...} +``` + +**Formula:** +``` +For mini_row = 2k (even rows only): + group_id = k mod 16 + position_in_group = k Γ· 16 + + full_circuit_row = group_id Γ— 8192 + position_in_group +``` + +**Example calculation:** +``` +mini_row = 64 (32nd even row, so k = 32) + group_id = 32 mod 16 = 0 + position = 32 Γ· 16 = 2 + full_circuit_row = 0 Γ— 8192 + 2 = 2 + +mini_row = 66 (33rd even row, so k = 33) + group_id = 33 mod 16 = 1 + position = 33 Γ· 16 = 2 + full_circuit_row = 1 Γ— 8192 + 2 = 8194 +``` + +### The Complete Circuit Trace Structure + +Here's the exact layout of the full circuit with interleaving: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ FULL CIRCUIT (2^17 = 131,072 rows) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ INTERLEAVED GROUP 0 Rows 0-8191 β”‚ +β”‚ β”œβ”€ Contains values from mini_rows: 0, 32, 64, 96, ... β”‚ +β”‚ β”œβ”€ interleaved_range_constraints_0[i] for i ∈ [0, 8191] β”‚ +β”‚ └─ ordered_range_constraints_0[i] = sorted version β”‚ +β”‚ β”‚ +β”‚ INTERLEAVED GROUP 1 Rows 8192-16383 β”‚ +β”‚ β”œβ”€ Contains values from mini_rows: 2, 34, 66, 98, ... β”‚ +β”‚ β”œβ”€ interleaved_range_constraints_1[i] β”‚ +β”‚ └─ ordered_range_constraints_1[i] = sorted version β”‚ +β”‚ β”‚ +β”‚ INTERLEAVED GROUP 2 Rows 16384-24575 β”‚ +β”‚ β”œβ”€ Contains values from mini_rows: 4, 36, 68, 100, ... β”‚ +β”‚ β”œβ”€ interleaved_range_constraints_2[i] β”‚ +β”‚ └─ ordered_range_constraints_2[i] = sorted version β”‚ +β”‚ β”‚ +β”‚ INTERLEAVED GROUP 3 Rows 24576-32767 β”‚ +β”‚ β”œβ”€ Contains values from mini_rows: 6, 38, 70, 102, ... β”‚ +β”‚ β”œβ”€ interleaved_range_constraints_3[i] β”‚ +β”‚ └─ ordered_range_constraints_3[i] = sorted version β”‚ +β”‚ β”‚ +β”‚ ... β”‚ +β”‚ (Groups 4-14 follow same pattern) β”‚ +β”‚ ... β”‚ +β”‚ β”‚ +β”‚ INTERLEAVED GROUP 15 Rows 122880-131071β”‚ +β”‚ β”œβ”€ Contains values from mini_rows: 30, 62, 94, 126, ... β”‚ +β”‚ β”œβ”€ interleaved_range_constraints_4[i] (reuses wire 4) β”‚ +β”‚ └─ ordered_range_constraints_4[i] = sorted version β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Important observation:** We only have **5 physical wires** for range constraints: +- `ordered_range_constraints_0` through `ordered_range_constraints_4` +- `interleaved_range_constraints_0` through `interleaved_range_constraints_3` +- Plus one extra numerator wire + +But we need to check **many more** microlimb sets. The solution: +- Each wire is **reused across different interleaving groups** +- Within each 8,192-row segment, the wire represents a different logical microlimb set +- The permutation argument operates **within each segment independently** + +### Why Interleaving Reduces Relation Degree + +**The Critical Insight: Degree = Number of Columns in Product** + +The permutation relation has the form: +``` +z_perm[i+1] Γ— ∏_{j=0}^{NUM_COLS-1} (ordered[j][i] + Ξ² + Ξ³) = +z_perm[i] Γ— ∏_{j=0}^{NUM_COLS-1} (interleaved[j][i] + Ξ² + Ξ³) +``` + +**Degree = 1 (from z_perm) + NUM_COLS (from the products)** + +**Without interleaving (naive approach):** +``` +Check all ~64 logical microlimb columns in one relation: + +Relation: + z_perm[i+1] Γ— ∏_{j=0}^{63} (ordered[j][i] + Ξ² + Ξ³) = + z_perm[i] Γ— ∏_{j=0}^{63} (interleaved[j][i] + Ξ² + Ξ³) + +DEGREE = 1 + 64 = 65 + +This creates a degree-65 relation! +- Sumcheck round complexity: 65 univariate polynomials per round +- FFT operations: O(n Β· 65) +- Prover time: dominated by high-degree relation +- **Completely impractical!** +``` + +**With interleaving (only 5 physical columns per check):** +``` +Group 16 logical columns together, use 5 physical wires per segment: + +Relation (same for all 16 segments): + z_perm[i+1] Γ— (ordered_0[i] + Ξ² + Ξ³) + Γ— (ordered_1[i] + Ξ² + Ξ³) + Γ— (ordered_2[i] + Ξ² + Ξ³) + Γ— (ordered_3[i] + Ξ² + Ξ³) + Γ— (ordered_4[i] + Ξ² + Ξ³) + = z_perm[i] Γ— (interleaved_0[i] + Ξ² + Ξ³) + Γ— (interleaved_1[i] + Ξ² + Ξ³) + Γ— (interleaved_2[i] + Ξ² + Ξ³) + Γ— (interleaved_3[i] + Ξ² + Ξ³) + Γ— (extra_numerator[i] + Ξ² + Ξ³) + +DEGREE = 1 + 5 = 6 (or 7 with Lagrange selector) + +Much more manageable! +``` + +**Degree reduction: 65 β†’ 7 (more than 9Γ— reduction!)** + +**How it works:** +- **Segment 0** (rows 0-8,191): Wires represent logical columns {0, 1, 2, 3, 4} +- **Segment 1** (rows 8,192-16,383): Same wires represent logical columns {5, 6, 7, 8, 9} +- **Segment 2** (rows 16,384-24,575): Same wires represent logical columns {10, 11, 12, 13, 14} +- ... and so on for 16 segments + +Each segment checks a different subset of logical columns, but all use the **same low-degree relation**! + +### The Permutation Check with Interleaving + +The permutation relation operates **within each 8,192-row segment**: + +**For segment s ∈ {0, 1, ..., 15}:** + +``` +Base row index: base = s Γ— 8,192 + +For row i within segment [0, 8191]: + full_row = base + i + + z_perm[full_row + 1] Γ— DENOMINATOR = z_perm[full_row] Γ— NUMERATOR + + Where: + NUMERATOR = (interleaved_0[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (interleaved_1[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (interleaved_2[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (interleaved_3[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (extra_numerator[full_row] + Ξ²Β·L_mask + Ξ³) + + DENOMINATOR = (ordered_0[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (ordered_1[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (ordered_2[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (ordered_3[full_row] + Ξ²Β·L_mask + Ξ³) + Γ— (ordered_4[full_row] + Ξ²Β·L_mask + Ξ³) +``` + +**Key insight:** The permutation argument doesn't know or care that these values came from different mini-circuit rows. It just checks that within each 8,192-row segment, the interleaved values are a permutation of the ordered values. + +### Concrete Example: Tracing One Microlimb + +Let's trace one specific microlimb through the entire system: + +**Setup:** +- We're checking P.x_low_limbs[0] (first 68-bit limb of P.x's lower 136 bits) +- At mini_row = 100 (even row, 50th accumulation) +- The value of the first 14-bit microlimb is: `micro = 0x2A5F = 10847` + +**Step 1: Mini-circuit computation (row 100)** +``` +P_X_LOW_LIMBS[0] = limb_value = 0x1234567890ABCDEF +Decompose into microlimbs: + P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[100] = 0xCDEF = 52719 + P_X_LOW_LIMBS_RANGE_CONSTRAINT_1[100] = 0x9012 = 36882 + ... +``` + +**Step 2: Determine interleaving group** +``` +k = 100 / 2 = 50 (since mini_row 100 is the 50th even row) +group_id = 50 mod 16 = 2 +position = 50 Γ· 16 = 3 +``` + +**Step 3: Map to full circuit** +``` +full_circuit_row = 2 Γ— 8192 + 3 = 16384 + 3 = 16387 + +interleaved_range_constraints_2[16387] = 52719 +``` + +**Step 4: Sorting** + +All microlimbs in group 2 are collected and sorted: +``` +interleaved_2 = [52719, 36882, ..., 4096 more values from group 2 mini-rows] +ordered_2 = sorted(interleaved_2) = [0, 0, 0, ..., 1, 1, 2, ..., 16383] + ↑ with step values inserted +``` + +**Step 5: Permutation check** + +The permutation relation verifies: +``` +For full_circuit_row ∈ [16384, 24575] (group 2 segment): + + Accumulate in z_perm: + z_perm[16384] = 1 + z_perm[16385] = z_perm[16384] Γ— (interleaved_2[16384] + ...) / (ordered_2[16384] + ...) + ... + z_perm[16387] = ... includes our value 52719 ... + ... + z_perm[24575] should equal 1 (modulo public input delta) +``` + +If the permutation is valid, our microlimb `52719` is proven to be ≀ 16383. βœ“ + +### The Sorted Array Structure + +Each `ordered_range_constraints_j` polynomial contains: + +``` +Row 0: 0 +Row 1: 0 (possible duplicate) +Row 2: 0 (possible duplicate) +Row 3: 1 (step by 0 or 1 or 2 or 3) +Row 4: 3 (step by 2) +Row 5: 4 (step by 1) +Row 6: 7 (step by 3) +Row 7: 7 (possible duplicate, step by 0) +... +Row 5461: 16380 (step by 3) +Row 5462: 16383 (step by 3) +Row 5463: 16383 ← Last value must be exactly 16383 +``` + +With periodic "step" values inserted every few rows to ensure coverage of [0, 16383]. The delta range constraint relation enforces: +1. Each step ∈ {0, 1, 2, 3} +2. Final value = 16383 + +### Benefits of Interleaving + +**1. Relation Degree Reduction (Most Important):** +- **From degree 65 to degree 7** (9Γ— reduction) +- This is the primary benefit - keeps relations efficient +- Sumcheck complexity is dominated by max relation degree + +**2. Proof Size Stays Constant:** +- Only need one z_perm polynomial +- Reuse it across all 16 segments +- Proof doesn't grow with number of groups + +**3. Verification Efficiency:** +- Verifier checks same polynomial across segments +- No additional cost for more interleaving groups + +**4. Flexibility:** +- Can adjust INTERLEAVING_GROUP_SIZE based on circuit size +- Balances polynomial degree vs. circuit size blowup + +### Trade-offs + +**Cost of interleaving:** +- Circuit size increases by 16Γ— (from 8,192 to 131,072 rows) +- More zero padding needed (Relation 7 ensures unused rows are zero) +- More complex witness generation (need to correctly map mini-circuit to full circuit) + +**Why it's worth it:** +- **Relation degree reduction** >>> circuit size increase +- Sumcheck is dominated by max relation degree +- Without interleaving, degree-65 relation would make the circuit impractical +- With interleaving, degree-7 is manageable for production use + +### Summary + +**Interleaving is the technique that makes the Translator practical:** + +Without interleaving: +- Permutation checks ~64 columns at once +- **Relation degree: 65** +- Sumcheck with degree-65 polynomials: impractical +- Prover time: hours (if even feasible) +- Unusable in production + +With interleaving: +- Permutation checks only 5 columns at once +- **Relation degree: 7** +- Circuit size: 131,072 rows (16Γ— increase, acceptable trade-off) +- Prover time: minutes +- **Production-ready! βœ“** + +**The key insight:** Interleaving trades circuit size (cheap to increase) for relation degree (expensive if high). By grouping 16 logical columns together and reusing 5 physical wires across 16 circuit segments, we keep the relation degree low while still checking all necessary columns. + +--- + +## Witness Polynomials (81 Total) + +The Translator circuit uses **81 witness polynomials** (no selector polynomials). These can be categorized as follows: + +### Category 1: EccOpQueue Transcript (4 wires) + +These contain the raw data from the EC operation queue: + +| Wire | Description | Range | +|------|-------------|-------| +| `OP` | Operation code | {0, 1, 2, 3, 4, 8} | +| `X_LOW_Y_HI` | P.x_lo (136-bit) at even rows, P.y_hi (118-bit) at odd rows | < 2¹³⁢ or < 2¹¹⁸ | +| `X_HIGH_Z_1` | P.x_hi (118-bit) at even rows, z₁ (128-bit) at odd rows | < 2¹¹⁸ or < 2¹²⁸ | +| `Y_LOW_Z_2` | P.y_lo (136-bit) at even rows, zβ‚‚ (128-bit) at odd rows | < 2¹³⁢ or < 2¹²⁸ | + +**Note:** The circuit operates in a 2-row cycle: +- **Even rows (accumulation):** Compute new accumulator value +- **Odd rows (copy):** Transfer accumulator to next cycle + +### Category 2: Binary Limb Decompositions (12 wires) + +These decompose coordinates and z-values into 68-bit limbs: + +**P.x limbs (4 wires):** +- `P_X_LOW_LIMBS`: Two 68-bit limbs from P.x_lo +- `P_X_HIGH_LIMBS`: One 68-bit + one 50-bit limb from P.x_hi + +**P.y limbs (4 wires):** +- `P_Y_LOW_LIMBS`: Two 68-bit limbs from P.y_lo +- `P_Y_HIGH_LIMBS`: One 68-bit + one 50-bit limb from P.y_hi + +**z limbs (4 wires):** +- `Z_LOW_LIMBS`: 68-bit limbs of z₁ and zβ‚‚ (low parts) +- `Z_HIGH_LIMBS`: 60-bit limbs of z₁ and zβ‚‚ (high parts) + +### Category 3: Accumulator Limbs (4 wires) + +Store current and previous accumulator values: + +| Wire | Description | Bits per limb | +|------|-------------|---------------| +| `ACCUMULATORS_BINARY_LIMBS_0` | Limb 0 (current & previous) | 68 bits | +| `ACCUMULATORS_BINARY_LIMBS_1` | Limb 1 (current & previous) | 68 bits | +| `ACCUMULATORS_BINARY_LIMBS_2` | Limb 2 (current & previous) | 68 bits | +| `ACCUMULATORS_BINARY_LIMBS_3` | Limb 3 (current & previous) | 50 bits | + +**Layout:** Previous accumulator is at higher indices (row i+1) due to KZG commitment structure. + +### Category 4: Quotient Limbs (2 wires) + +The quotient from dividing by q: + +| Wire | Description | +|------|-------------| +| `QUOTIENT_LOW_BINARY_LIMBS` | Lower two 68-bit limbs | +| `QUOTIENT_HIGH_BINARY_LIMBS` | One 68-bit + one 52-bit limb | + +### Category 5: Relation Wide Limbs (1 wire) + +Used for modulo 2²⁷² computation: + +| Wire | Description | Bits | +|------|-------------|------| +| `RELATION_WIDE_LIMBS` | Carries for 136-bit computation steps | 84 bits each | + +Contains two values: +- **relation_wide_lower_limb:** Carry from lower 136-bit computation +- **relation_wide_higher_limb:** Carry from higher 136-bit computation + +### Category 6: Range Constraint Microlimbs (52 wires) + +Each limb is further decomposed into 14-bit microlimbs for tight range constraints: + +**Pattern for each element (P.x_lo, P.x_hi, P.y_lo, P.y_hi, z₁_lo, z₁_hi, zβ‚‚_lo, zβ‚‚_hi, acc_lo, acc_hi, quot_lo, quot_hi):** +- `*_RANGE_CONSTRAINT_0` through `*_RANGE_CONSTRAINT_4`: Five 14-bit microlimbs +- `*_RANGE_CONSTRAINT_TAIL`: Shifted highest microlimb (for stricter constraint) + +Examples: +``` +P_X_LOW_LIMBS_RANGE_CONSTRAINT_0 // Microlimb 0 (bits 0-13) +P_X_LOW_LIMBS_RANGE_CONSTRAINT_1 // Microlimb 1 (bits 14-27) +... +P_X_LOW_LIMBS_RANGE_CONSTRAINT_4 // Microlimb 4 (bits 56-69, actually 56-67) +P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL // Microlimb 4 << 4 (for exact 68-bit constraint) +``` + +**Relation wide limb microlimbs (4 wires):** +- `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0` through `_3`: Four 14-bit chunks + +Total range constraint wires: +- 10 elements Γ— 6 microlimbs = 60 wires +- But relation_wide_limbs only needs 4 microlimbs +- **Total: 56 microlimb wires** + +### Category 7: Ordered Range Constraint Wires (5 wires) + +Used for the permutation argument to prove all microlimbs are ≀ 2¹⁴ - 1: + +| Wire | Description | +|------|-------------| +| `ordered_range_constraints_0` | Sorted values for constraint set 0 | +| `ordered_range_constraints_1` | Sorted values for constraint set 1 | +| `ordered_range_constraints_2` | Sorted values for constraint set 2 | +| `ordered_range_constraints_3` | Sorted values for constraint set 3 | +| `ordered_range_constraints_4` | Sorted values for constraint set 4 | + +These are not explicit wires but are part of the interleaving structure. + +**Interleaving:** To handle 131,072 rows with efficient permutation, microlimbs from 16 consecutive mini-circuit rows are interleaved into single full-circuit rows. + +--- + +## Selector Polynomials + +**Critical fact:** The Translator circuit uses **ZERO selector polynomials** (`NUM_SELECTORS = 0`). + +Instead, the circuit uses **Lagrange polynomials** to control which constraints are active: + +### Lagrange Polynomials (Precomputed) + +| Polynomial | Description | Active Rows | +|------------|-------------|-------------| +| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | i ∈ {0, 2, 4, ..., 8190} (mini) | +| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | i ∈ {1, 3, 5, ..., 8191} (mini) | +| `lagrange_first` | First row | i = 0 | +| `lagrange_last_in_minicircuit` | Last row in mini-circuit | i = 8191 (mini) | +| `lagrange_result_row` | Row containing final result | Specific row in trace | +| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | +| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | + +**Why no selectors?** The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange polynomials, which are more efficient than custom selectors. + +--- + +## The Seven Relations + +The Translator circuit enforces correctness through **7 distinct relations** totaling **151 subrelations**. + +### Relation 1: Permutation Relation (2 subrelations) + +**Purpose:** Prove that all microlimbs are properly range-constrained to 14 bits. + +**Method:** Grand product argument over sorted vs. interleaved values. + +#### Subrelation 1.1: Grand Product Identity + +$$\boxed{(z_{\text{perm}} + L_0) \cdot \prod_{j=0}^{4} (\text{interleaved}_j + \beta \cdot L_{\text{mask}} + \gamma) = (z_{\text{perm,shift}} + L_{\text{last}}) \cdot \prod_{j=0}^{4} (\text{ordered}_j + \beta \cdot L_{\text{mask}} + \gamma)}$$ + +Where: +- **Numerator:** Product over 4 interleaved range constraint wires + 1 extra numerator +- **Denominator:** Product over 5 ordered range constraint wires +- **Masking:** `lagrange_masking` marks ZK rows to exclude from permutation + +**Intuition:** If the multisets match (interleaved = permutation of ordered), the grand product telescopes to 1. + +#### Subrelation 1.2: Final Value Check + +$$\boxed{L_{\text{last}} \cdot z_{\text{perm,shift}} = 0}$$ + +Ensures the grand product returns to 1 at the end (accounting for masking). + +**Degree:** 7 (highest in Translator) + +**Critical for security:** If this fails, an attacker could use out-of-range values, breaking the non-native field arithmetic soundness. + +### Relation 2: Delta Range Constraint Relation (10 subrelations) + +**Purpose:** Ensure ordered polynomials are actually sorted and bounded. + +**Method:** Check consecutive differences and final value. + +#### Subrelations 2.1-2.5: Difference Constraints + +For each `j ∈ {0, 1, 2, 3, 4}`: + +$$\boxed{(L_{\text{real\_last}} - 1) \cdot (L_{\text{mask}} - 1) \cdot \Delta_j \cdot (\Delta_j - 1) \cdot (\Delta_j - 2) \cdot (\Delta_j - 3) = 0}$$ + +Where: +$$\Delta_j = \text{ordered}_j^{(\text{shift})} - \text{ordered}_j$$ + +**Meaning:** The difference between consecutive values must be in {0, 1, 2, 3} (non-descending, max step = 3). + +**Why max step 3?** This allows the sorted array to contain "step" values every 3 increments, ensuring coverage of [0, 2¹⁴-1] without making the polynomial too dense. + +#### Subrelations 2.6-2.10: Maximum Value Constraints + +For each `j ∈ {0, 1, 2, 3, 4}`: + +$$\boxed{L_{\text{real\_last}} \cdot (\text{ordered}_j - (2^{14} - 1)) = 0}$$ + +**Meaning:** The last value in each sorted array must be exactly 2¹⁴ - 1 = 16383. + +**Together:** These constraints ensure every microlimb ∈ [0, 2¹⁴ - 1], which is the foundation for all range constraints. + +**Degree:** 7 (due to 5-way product for difference check) + +### Relation 3: Decomposition Relation (48 subrelations) + +**Purpose:** Prove that limbs are correctly decomposed into microlimbs and wide limbs into narrow limbs. + +**Method:** Polynomial identities checking decomposition formulas. + +#### Subrelation Types + +**Type A: Binary Limb Decomposition (6 subrelations)** + +For each transcript value (x_lo, x_hi, y_lo, y_hi, z₁, zβ‚‚): + +$$\boxed{L_{\text{even}} \cdot \left( \text{wide\_limb} - \text{limb}_{\text{low}} - 2^{68} \cdot \text{limb}_{\text{high}} \right) = 0}$$ + +Example for x_lo: +$$X\_LOW\_Y\_HI = P\_X\_LOW\_LIMBS[0] + 2^{68} \cdot P\_X\_LOW\_LIMBS[1]$$ + +**Type B: Limb to Microlimb Decomposition (44 subrelations)** + +For standard 68-bit limbs: + +$$\boxed{L_{\text{even}} \cdot \left( \text{limb} - \sum_{k=0}^{4} 2^{14k} \cdot \text{micro}_k - 2^{68} \cdot \text{micro}_{tail} \right) = 0}$$ + +Example for P.x limb 0: +``` +P_X_LOW_LIMBS[0] = + P_X_LOW_LIMBS_RANGE_CONSTRAINT_0 + + 2^14 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_1 + + 2^28 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_2 + + 2^42 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_3 + + 2^56 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_4 + + 2^68 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL +``` + +For top limbs (50-bit, 60-bit, 52-bit), the formula adjusts accordingly. + +For relation wide limbs (84-bit): +$$\text{relation\_wide\_limb} = \sum_{k=0}^{5} 2^{14k} \cdot \text{micro}_k$$ + +**Type C: Tail Microlimb Stricter Constraints (42 subrelations)** + +For elements that need exact bit constraints (not just ≀ 68): + +$$\boxed{L_{\text{even}} \cdot \left( \text{micro}_4 \cdot 2^{shift} - \text{micro}_{tail} \right) = 0}$$ + +Example: For 68-bit limb, shift = 4 (since 68 = 14Γ—4 + 12, so top microlimb must be ≀ 2ΒΉΒ² - 1): +$$\text{micro}_4 \cdot 16 = \text{micro}_{tail}$$ + +Since both `micro_4` and `micro_tail` are constrained to 14 bits by the permutation, this forces `micro_4 ≀ 2ΒΉΒ² - 1`. + +**Degree:** 4 (lagrange Γ— decomposition identity) + +**Why important:** Without correct decomposition, the non-native arithmetic breaks down completely. + +### Relation 4: Non-Native Field Relation (3 subrelations) + +**Purpose:** Prove the core accumulation identity in non-native field arithmetic. + +**The Formula:** +$$\text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \text{quot} \cdot q - \text{acc}_{\text{curr}} = 0$$ + +This must hold in two moduli for soundness. + +#### Subrelation 4.1: Lower Mod 2¹³⁢ Check + +Compute the formula using only limbs [0] and parts of limbs [1], check that result Γ· 2¹³⁢ equals `relation_wide_lower_limb`: + +$$\boxed{L_{\text{even}} \cdot \left( \text{LOWER\_COMPUTATION} - 2^{136} \cdot \text{relation\_wide\_lower\_limb} \right) = 0}$$ + +Where `LOWER_COMPUTATION` includes: +``` + acc_prev[0]Β·x[0] + op + P_x[0]Β·v[0] + P_y[0]Β·vΒ²[0] + z₁[0]Β·vΒ³[0] + zβ‚‚[0]Β·v⁴[0] ++ quot[0]Β·(-q)[0] - acc_curr[0] ++ 2^68Β·( + acc_prev[1]Β·x[0] + P_x[1]Β·v[0] + P_y[1]Β·vΒ²[0] + z₁[1]Β·vΒ³[0] + zβ‚‚[1]Β·v⁴[0] + + quot[1]Β·(-q)[0] + + acc_prev[0]Β·x[1] + P_x[0]Β·v[1] + P_y[0]Β·vΒ²[1] + z₁[0]Β·vΒ³[1] + zβ‚‚[0]Β·v⁴[1] + + quot[0]Β·(-q)[1] - acc_curr[1] +) +``` + +All arithmetic is in 𝔽r, but the structure mimics integer arithmetic mod 2¹³⁢. + +#### Subrelation 4.2: Higher Mod 2¹³⁢ Check + +Use `relation_wide_lower_limb` as carry and compute for limbs [2], [3]: + +$$\boxed{L_{\text{even}} \cdot \left( \text{HIGHER\_COMPUTATION} - 2^{136} \cdot \text{relation\_wide\_higher\_limb} \right) = 0}$$ + +Where `HIGHER_COMPUTATION` includes: +``` +relation_wide_lower_limb ++ combinations of limbs: (0,2), (1,1), (2,0), (0,3), (1,2), (2,1), (3,0), ... ++ higher cross-terms from all products +``` + +**Together (4.1 & 4.2):** Prove the relation holds modulo 2²⁷². + +#### Subrelation 4.3: Native Field Check + +Reconstruct full elements in 𝔽r and check directly: + +$$\boxed{L_{\text{even}} \cdot \text{NATIVE\_CHECK} = 0}$$ + +Where: +``` +NATIVE_CHECK = + acc_prev_native Β· x_native + op + P_x_native Β· v_native + P_y_native Β· vΒ²_native + + z₁_native Β· vΒ³_native + zβ‚‚_native Β· v⁴_native + - quot_native Β· q_native - acc_curr_native +``` + +And: +``` +acc_prev_native = acc_prev[0] + 2^68Β·acc_prev[1] + 2^136Β·acc_prev[2] + 2^204Β·acc_prev[3] (mod r) +``` + +**Degree:** 4 (lagrange Γ— triple products like accΒ·x) + +**Soundness argument:** +- If the relation holds mod 2²⁷² AND mod r +- AND all values are properly range-constrained +- THEN 2²⁷² Β· r > 2⁡¹⁴ > max_possible_value +- IMPLIES the relation holds in integers +- IMPLIES the relation holds mod q (since q < 2²⁡⁴) + +**This is the heart of the Translator circuit.** + +### Relation 5: Opcode Constraint Relation (5 subrelations) + +**Purpose:** Ensure opcodes are valid: op ∈ {0, 1, 2, 3, 4, 8}. + +**Method:** Enforce polynomial identity with roots at valid opcodes. + +$$\boxed{(L_{\text{even}} + L_{\text{mini\_mask}}) \cdot \text{op} \cdot (\text{op} - 1) \cdot (\text{op} - 2) \cdot (\text{op} - 3) \cdot (\text{op} - 4) \cdot (\text{op} - 8) = 0}$$ + +Actually implemented as 5 separate subrelations for efficiency (one per opcode comparison). + +**Degree:** 6 (lagrange Γ— 5-way product) + +**Why important:** Invalid opcodes could allow injection of arbitrary values into the accumulation. + +### Relation 6: Accumulator Transfer Relation (12 subrelations) + +**Purpose:** Handle non-arithmetic accumulator transitions (initialization, copying, finalization). + +#### Subrelations 6.1-6.4: Copy at Odd Rows + +At odd rows, accumulator should not change: + +$$\boxed{L_{\text{odd}} \cdot (\text{acc\_limb}_i - \text{acc\_limb}_i^{(\text{shift})}) = 0}$$ + +For `i ∈ {0, 1, 2, 3}`. + +#### Subrelations 6.5-6.8: Initialize to Zero + +At the start of accumulation (first row): + +$$\boxed{L_{\text{first}} \cdot \text{acc\_limb}_i = 0}$$ + +For `i ∈ {0, 1, 2, 3}`. + +#### Subrelations 6.9-6.12: Final Result Check + +At the result row, accumulator must match expected value: + +$$\boxed{L_{\text{result}} \cdot (\text{acc\_limb}_i - \text{expected\_result\_limb}_i) = 0}$$ + +For `i ∈ {0, 1, 2, 3}`. + +The expected result is provided as relation parameters (from ECCVM output). + +**Degree:** 4 (lagrange Γ— difference) + +### Relation 7: Zero Constraints Relation (68 subrelations) + +**Purpose:** Ensure all range constraint microlimb wires are zero outside the mini-circuit. + +**Why needed:** The interleaving structure means full circuit is 16Γ— larger than mini-circuit. Rows outside mini-circuit must be zero to avoid polluting the permutation argument. + +For each of 64 range constraint wires + 4 transcript wires: + +$$\boxed{(L_{\text{odd}} + L_{\text{even}} + L_{\text{mini\_mask}})^{\text{complement}} \cdot \text{wire}_i = 0}$$ + +Equivalently (via De Morgan): +$$\boxed{\neg(L_{\text{in\_mini}} \lor L_{\text{mask}}) \implies \text{wire}_i = 0}$$ + +**Special case for no-ops:** If `op = 0` at even rows, additional constraints force range wires to zero. + +**Degree:** 4 (lagrange Γ— wire value) + +**Why important:** Without this, garbage values in unused rows could satisfy the permutation argument while violating actual range constraints. + +--- + +## Proof System Details + +### Proof System Type + +**TranslatorFlavor** uses: +- **HyperNova-style sumcheck** with ZK (zero-knowledge) +- **KZG polynomial commitment scheme** over BN254 +- **Libra** for ZK masking +- **Gemini + Shplonk** for batched polynomial openings (Shplemini protocol) + +### Inputs to the Prover + +```cpp +struct TranslatorProverInput { + // From ECCVM + std::vector ecc_op_queue; // EC operations to batch + Fq evaluation_challenge_x; // Challenge point x ∈ Fq + Fq batching_challenge_v; // Batching challenge v ∈ Fq + + // Expected output (from ECCVM verification) + Fq expected_accumulator_result; // What acc_final should be + + // Powers of challenges (precomputed) + Fq x; + Fq v, v_squared, v_cubed, v_quarted; + + // Proving key + std::shared_ptr proving_key; +}; +``` + +**Construction:** +1. For each `UltraOp` in the queue, generate witness values: + - Decompose P.x, P.y, z₁, zβ‚‚ into limbs and microlimbs + - Compute quotient and new accumulator + - Compute relation wide limbs +2. Fill witness polynomials (81 wires Γ— circuit_size values) +3. Construct ordered range constraint polynomials via sorting +4. Create interleaved polynomials + +### Prover Algorithm + +``` +TranslatorProver::prove(): + 1. OINK phase (witness commitment): + - Commit to all 91 witness polynomials (90 + masking) + - Generate commitment challenges + + 2. Sumcheck phase: + - For each round d = 1 to 17: + - Compute sumcheck univariates over all 7 relations + - Send univariate coefficients to verifier + - Receive challenge u_d + - Output: Claimed evaluations at challenge point Ε« + + 3. Libra ZK sumcheck masking: + - Generate ZK commitments + - Prove claimed evaluation matches with ZK + + 4. Gemini multilinear opening: + - Fold multilinear polynomials d-1 times + - Reduce to d univariate openings + + 5. Shplonk batching: + - Batch all opening claims + - Reduce to single KZG opening + + 6. KZG opening proof: + - Compute W commitment + - Output final opening proof + + Return: TranslatorProof (568 field elements) +``` + +### Outputs from the Prover + +```cpp +struct TranslatorProof { + std::vector proof_data; // 568 field elements + Fq accumulated_result; // The batched evaluation result (Fq element) +}; +``` + +The proof contains: +1. Witness commitments (88 Γ— 2 = 176 Fr elements) +2. Libra commitments and sum (2 + 1 = 3 Fr) +3. Sumcheck univariates (17 rounds Γ— 8 coefficients = 136 Fr) +4. Sumcheck evaluations (188 Fr) +5. Libra evaluation (1 Fr) +6. Libra grand sum and quotient commitments (2 + 2 = 4 Fr) +7. Gemini commitments (16 Γ— 2 = 32 Fr) +8. Gemini evaluations (17 Fr) +9. Gemini positive/negative evaluations (2 Fr) +10. SmallSubgroupIPA evaluations (4 Fr) +11. Shplonk Q commitment (2 Fr) +12. KZG W commitment (2 Fr) +13. Accumulated result in Fq (1 Fq = 1 Fr for encoding) + +### Verifier Algorithm + +``` +TranslatorVerifier::verify(proof, vk): + 1. Deserialize proof + + 2. Reconstruct challenges (Fiat-Shamir): + - Hash commitments to generate challenges + + 3. Sumcheck verification: + - For each round, check univariate identity + - Accumulate claimed evaluations + + 4. Libra verification: + - Verify ZK grand sum + - Check claimed evaluation + + 5. Gemini verification: + - Verify fold commitments + - Check evaluation consistency + + 6. Shplonk verification: + - Batch all opening claims + + 7. KZG pairing check: + - Compute pairing e(W, [Ο„]β‚‚) vs e(commitment, [1]β‚‚) + - Accept if pairing checks pass + + 8. Check accumulated_result matches expected: + - Compare proof's accumulator against ECCVM output + + Return: accept/reject +``` + +--- + +## Proof Size Analysis + +As computed in CHONK_MATH_EXPLAINED.md, the Translator proof size is: + +### Detailed Breakdown + +| Component | Formula | Field Elements | +|-----------|---------|----------------| +| 1. Accumulated result (BN254 Fq) | `1 Γ— 1` | **1** | +| 2. Witness commitments | `88 Γ— 2` | **176** | +| 3. Libra concatenation commitment | `1 Γ— 2` | **2** | +| 4. Libra sum | `1 Γ— 1` | **1** | +| 5. Sumcheck univariates | `17 Γ— 8 Γ— 1` | **136** | +| 6. Sumcheck evaluations | `188 Γ— 1` | **188** | +| 7. Libra claimed evaluation | `1 Γ— 1` | **1** | +| 8. Libra grand sum commitment | `1 Γ— 2` | **2** | +| 9. Libra quotient commitment | `1 Γ— 2` | **2** | +| 10. Gemini fold commitments | `16 Γ— 2` | **32** | +| 11. Gemini evaluations | `17 Γ— 1` | **17** | +| 12. Gemini P positive evaluation | `1 Γ— 1` | **1** | +| 13. Gemini P negative evaluation | `1 Γ— 1` | **1** | +| 14. SmallSubgroupIPA evals | `4 Γ— 1` | **4** | +| 15. Shplonk Q commitment | `1 Γ— 2` | **2** | +| 16. KZG opening commitment | `1 Γ— 2` | **2** | + +**Total: 568 field elements = 568 Γ— 32 bytes = 18,176 bytes β‰ˆ 17.8 KB** + +### Comparison with Other Components + +| Component | Size (field elements) | Size (KB) | Percentage of Chonk | +|-----------|----------------------|-----------|---------------------| +| **Translator** | **568** | **17.8** | **37.6%** | +| Mega ZK | 356 | 11.1 | 23.6% | +| ECCVM | 488 | 15.2 | 32.3% | +| Merge | 42 | 1.3 | 2.8% | + +**Insight:** Translator is the **largest single component** in the Chonk proof, primarily due to: +1. 188 sumcheck evaluations (all 91 witness + 86 derived + shifts) +2. 136 sumcheck univariates (17 rounds Γ— 8 coefficients) +3. 176 witness commitments (88 polynomials) + +The large number of witness polynomials (81 explicit + derived) drives the proof size. + +--- + +## Critical Components for Auditing + +Ranked from most to least critical for security: + +### πŸ”΄ **CRITICAL (Audit First)** + +#### 1. Non-Native Field Relation (Relation 4) +**File:** `translator_non_native_field_relation.hpp` + +**Why critical:** +- **Core soundness:** This is the heart of the circuit. If this relation is wrong, the entire translation is invalid. +- **Complex arithmetic:** Involves intricate modular arithmetic across two moduli with limb-based computation. +- **Overflow risks:** If the mod 2²⁷² check is wrong, overflow could allow false proofs. + +**What to audit:** +- Verify the limb combination formulas match the mathematical specification exactly +- Check all powers of 2 (2⁢⁸, 2¹³⁢, etc.) are correct +- Ensure the "wide" relation limbs correctly capture carries +- Confirm native field reconstruction is complete (all cross-terms present) +- Test edge cases: maximum values, zero values, boundary conditions + +**Attack vector:** Incorrect arithmetic could allow proving wrong evaluations, breaking Goblin soundness. + +#### 2. Permutation Relation (Relation 1) +**File:** `translator_permutation_relation.hpp` + +**Why critical:** +- **Foundation for range constraints:** If permutation is broken, attacker can use out-of-range values. +- **Grand product soundness:** The z_perm computation must be absolutely correct. +- **Masking handling:** ZK rows must be properly excluded. + +**What to audit:** +- Verify grand product formula matches the specification +- Check initialization (z_perm[0] = 1 accounting for L_0) +- Verify finalization (z_perm[last] = 0 accounting for L_last and masking) +- Ensure interleaving structure is correctly implemented +- Test with malicious permutations + +**Attack vector:** Broken permutation β†’ use 2⁢⁸ instead of 2¹⁴ limbs β†’ completely break non-native arithmetic. + +#### 3. Delta Range Constraint Relation (Relation 2) +**File:** `translator_delta_range_constraint_relation.hpp` + +**Why critical:** +- **Enforces sorted property:** Without this, permutation check is meaningless. +- **Maximum value check:** Must ensure final value is exactly 2¹⁴ - 1. +- **Step constraint:** Max step of 3 is necessary for coverage. + +**What to audit:** +- Verify Ξ” ∈ {0,1,2,3} check is correctly implemented +- Confirm final value check at lagrange_last is exact +- Check masking rows are properly excluded +- Test boundary: can attacker craft a sequence that looks sorted but isn't? + +**Attack vector:** Wrong max value (e.g., 2¹⁡ instead of 2¹⁴) β†’ double the range β†’ break soundness. + +### 🟠 **HIGH PRIORITY** + +#### 4. Decomposition Relation (Relation 3) +**File:** `translator_decomposition_relation.hpp` + +**Why high priority:** +- **Ensures consistency:** Limbs must match original values. +- **Many subrelations (48):** More code = more potential bugs. +- **Tail microlimb logic:** The shift factors must be exact. + +**What to audit:** +- Verify all 48 decomposition formulas match specification +- Check powers of 2 are correct (2⁢⁸, 2¹⁴, etc.) +- Confirm tail shift calculations (especially the Γ—4, Γ—16 multipliers) +- Test: provide wrong decomposition, ensure relation catches it + +**Attack vector:** Wrong decomposition β†’ mismatch between transcript and limbs β†’ arbitrary values. + +#### 5. Opcode Constraint Relation (Relation 5) +**File:** `translator_extra_relations.hpp` + +**Why high priority:** +- **Input validation:** Invalid opcodes could inject malicious data. +- **Relatively simple:** But critical to get right. + +**What to audit:** +- Verify opcode set {0, 1, 2, 3, 4, 8} is complete and correct +- Check polynomial roots match opcodes exactly +- Ensure masking rows are handled + +**Attack vector:** Missing opcode constraint β†’ inject opcode 255 β†’ break accumulation logic. + +### 🟑 **MEDIUM PRIORITY** + +#### 6. Accumulator Transfer Relation (Relation 6) +**File:** `translator_extra_relations.hpp` + +**Why medium priority:** +- **Ensures state consistency:** But doesn't directly affect arithmetic soundness. +- **Edge cases:** Initialization and finalization must be correct. + +**What to audit:** +- Verify odd row copy constraint is active at all odd rows +- Check initialization to zero at start +- Confirm final result comparison uses correct expected value +- Test: try to skip initialization, see if caught + +**Attack vector:** Wrong initialization β†’ start with non-zero acc β†’ offset all computations. + +#### 7. Zero Constraints Relation (Relation 7) +**File:** `translator_extra_relations.hpp` + +**Why medium priority:** +- **Cleanup relation:** Ensures unused rows don't pollute permutation. +- **Many subrelations (68):** But mostly repetitive. + +**What to audit:** +- Verify all 68 wires are covered +- Check lagrange polynomial logic for "outside minicircuit" +- Ensure no-op case (op = 0) is handled correctly + +**Attack vector:** Garbage in unused rows β†’ permutation allows wrong values β†’ potential soundness break. + +### 🟒 **LOW PRIORITY (But Still Check)** + +#### 8. Circuit Builder Logic +**File:** `translator_circuit_builder.cpp` + +**Why low priority for audit:** +- Prover-side only (doesn't affect verification soundness directly) +- But bugs here could cause proof generation failures + +**What to check:** +- Witness generation formulas match relation formulas +- Quotient calculation is correct +- Microlimb splitting logic matches decomposition relation + +#### 9. Flavor Configuration +**File:** `translator_flavor.hpp` + +**Why low priority:** +- Configuration and constants +- But errors here (wrong NUM_LIMB_BITS) would be catastrophic + +**What to check:** +- All constants match specification +- Proof length formula is correct +- Polynomial commitment configuration is sound + +--- + +## Audit Checklist + +Use this checklist when auditing the Translator: + +### Mathematical Specification +- [ ] Verify q (Fq modulus) is correct BN254 base field +- [ ] Verify r (Fr modulus) is correct BN254 scalar field +- [ ] Confirm 2²⁷² Β· r > 2⁡¹⁴ (soundness bound) +- [ ] Check limb sizes: 68, 68, 68, 50 bits for 254-bit values +- [ ] Verify microlimb size: 14 bits +- [ ] Confirm SORT_STEP = 3 is sufficient for coverage + +### Non-Native Field Arithmetic +- [ ] Audit all limb combination formulas in subrelation 4.1 +- [ ] Audit all limb combination formulas in subrelation 4.2 +- [ ] Verify native field reconstruction in subrelation 4.3 +- [ ] Test with maximum value inputs +- [ ] Test with zero inputs +- [ ] Test with adversarial quotients + +### Range Constraints +- [ ] Verify permutation grand product formula +- [ ] Check delta constraint polynomial (degree 5 product) +- [ ] Confirm final value = 2¹⁴ - 1 exactly +- [ ] Test with out-of-order values +- [ ] Test with values > 2¹⁴ + +### Decomposition +- [ ] Verify all 6 binary limb decompositions +- [ ] Verify all 44 microlimb decompositions +- [ ] Check all 42 tail microlimb stricter constraints +- [ ] Test with wrong decompositions + +### Edge Cases +- [ ] First row (initialization) +- [ ] Last row (finalization) +- [ ] No-op case (op = 0) +- [ ] Masking rows (ZK) +- [ ] Interleaving boundary + +### Implementation +- [ ] Code review all relation implementations +- [ ] Verify relation degrees match specification +- [ ] Check lagrange polynomial usage is correct +- [ ] Ensure no off-by-one errors in indices +- [ ] Test proof generation and verification end-to-end + +--- + +**Document Version:** 1.0 +**Author:** ZK Content Expert +**Last Updated:** 2025-12-04 +**Purpose:** Advanced Modern Cryptography Course Material & Security Audit Guide From a7ba596188ddfa385dab0f1c7ee59f61e465ebc4 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Mon, 8 Dec 2025 12:49:45 +0000 Subject: [PATCH 02/29] init nnf relation readme. --- TRANSLATOR_NON_NATIVE_FIELD_MATH.md | 604 ++++++++++++++++++++++++++++ 1 file changed, 604 insertions(+) create mode 100644 TRANSLATOR_NON_NATIVE_FIELD_MATH.md diff --git a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md new file mode 100644 index 000000000000..7609e37cde30 --- /dev/null +++ b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md @@ -0,0 +1,604 @@ +# Translator Non-Native Field Relation: Complete Mathematical Derivation + +## Document Purpose + +This document provides a rigorous mathematical treatment of the **Non-Native Field Relation** in the Translator circuit, using consistent LaTeX nomenclature throughout. This is the core relation that enables computation in 𝔽q (BN254 base field) using only 𝔽r (BN254 scalar field) arithmetic. + +--- + +## Witness Trace Structure + +The Translator circuit operates on a **2-row cycle structure**. Each EccOpQueue entry occupies exactly 2 rows: + +- **Row 2i (Even rows)**: **Computation rows** where the non-native field relation is actively checked +- **Row 2i+1 (Odd rows)**: **Data storage rows** that hold values accessed by the next even row via shifts + +This architecture exists because of how polynomial commitments work in the KZG scheme: the "shifted" polynomial at index $i$ evaluates to the polynomial at index $i+1$. Thus: + +- Even row $2i$ performs computation using "current" values from its own row +- Even row $2i$ accesses "previous" values from odd row $2i+1$ via shift columns +- Odd row $2i+1$ stores the data that will become "previous" for the next computation at row $2i+2$ + +The Translator circuit has **81 witness columns** organized into several categories: + +#### 1. EccOpQueue Transcript Columns (4 columns) + +These columns directly represent the EccOpQueue transcript: + +| Column | Even Row (2i) | Odd Row (2i+1) | Description | +| ----------- | --------------------------------- | ---------------------------- | --------------------------------------------- | +| `OP` | $\texttt{op} \in \{0,1,2,3,4,8\}$ | 0 (no-op) | Opcode (the type of elliptic curve operation) | +| `X_LO_Y_HI` | $P_{x,\text{lo}}$ (136 bits) | $P_{y,\text{hi}}$ (118 bits) | Low 136 bits of P.x and High 118 bits of P.y | +| `X_HI_Z_1` | $P_{x,\text{hi}}$ (118 bits) | $z_1$ (128 bits) | High 118 bits of P.x and first scalar | +| `Y_LO_Z_2` | $P_{y,\text{lo}}$ (136 bits) | $z_2$ (128 bits) | Low 136 bits of P.y and second scalar | +| | | | | + +**Encoding scheme**: Point coordinates $P_x$ and $P_y$ are each 254 bits, split as: + +- $P_x = (P_{x,\text{hi}}$ (118 bits) $\|$ $P_{x,\text{lo}}$ (136 bits) $)$ +- $P_y = (P_{y,\text{hi}}$ (118 bits) $\|$ $P_{y,\text{lo}}$ (136 bits) $)$ + +#### 2. Limb Decomposition Columns (13 columns) + +These columns store finer-grained limb decompositions for non-native arithmetic: + +| Column Group | Even Row (2i) | Odd Row (2i+1) | Bits | Purpose | +| ----------------------------- | --------------------- | --------------------- | ------ | ---------------------------------------- | +| `P_X_LOW_LIMBS` | $P_{x,0}^{\text{lo}}$ | $P_{x,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{x,\text{lo}}$ | +| `P_X_HIGH_LIMBS` | $P_{x,0}^{\text{hi}}$ | $P_{x,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{x,\text{hi}}$ | +| `P_Y_LOW_LIMBS` | $P_{y,0}^{\text{lo}}$ | $P_{y,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{y,\text{lo}}$ | +| `P_Y_HIGH_LIMBS` | $P_{y,0}^{\text{hi}}$ | $P_{y,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{y,\text{hi}}$ | +| `Z_LOW_LIMBS` | $z_{1,0}$ | $z_{2,0}$ | 68 | Low limbs of $z_1$ and $z_2$ | +| `Z_HIGH_LIMBS` | $z_{1,1}$ | $z_{2,1}$ | 60 | High limbs of $z_1$ and $z_2$ | +| `ACCUMULATORS_BINARY_LIMBS_0` | $a_0^{\text{curr}}$ | $a_0^{\text{prev}}$ | 68 | Limb 0 of current/previous accumulator | +| `ACCUMULATORS_BINARY_LIMBS_1` | $a_1^{\text{curr}}$ | $a_1^{\text{prev}}$ | 68 | Limb 1 of current/previous accumulator | +| `ACCUMULATORS_BINARY_LIMBS_2` | $a_2^{\text{curr}}$ | $a_2^{\text{prev}}$ | 68 | Limb 2 of current/previous accumulator | +| `ACCUMULATORS_BINARY_LIMBS_3` | $a_3^{\text{curr}}$ | $a_3^{\text{prev}}$ | 50 | Limb 3 of current/previous accumulator | +| `QUOTIENT_LOW_BINARY_LIMBS` | $q_0$ | $q_1$ | 68 | Limbs 0 & 1 of quotient $\mathcal{Q}$ | +| `QUOTIENT_HIGH_BINARY_LIMBS` | $q_2$ | $q_3$ | 68, 52 | Limbs 2 & 3 of quotient $\mathcal{Q}$ | +| `RELATION_WIDE_LIMBS` | $c^{\text{lo}}$ | $c^{\text{hi}}$ | 84 | Carry/overflow from mod $2^{136}$ checks | + +**Key insight**: The accumulator columns demonstrate the shift mechanism: + +- Even row stores $a^{\text{curr}}$ (result of current computation) +- Odd row stores what will become $a^{\text{prev}}$ (input to next computation) +- Via shifts, even row $2i$ reads odd row $2i+1$ to get "previous" values + +#### 3. Range Constraint Microlimb Columns (64 columns) + +Each limb is further decomposed into **14-bit microlimbs** for range checking: + +| Column Group | Count | Decomposition | Range per Microlimb | +| ------------------------------------------- | ----- | -------------------------------- | ------------------- | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail (shifted by 4) | [0, 2¹⁴) each | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_*` | 4 | 6Γ—14-bit (84 bits total) | [0, 2¹⁴) each | + +**Tail microlimb**: The "\_TAIL" column contains the highest 14-bit microlimb multiplied by 4, providing a stricter constraint to ensure the total limb doesn't overflow its intended bit width. + +### Active Constraints by Row Type + +| Constraint | Active on Even Rows | Active on Odd Rows | +| ------------------------------------------ | ------------------- | ------------------ | +| Non-Native Field Relation (3 subrelations) | βœ“ | βœ— | +| Accumulator Transfer Relation | βœ— | βœ“ | +| Opcode Constraint | βœ“ | βœ“ | +| Range Constraints (Permutation) | βœ“ | βœ“ | +| Decomposition Relations | βœ“ | βœ“ | + +**Lagrange selectors**: + +- $L_{\text{even}}$: Equals 1 on even rows, 0 elsewhere +- $L_{\text{odd}}$: Equals 1 on odd rows, 0 elsewhere + +--- + +## Table of Contents + +1. [Limb Decomposition Structure](#limb-decomposition-structure) +2. [The Problem Statement](#the-problem-statement) +3. [Nomenclature and Notation](#nomenclature-and-notation) +4. [The Three Subrelations](#the-three-subrelations) +5. [Subrelation 1: Lower Mod 2¹³⁢ Check](#subrelation-1-lower-mod-2136-check) +6. [Subrelation 2: Higher Mod 2¹³⁢ Check](#subrelation-2-higher-mod-2136-check) +7. [Subrelation 3: Native Field Check](#subrelation-3-native-field-check) +8. [Soundness Argument](#soundness-argument) +9. [Complete Constraint System](#complete-constraint-system) + +--- + +## Limb Decomposition Structure + +### Why 68-bit Limbs? + +- Need to represent 254-bit values (elements of 𝔽q) +- Split into **4 limbs**: 68 + 68 + 68 + 50 = 254 bits +- 68 bits chosen for efficient range constraints (68 = 14 Γ— 4 + 12) + +### Complete Decomposition Table + +This table establishes **all notation** used in the relations: + +| Value | Native (𝔽q) | Binary Limbs | Native (𝔽r) | +| ------------------------------- | -------------------- | ------------------------------------------------------------------------------------ | --------------- | +| **Evaluation challenge** | +| $x$ | Evaluation point | $x_0, x_1, x_2, x_3$ | $x_4$ | +| **Batching challenges** | +| $v$ | Batching challenge | $v_0, v_1, v_2, v_3$ | $v_4$ | +| $v^2$ | v squared | $(v^2)_0, (v^2)_1, (v^2)_2, (v^2)_3$ | $(v^2)_4$ | +| $v^3$ | v cubed | $(v^3)_0, (v^3)_1, (v^3)_2, (v^3)_3$ | $(v^3)_4$ | +| $v^4$ | v to fourth | $(v^4)_0, (v^4)_1, (v^4)_2, (v^4)_3$ | $(v^4)_4$ | +| **Point coordinates (witness)** | +| $P_x$ | Point x-coordinate | $P_{x,0}^{\text{lo}}, P_{x,1}^{\text{lo}}, P_{x,0}^{\text{hi}}, P_{x,1}^{\text{hi}}$ | (reconstructed) | +| $P_y$ | Point y-coordinate | $P_{y,0}^{\text{lo}}, P_{y,1}^{\text{lo}}, P_{y,0}^{\text{hi}}, P_{y,1}^{\text{hi}}$ | (reconstructed) | +| **Z-values (witness, 128-bit)** | +| $z_1$ | 128-bit value | $z_{1,0}, z_{1,1}$ (only 2 limbs) | (reconstructed) | +| $z_2$ | 128-bit value | $z_{2,0}, z_{2,1}$ (only 2 limbs) | (reconstructed) | +| **Accumulator (witness)** | +| $a^{\text{prev}}$ | Previous accumulator | $a_0^{\text{prev}}, a_1^{\text{prev}}, a_2^{\text{prev}}, a_3^{\text{prev}}$ | (reconstructed) | +| $a^{\text{curr}}$ | Current accumulator | $a_0^{\text{curr}}, a_1^{\text{curr}}, a_2^{\text{curr}}, a_3^{\text{curr}}$ | (reconstructed) | +| **Quotient (witness)** | +| $\mathcal{Q}$ | Division quotient | $q_0, q_1, q_2, q_3$ | (reconstructed) | +| **Carries (witness)** | +| $c^{\text{lo}}$ | Lower carry | (single 84-bit value) | - | +| $c^{\text{hi}}$ | Higher carry | (single 84-bit value) | - | +| **Opcode (witness, small)** | +| $\texttt{op}$ | Operation code | (no decomposition, ≀ 8) | $\texttt{op}$ | + +### Reconstruction Formula (General) + +For a 254-bit value decomposed as $\ell_0, \ell_1, \ell_2, \ell_3$: + +$$\boxed{\text{Value} = \ell_0 + 2^{68} \cdot \ell_1 + 2^{136} \cdot \ell_2 + 2^{204} \cdot \ell_3}$$ + +**Specific reconstructions:** + +The coordinates $P_x$ and $P_y$ are reconstructed as: + +$$P_x = P_{x,0}^{\text{lo}} + 2^{68} \cdot P_{x,1}^{\text{lo}} + 2^{136} \cdot P_{x,0}^{\text{hi}} + 2^{204} \cdot P_{x,1}^{\text{hi}}$$ + +$$P_y = P_{y,0}^{\text{lo}} + 2^{68} \cdot P_{y,1}^{\text{lo}} + 2^{136} \cdot P_{y,0}^{\text{hi}} + 2^{204} \cdot P_{y,1}^{\text{hi}}$$ + +The scalars $z_1$ and $z_2$ (both 128-bit) are reconstructed as: + +$$z_1 = z_{1,0} + 2^{68} \cdot z_{1,1}$$ + +$$z_2 = z_{2,0} + 2^{68} \cdot z_{2,1}$$ + +The accumulators are reconstructed as: + +$$a^{\text{prev}} = a_0^{\text{prev}} + 2^{68} \cdot a_1^{\text{prev}} + 2^{136} \cdot a_2^{\text{prev}} + 2^{204} \cdot a_3^{\text{prev}}$$ + +$$a^{\text{curr}} = a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}}$$ + +The quotient $\mathcal{Q}$ is reconstructed as: + +$$\mathcal{Q} = q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3$$ + +--- + +## The Problem Statement + +### Field Moduli + +| Symbol | Value | Description | +| ------ | -------------------------------------------------------------------- | ------------------------------- | +| $q$ | `0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` | BN254 base field modulus (𝔽q) | +| $r$ | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽r) | + +**Key fact:** $q \neq r$, so we cannot directly compute in 𝔽q using 𝔽r arithmetic. + +### Goal + +Prove the following accumulation identity holds in $\mathbb{F}_q$: + +$$\boxed{a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}}$$ + +### Challenge + +We can only perform arithmetic in $\mathbb{F}_r$ (the scalar field), but we need to prove correctness in $\mathbb{F}_q$ (the base field). + +### Solution Approach + +Rewrite as an integer equation with quotient: + +$$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \mathcal{Q} \cdot q - a^{\text{curr}} = 0 \quad (\text{in integers})$$ + +**Key insight:** If this equation holds: + +1. **Modulo $2^{272}$** (via limb arithmetic in 𝔽r), AND +2. **Modulo $r$** (native 𝔽r computation), AND +3. All values are properly range-constrained + +Then it holds in integers (since $2^{272} \cdot r > 2^{514}$ > max possible value), which implies it holds modulo $q$. + +### Negative Prime Modulus + +We work with $-q \pmod{2^{272}}$ to avoid subtraction: + +$$\bar{q} := 2^{272} - q$$ + +Decomposed into limbs: + +$$\bar{q} = \bar{q}_0 + 2^{68} \cdot \bar{q}_1 + 2^{136} \cdot \bar{q}_2 + 2^{204} \cdot \bar{q}_3$$ + +Plus native field representation: $\bar{q}_4 = -q \pmod{r}$ + +--- + +## The Problem Statement + +### Goal + +Prove the following accumulation identity holds in 𝔽q: + +$$\boxed{a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}}$$ + +### Challenge + +We can only perform arithmetic in 𝔽r (the scalar field), but we need to prove correctness in 𝔽q (the base field). +Since $q \neq r$, so we cannot directly compute in 𝔽q using 𝔽r arithmetic. + +| Symbol | LaTeX | Value | Description | +| ------ | ----- | -------------------------------------------------------------------- | ------------------------------- | +| q | `q` | `0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` | BN254 base field modulus (𝔽q) | +| r | `r` | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽r) | + +### Solution Approach + +Rewrite as an integer equation with quotient: + +$$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \mathcal{Q} \cdot q - a^{\text{curr}} = 0 \quad (\text{in integers})$$ + +**Key insight:** If this equation holds: + +1. **Modulo 2²⁷²** (via limb arithmetic in 𝔽r), AND +2. **Modulo r** (native 𝔽r computation), AND +3. All values are properly range-constrained + +Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot r > 2^{514}$ > max possible value), which implies it holds modulo q. +See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. + +## Non-Native Field Relations + +The non-native field relation is enforced through **three separate subrelations**: + +| Subrelation | Purpose | Modulus | Limbs Checked | +| ----------- | --------------------- | --------- | ------------------------------------- | +| 1 | Lower mod 2²⁷² check | $2^{136}$ | Limbs 0, 1 | +| 2 | Higher mod 2²⁷² check | $2^{136}$ | Limbs 2, 3 (with carry from subrel 1) | +| 3 | Native field check | $r$ | Full native reconstruction | + +Together, these prove the relation holds in integers. + +--- + +## Subrelation 1: Lower Mod 2¹³⁢ Check + +### Goal + +Prove that when we compute the accumulation formula using limbs 0 and 1, the result is a multiple of $2^{136}$. + +### The Computation + +We compute the accumulation using: + +- Limb 0 terms (contribute at weight $2^0$) +- Limb 1 terms (contribute at weight $2^{68}$) + +The result should be: $\text{Result} = c^{\text{lo}} \cdot 2^{136}$ for some carry $c^{\text{lo}}$. + +### Limb 0 Contribution + +$$\boxed{T_0 := a_0^{\text{prev}} \cdot x_0 + \texttt{op} + P_{x,0}^{\text{lo}} \cdot v_0 + P_{y,0}^{\text{lo}} \cdot (v^2)_0 + z_{1,0} \cdot (v^3)_0 + z_{2,0} \cdot (v^4)_0 + q_0 \cdot \bar{q}_0 - a_0^{\text{curr}}}$$ + +**Expanded with all products:** + +| Term | Product | Weight | +| ----------------------------------- | ------------------------------------------------- | ------ | +| $a_0^{\text{prev}} \cdot x_0$ | Previous acc limb 0 Γ— evaluation challenge limb 0 | $2^0$ | +| $\texttt{op}$ | Operation code (small value ≀ 8) | $2^0$ | +| $P_{x,0}^{\text{lo}} \cdot v_0$ | P.x low limb 0 Γ— batching challenge limb 0 | $2^0$ | +| $P_{y,0}^{\text{lo}} \cdot (v^2)_0$ | P.y low limb 0 Γ— vΒ² limb 0 | $2^0$ | +| $z_{1,0} \cdot (v^3)_0$ | z₁ limb 0 Γ— vΒ³ limb 0 | $2^0$ | +| $z_{2,0} \cdot (v^4)_0$ | zβ‚‚ limb 0 Γ— v⁴ limb 0 | $2^0$ | +| $q_0 \cdot \bar{q}_0$ | Quotient limb 0 Γ— negative modulus limb 0 | $2^0$ | +| $-a_0^{\text{curr}}$ | Negative of current accumulator limb 0 | $2^0$ | + +### Limb 1 Contribution + +$$ +\boxed{\begin{align}T_1 := &\; a_1^{\text{prev}} \cdot x_0 + a_0^{\text{prev}} \cdot x_1 \\ +&+ P_{x,0}^{\text{lo}} \cdot v_1 + P_{x,1}^{\text{lo}} \cdot v_0 \\ +&+ P_{y,0}^{\text{lo}} \cdot (v^2)_1 + P_{y,1}^{\text{lo}} \cdot (v^2)_0 \\ +&+ z_{1,0} \cdot (v^3)_1 + z_{1,1} \cdot (v^3)_0 \\ +&+ z_{2,0} \cdot (v^4)_1 + z_{2,1} \cdot (v^4)_0 \\ +&+ q_0 \cdot \bar{q}_1 + q_1 \cdot \bar{q}_0 \\ +&- a_1^{\text{curr}} +\end{align}} +$$ + +**Expanded with all cross-products:** + +| Term | Product | Weight | +| ----------------------------------- | --------------------------------------- | -------- | +| $a_1^{\text{prev}} \cdot x_0$ | Prev acc limb 1 Γ— eval challenge limb 0 | $2^{68}$ | +| $a_0^{\text{prev}} \cdot x_1$ | Prev acc limb 0 Γ— eval challenge limb 1 | $2^{68}$ | +| $P_{x,0}^{\text{lo}} \cdot v_1$ | P.x low limb 0 Γ— batching limb 1 | $2^{68}$ | +| $P_{x,1}^{\text{lo}} \cdot v_0$ | P.x low limb 1 Γ— batching limb 0 | $2^{68}$ | +| $P_{y,0}^{\text{lo}} \cdot (v^2)_1$ | P.y low limb 0 Γ— vΒ² limb 1 | $2^{68}$ | +| $P_{y,1}^{\text{lo}} \cdot (v^2)_0$ | P.y low limb 1 Γ— vΒ² limb 0 | $2^{68}$ | +| $z_{1,0} \cdot (v^3)_1$ | z₁ limb 0 Γ— vΒ³ limb 1 | $2^{68}$ | +| $z_{1,1} \cdot (v^3)_0$ | z₁ limb 1 Γ— vΒ³ limb 0 | $2^{68}$ | +| $z_{2,0} \cdot (v^4)_1$ | zβ‚‚ limb 0 Γ— v⁴ limb 1 | $2^{68}$ | +| $z_{2,1} \cdot (v^4)_0$ | zβ‚‚ limb 1 Γ— v⁴ limb 0 | $2^{68}$ | +| $q_0 \cdot \bar{q}_1$ | Quotient limb 0 Γ— neg mod limb 1 | $2^{68}$ | +| $q_1 \cdot \bar{q}_0$ | Quotient limb 1 Γ— neg mod limb 0 | $2^{68}$ | +| $-a_1^{\text{curr}}$ | Negative of current acc limb 1 | $2^{68}$ | + +### Combined Subrelation 1 Formula + +$$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_0 + 2^{68} \cdot T_1 - 2^{136} \cdot c^{\text{lo}} \right) = 0}$$ + +**Interpretation:** + +- Compute $T_0$ (limb 0 contribution) +- Compute $T_1 \cdot 2^{68}$ (limb 1 contribution, shifted by 68 bits) +- Their sum should equal $c^{\text{lo}} \cdot 2^{136}$ +- If this holds, the lower 136 bits of the accumulation equation are correct + +**Active when:** + +- $L_{\text{even}} = 1$ (even rows in mini-circuit) +- $\texttt{op} \neq 0$ (not a no-op) + +--- + +## Subrelation 2: Higher Mod 2¹³⁢ Check + +### Goal + +Prove that when we compute the accumulation formula using limbs 2 and 3, plus the carry from subrelation 1, the result is a multiple of $2^{136}$. + +### The Computation + +We compute using: + +- The carry $c^{\text{lo}}$ from subrelation 1 +- Limb 2 terms (contribute at weight $2^{136}$) +- Limb 3 terms (contribute at weight $2^{204}$) + +The result should be: $\text{Result} = c^{\text{hi}} \cdot 2^{136}$ for some carry $c^{\text{hi}}$. + +### Limb 2 Contribution (with Carry) + +$$ +\boxed{\begin{align}T_2 := &\; c^{\text{lo}} \quad \text{(carry from subrelation 1)} \\ +&+ a_2^{\text{prev}} \cdot x_0 + a_1^{\text{prev}} \cdot x_1 + a_0^{\text{prev}} \cdot x_2 \\ +&+ P_{x,0}^{\text{hi}} \cdot v_0 + P_{x,1}^{\text{lo}} \cdot v_1 + P_{x,0}^{\text{lo}} \cdot v_2 \\ +&+ P_{y,0}^{\text{hi}} \cdot (v^2)_0 + P_{y,1}^{\text{lo}} \cdot (v^2)_1 + P_{y,0}^{\text{lo}} \cdot (v^2)_2 \\ +&+ z_{1,1} \cdot (v^3)_1 + z_{1,0} \cdot (v^3)_2 \\ +&+ z_{2,1} \cdot (v^4)_1 + z_{2,0} \cdot (v^4)_2 \\ +&+ q_2 \cdot \bar{q}_0 + q_1 \cdot \bar{q}_1 + q_0 \cdot \bar{q}_2 \\ +&- a_2^{\text{curr}} +\end{align}} +$$ + +**Key cross-products at weight $2^{136}$:** + +| Term | Product | Description | +| ------------------------------- | -------------------------- | ---------------------------------- | +| $c^{\text{lo}}$ | Carry | From lower 136-bit computation | +| $a_2^{\text{prev}} \cdot x_0$ | Acc limb 2 Γ— eval limb 0 | Direct limb 2 term | +| $a_1^{\text{prev}} \cdot x_1$ | Acc limb 1 Γ— eval limb 1 | Cross-product $(1,1)$ | +| $a_0^{\text{prev}} \cdot x_2$ | Acc limb 0 Γ— eval limb 2 | Cross-product $(0,2)$ | +| $P_{x,0}^{\text{hi}} \cdot v_0$ | P.x high limb 0 Γ— v limb 0 | High limbs start here | +| $P_{x,1}^{\text{lo}} \cdot v_1$ | P.x low limb 1 Γ— v limb 1 | Cross-product | +| $P_{x,0}^{\text{lo}} \cdot v_2$ | P.x low limb 0 Γ— v limb 2 | Cross-product | +| ... | (similar for P.y, z₁, zβ‚‚) | All combinations summing to limb 2 | + +### Limb 3 Contribution + +$$ +\boxed{\begin{align}T_3 := &\; a_3^{\text{prev}} \cdot x_0 + a_2^{\text{prev}} \cdot x_1 + a_1^{\text{prev}} \cdot x_2 + a_0^{\text{prev}} \cdot x_3 \\ +&+ P_{x,1}^{\text{hi}} \cdot v_0 + P_{x,0}^{\text{hi}} \cdot v_1 + P_{x,1}^{\text{lo}} \cdot v_2 + P_{x,0}^{\text{lo}} \cdot v_3 \\ +&+ P_{y,1}^{\text{hi}} \cdot (v^2)_0 + P_{y,0}^{\text{hi}} \cdot (v^2)_1 + P_{y,1}^{\text{lo}} \cdot (v^2)_2 + P_{y,0}^{\text{lo}} \cdot (v^2)_3 \\ +&+ z_{1,1} \cdot (v^3)_2 + z_{1,0} \cdot (v^3)_3 \\ +&+ z_{2,1} \cdot (v^4)_2 + z_{2,0} \cdot (v^4)_3 \\ +&+ q_3 \cdot \bar{q}_0 + q_2 \cdot \bar{q}_1 + q_1 \cdot \bar{q}_2 + q_0 \cdot \bar{q}_3 \\ +&- a_3^{\text{curr}} +\end{align}} +$$ + +**Key cross-products at weight $2^{204}$:** + +| Term | Product | Description | +| ----------------------------- | ------------------------ | ---------------------------------- | +| $a_3^{\text{prev}} \cdot x_0$ | Acc limb 3 Γ— eval limb 0 | Direct limb 3 term | +| $a_2^{\text{prev}} \cdot x_1$ | Acc limb 2 Γ— eval limb 1 | Cross-product $(2,1)$ | +| $a_1^{\text{prev}} \cdot x_2$ | Acc limb 1 Γ— eval limb 2 | Cross-product $(1,2)$ | +| $a_0^{\text{prev}} \cdot x_3$ | Acc limb 0 Γ— eval limb 3 | Cross-product $(0,3)$ | +| ... | (all 4-limb products) | All combinations summing to limb 3 | + +### Combined Subrelation 2 Formula + +$$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_2 + 2^{68} \cdot T_3 - 2^{136} \cdot c^{\text{hi}} \right) = 0}$$ + +**Interpretation:** + +- Start with carry $c^{\text{lo}}$ from subrelation 1 +- Add limb 2 contribution $T_2$ +- Add limb 3 contribution $T_3 \cdot 2^{68}$ +- Result should be $c^{\text{hi}} \cdot 2^{136}$ +- If this holds, the higher 136 bits are correct + +**Together with Subrelation 1:** We've proven the relation holds modulo $2^{272}$. + +--- + +## Subrelation 3: Native Field Check + +### Goal + +Prove the accumulation formula holds when computed directly in 𝔽r (the native field). + +### Reconstruction + +First, reconstruct all values from their limbs: + +$$ +\begin{align} +\tilde{P}_x &= P_{x,0}^{\text{lo}} + 2^{68} \cdot P_{x,1}^{\text{lo}} + 2^{136} \cdot P_{x,0}^{\text{hi}} + 2^{204} \cdot P_{x,1}^{\text{hi}} \pmod{r} \\ +\tilde{P}_y &= P_{y,0}^{\text{lo}} + 2^{68} \cdot P_{y,1}^{\text{lo}} + 2^{136} \cdot P_{y,0}^{\text{hi}} + 2^{204} \cdot P_{y,1}^{\text{hi}} \pmod{r} \\ +\tilde{z}_1 &= z_{1,0} + 2^{68} \cdot z_{1,1} \pmod{r} \\ +\tilde{z}_2 &= z_{2,0} + 2^{68} \cdot z_{2,1} \pmod{r} \\ +\tilde{a}^{\text{prev}} &= a_0^{\text{prev}} + 2^{68} \cdot a_1^{\text{prev}} + 2^{136} \cdot a_2^{\text{prev}} + 2^{204} \cdot a_3^{\text{prev}} \pmod{r} \\ +\tilde{a}^{\text{curr}} &= a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}} \pmod{r} \\ +\tilde{\mathcal{Q}} &= q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3 \pmod{r} +\end{align} +$$ + +**Note:** The tilde $\tilde{}$ indicates these are native field reconstructions in 𝔽r, not the original 𝔽q values. + +### Subrelation 3 Formula + +$$ +\boxed{\begin{align}L_{\text{even}} \cdot \texttt{op} \cdot \Big( &\tilde{a}^{\text{prev}} \cdot x_4 \\ +&+ \texttt{op} \\ +&+ \tilde{P}_x \cdot v_4 \\ +&+ \tilde{P}_y \cdot (v^2)_4 \\ +&+ \tilde{z}_1 \cdot (v^3)_4 \\ +&+ \tilde{z}_2 \cdot (v^4)_4 \\ +&+ \tilde{\mathcal{Q}} \cdot \bar{q}_4 \\ +&- \tilde{a}^{\text{curr}} \Big) = 0 +\end{align}} +$$ + +Where: + +- All arithmetic is performed in $\mathbb{F}_{r}$ +- $x_4, v_4, (v^2)_4, (v^3)_4, (v^4)_4$ are the native field representations of the challenges +- $\bar{q}_4 = -q \pmod{r}$ + +**Interpretation:** + +- Reconstruct all limbed values back to native $\mathbb{F}_{r}$ elements +- Compute the accumulation formula directly in $\mathbb{F}_{r}$ +- If subrelations 1 and 2 prove it holds mod $2^{272}$, and subrelation 3 proves it holds mod $r$, then it holds in integers + +--- + +## Soundness Argument + +### The Two-Moduli Approach + +We prove the accumulation identity holds in three ways: + +1. **Modulo $2^{136}$ (lower):** Subrelation 1 +2. **Modulo $2^{136}$ (higher):** Subrelation 2, which together with 1 gives mod $2^{272}$ +3. **Modulo $r$:** Subrelation 3 + +### Chinese Remainder Theorem Intuition + +If an equation holds modulo $M_1$ and modulo $M_2$ where $\gcd(M_1, M_2) = 1$, then it holds modulo $M_1 \cdot M_2$. + +**Application:** + +- $\gcd(2^{272}, r) = 1$ (since $r$ is odd prime) +- If equation holds mod $2^{272}$ AND mod $r$ +- Then it holds mod $2^{272} \cdot r$ + +### Maximum Value Bound + +**Maximum possible value of LHS:** + +$$\text{Max} = \max(a^{\text{prev}}) \cdot \max(x) + \text{sum of other products}$$ + +Each factor is at most $2^{254}$, so: + +$$\text{Max} < 2^{254} \cdot 2^{254} + 4 \cdot 2^{254} \cdot 2^{254} < 5 \cdot 2^{508} < 2^{511}$$ + +**Key inequality:** +$$2^{272} \cdot r > 2^{272} \cdot 2^{254} = 2^{526} > 2^{511} > \text{Max}$$ + +**Conclusion:** + +- If the equation holds mod $2^{272} \cdot r$ +- AND all values are bounded as above +- THEN the equation holds in integers (no wraparound possible) +- THEREFORE it holds modulo any smaller modulus, including $q$ + +### Range Constraints are Critical + +The soundness argument **requires** that all limbs are properly range-constrained: + +| Limb | Required Range | Enforced By | +| ------------------------------------------------ | ------------------------------ | -------------------------------------- | +| $P_{x,i}^{\text{lo}}, P_{x,i}^{\text{hi}}$ (i=0) | $[0, 2^{68})$ | Decomposition + Delta Range Constraint | +| $P_{x,1}^{\text{hi}}$ | $[0, 2^{50})$ | Stricter constraint via tail microlimb | +| All other 68-bit limbs | $[0, 2^{68})$ | Permutation argument | +| Quotient limbs | $[0, 2^{68})$ or $[0, 2^{52})$ | Permutation argument | +| Carries $c^{\text{lo}}, c^{\text{hi}}$ | $[0, 2^{84})$ | Relation wide limb range constraints | + +**If any limb is out of range**, the maximum value bound is violated and soundness breaks. + +--- + +## Complete Constraint System + +### Subrelation 1: Lower 136 Bits + +$$ +\boxed{\begin{align} +&L_{\text{even}} \cdot \texttt{op} \cdot \Bigg[ \\ +&\quad \underbrace{a_0^{\text{prev}} \cdot x_0 + \texttt{op} + \sum_{j} \text{(limb 0 products)}_j - a_0^{\text{curr}}}_{\text{Limb 0: } T_0} \\ +&\quad + 2^{68} \cdot \underbrace{\sum_{i,j: i+j=1} \text{(limb } i \text{ Γ— limb } j \text{ products)} - a_1^{\text{curr}}}_{\text{Limb 1: } T_1} \\ +&\quad - 2^{136} \cdot c^{\text{lo}} \\ +&\Bigg] = 0 +\end{align}} +$$ + +### Subrelation 2: Higher 136 Bits + +$$ +\boxed{\begin{align} +&L_{\text{even}} \cdot \texttt{op} \cdot \Bigg[ \\ +&\quad \underbrace{c^{\text{lo}} + \sum_{i,j: i+j=2} \text{(limb } i \text{ Γ— limb } j \text{ products)} - a_2^{\text{curr}}}_{\text{Limb 2: } T_2} \\ +&\quad + 2^{68} \cdot \underbrace{\sum_{i,j: i+j=3} \text{(limb } i \text{ Γ— limb } j \text{ products)} - a_3^{\text{curr}}}_{\text{Limb 3: } T_3} \\ +&\quad - 2^{136} \cdot c^{\text{hi}} \\ +&\Bigg] = 0 +\end{align}} +$$ + +### Subrelation 3: Native Field + +$$ +\boxed{\begin{align} +&L_{\text{even}} \cdot \texttt{op} \cdot \Bigg[ \\ +&\quad \tilde{a}^{\text{prev}} \cdot x_4 + \texttt{op} + \tilde{P}_x \cdot v_4 + \tilde{P}_y \cdot (v^2)_4 \\ +&\quad + \tilde{z}_1 \cdot (v^3)_4 + \tilde{z}_2 \cdot (v^4)_4 + \tilde{\mathcal{Q}} \cdot \bar{q}_4 - \tilde{a}^{\text{curr}} \\ +&\Bigg] = 0 +\end{align}} +$$ + +Where all $\tilde{\cdot}$ values are reconstructed from limbs in $\mathbb{F}_{r}$. + +### Combined Guarantee + +**If all three subrelations hold**, then: + +$$a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ + +is **provably correct in $\mathbb{F}_{q}$**, despite being computed entirely in $\mathbb{F}_{r}$. + +--- + +**This completes the mathematical specification of the Non-Native Field Relation.** From 6c0421dc7dd029f91f748db48c3f212197fe461c Mon Sep 17 00:00:00 2001 From: suyash67 Date: Mon, 8 Dec 2025 13:01:35 +0000 Subject: [PATCH 03/29] more comments in nnf relation. --- ...nslator_non_native_field_relation_impl.hpp | 59 ++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp index 1a09fde34f1f..b682b17277fb 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp @@ -11,6 +11,7 @@ namespace bb { /** * @brief Expression for the computation of Translator accumulator in integers through 68-bit limbs and * native field (prime) limb + * * @details This relation is a part of system of relations that enforce a formula in non-native field (base field of * bn254 curve Fp (p - modulus of Fp)). We are trying to compute: * @@ -98,34 +99,42 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati -FF(curve::BN254::BaseField::modulus) }; + // Limbs of evaluation challenge x const auto& evaluation_input_x_0 = params.evaluation_input_x[0]; const auto& evaluation_input_x_1 = params.evaluation_input_x[1]; const auto& evaluation_input_x_2 = params.evaluation_input_x[2]; const auto& evaluation_input_x_3 = params.evaluation_input_x[3]; const auto& evaluation_input_x_4 = params.evaluation_input_x[4]; - // for j < 4, v_i_j is the j-th limb of v^{1+i} - // v_i_4 is v^{1+i} in the native field + + // Limbs of batching challenge v const auto& v_0_0 = params.batching_challenge_v[0][0]; const auto& v_0_1 = params.batching_challenge_v[0][1]; const auto& v_0_2 = params.batching_challenge_v[0][2]; const auto& v_0_3 = params.batching_challenge_v[0][3]; const auto& v_0_4 = params.batching_challenge_v[0][4]; + + // Limbs of batching challenge vΒ² const auto& v_1_0 = params.batching_challenge_v[1][0]; const auto& v_1_1 = params.batching_challenge_v[1][1]; const auto& v_1_2 = params.batching_challenge_v[1][2]; const auto& v_1_3 = params.batching_challenge_v[1][3]; const auto& v_1_4 = params.batching_challenge_v[1][4]; + + // Limbs of batching challenge vΒ³ const auto& v_2_0 = params.batching_challenge_v[2][0]; const auto& v_2_1 = params.batching_challenge_v[2][1]; const auto& v_2_2 = params.batching_challenge_v[2][2]; const auto& v_2_3 = params.batching_challenge_v[2][3]; const auto& v_2_4 = params.batching_challenge_v[2][4]; + + // Limbs of batching challenge v⁴ const auto& v_3_0 = params.batching_challenge_v[3][0]; const auto& v_3_1 = params.batching_challenge_v[3][1]; const auto& v_3_2 = params.batching_challenge_v[3][2]; const auto& v_3_3 = params.batching_challenge_v[3][3]; const auto& v_3_4 = params.batching_challenge_v[3][4]; + // Fetch witness values const auto& op = View(in.op); const auto& p_x_low_limbs = View(in.p_x_low_limbs); const auto& p_y_low_limbs = View(in.p_y_low_limbs); @@ -155,9 +164,16 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati const auto& relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); const auto& lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - // Contribution (1) Computing the mod 2²⁷² relation over lower 136 bits + /** + * Contribution (1): Subrelation 1 - Lower Mod 2¹³⁢ Check + * + * Proves that the accumulation formula holds for the lower 136 bits (limbs 0 and 1). + * Computes: Tβ‚€ + 2⁢⁸·T₁ - 2¹³⁢·c_lo = 0 + * where Tβ‚€ and T₁ are linear combinations of limb-0 and limb-1 products respectively, + * and c_lo is the carry to the higher 136 bits. + */ // clang-format off - // the index-0 limb + // Tβ‚€: Limb 0 contribution (all products contributing at weight 2⁰) auto tmp = accumulators_binary_limbs_0_shift * evaluation_input_x_0 + op + p_x_low_limbs * v_0_0 @@ -167,7 +183,7 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0; - // the index-1 limb + // T₁: Limb 1 contribution (all cross-products contributing at weight 2⁢⁸) tmp += (accumulators_binary_limbs_1_shift * evaluation_input_x_0 + accumulators_binary_limbs_0_shift * evaluation_input_x_1 + p_x_low_limbs * v_0_1 @@ -183,16 +199,23 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati - accumulators_binary_limbs_1) * shift ; // clang-format on - // subtract large value; vanishing shows the desired relation holds on low 136-bit limb + // Subtract 2¹³⁢·c_lo: if the result is zero, lower 136 bits are correct tmp -= relation_wide_limbs * shiftx2; tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<0>(accumulators) += tmp; - // Contribution (2) Computing the 2²⁷² relation over higher 136 bits - // why declare another temporary? + /** + * Contribution (2): Subrelation 2 - Higher Mod 2¹³⁢ Check + * + * Proves that the accumulation formula holds for the higher 136 bits (limbs 2 and 3). + * Computes: Tβ‚‚ + 2⁢⁸·T₃ - 2¹³⁢·c_hi = 0 + * where Tβ‚‚ includes the carry c_lo from subrelation 1, T₃ contains limb-3 products, + * and c_hi is the overflow carry (should be range-constrained to ensure soundness). + * Together with Subrelation 1, this proves the relation holds mod 2²⁷². + */ // clang-format off - // the index-2 limb, with a carry from the previous calculation + // Tβ‚‚: Limb 2 contribution (with carry from lower 136 bits) tmp = relation_wide_limbs + accumulators_binary_limbs_2_shift * evaluation_input_x_0 + accumulators_binary_limbs_1_shift * evaluation_input_x_1 @@ -212,7 +235,7 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] - accumulators_binary_limbs_2; - // the index-2 limb + // T₃: Limb 3 contribution (all cross-products contributing at weight 2²⁰⁴) tmp += (accumulators_binary_limbs_3_shift * evaluation_input_x_0 + accumulators_binary_limbs_2_shift * evaluation_input_x_1 + accumulators_binary_limbs_1_shift * evaluation_input_x_2 @@ -236,19 +259,20 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati - accumulators_binary_limbs_3) * shift; // clang-format on - // subtract large value; vanishing shows the desired relation holds on high 136-bit limb + // Subtract 2¹³⁢·c_hi: if the result is zero, higher 136 bits are correct tmp -= relation_wide_limbs_shift * shiftx2; tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<1>(accumulators) += tmp; + // Helper functions to reconstruct field elements from limbs const auto reconstruct_from_two = [](const auto& l0, const auto& l1) { return l0 + l1 * shift; }; const auto reconstruct_from_four = [](const auto& l0, const auto& l1, const auto& l2, const auto& l3) { return l0 + l1 * shift + l2 * shiftx2 + l3 * shiftx3; }; - // Reconstructing native versions of values + // Reconstruct native 𝔽ᡣ representations from binary limbs auto reconstructed_p_x = reconstruct_from_four(p_x_low_limbs, p_x_low_limbs_shift, p_x_high_limbs, p_x_high_limbs_shift); auto reconstructed_p_y = @@ -268,9 +292,16 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati quotient_high_binary_limbs, quotient_high_binary_limbs_shift); - // Contribution (3). Evaluating integer relation over native field + /** + * Contribution (3): Subrelation 3 - Native Field Check + * + * Proves the accumulation formula holds when computed directly in 𝔽ᡣ. + * Uses reconstructed native field representations (tilde notation in docs). + * Combined with mod 2²⁷² checks (Subrelations 1 & 2), this proves the relation + * holds in integers via Chinese Remainder Theorem, which implies it holds mod q. + */ // clang-format off - // the native limb index is 4 + // Compute accumulation formula using native 𝔽ᡣ arithmetic (limb index 4) tmp = reconstructed_previous_accumulator * evaluation_input_x_4 + op + reconstructed_p_x * v_0_4 From 8b6b5ee17ff93e6ea953e6928a6326150c85aa5d Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 9 Dec 2025 08:45:38 +0000 Subject: [PATCH 04/29] chore: change names. --- TRANSLATOR_NON_NATIVE_FIELD_MATH.md | 186 +++++++---------- ...nslator_non_native_field_relation_impl.hpp | 187 +++++++++--------- noir/noir-repo | 2 +- 3 files changed, 168 insertions(+), 207 deletions(-) diff --git a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md index 7609e37cde30..e5a51b977b51 100644 --- a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md +++ b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md @@ -2,7 +2,7 @@ ## Document Purpose -This document provides a rigorous mathematical treatment of the **Non-Native Field Relation** in the Translator circuit, using consistent LaTeX nomenclature throughout. This is the core relation that enables computation in 𝔽q (BN254 base field) using only 𝔽r (BN254 scalar field) arithmetic. +This document provides a rigorous mathematical treatment of the **Non-Native Field Relation** in the Translator circuit, using consistent LaTeX nomenclature throughout. This is the core relation that enables computation in 𝔽q (BN254 base field) using only 𝔽p (BN254 scalar field) arithmetic. --- @@ -127,7 +127,7 @@ Each limb is further decomposed into **14-bit microlimbs** for range checking: This table establishes **all notation** used in the relations: -| Value | Native (𝔽q) | Binary Limbs | Native (𝔽r) | +| Value | Native (𝔽q) | Binary Limbs | Native (𝔽p) | | ------------------------------- | -------------------- | ------------------------------------------------------------------------------------ | --------------- | | **Evaluation challenge** | | $x$ | Evaluation point | $x_0, x_1, x_2, x_3$ | $x_4$ | @@ -192,9 +192,9 @@ $$\mathcal{Q} = q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3$$ | Symbol | Value | Description | | ------ | -------------------------------------------------------------------- | ------------------------------- | | $q$ | `0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` | BN254 base field modulus (𝔽q) | -| $r$ | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽r) | +| $p$ | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽p) | -**Key fact:** $q \neq r$, so we cannot directly compute in 𝔽q using 𝔽r arithmetic. +**Key fact:** $q \neq p$, so we cannot directly compute in 𝔽q using 𝔽p arithmetic. ### Goal @@ -204,7 +204,7 @@ $$\boxed{a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + ### Challenge -We can only perform arithmetic in $\mathbb{F}_r$ (the scalar field), but we need to prove correctness in $\mathbb{F}_q$ (the base field). +We can only perform arithmetic in $\mathbb{F}_p$ (the scalar field), but we need to prove correctness in $\mathbb{F}_q$ (the base field). ### Solution Approach @@ -214,11 +214,11 @@ $$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdo **Key insight:** If this equation holds: -1. **Modulo $2^{272}$** (via limb arithmetic in 𝔽r), AND -2. **Modulo $r$** (native 𝔽r computation), AND +1. **Modulo $2^{272}$** (via limb arithmetic in 𝔽p), AND +2. **Modulo $p$** (native 𝔽p computation), AND 3. All values are properly range-constrained -Then it holds in integers (since $2^{272} \cdot r > 2^{514}$ > max possible value), which implies it holds modulo $q$. +Then it holds in integers (since $2^{272} \cdot p > 2^{514}$ > max possible value), which implies it holds modulo $q$. ### Negative Prime Modulus @@ -230,7 +230,7 @@ Decomposed into limbs: $$\bar{q} = \bar{q}_0 + 2^{68} \cdot \bar{q}_1 + 2^{136} \cdot \bar{q}_2 + 2^{204} \cdot \bar{q}_3$$ -Plus native field representation: $\bar{q}_4 = -q \pmod{r}$ +Plus native field representation: $\bar{q}_4 = -q \pmod{p}$ --- @@ -244,13 +244,13 @@ $$\boxed{a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + ### Challenge -We can only perform arithmetic in 𝔽r (the scalar field), but we need to prove correctness in 𝔽q (the base field). -Since $q \neq r$, so we cannot directly compute in 𝔽q using 𝔽r arithmetic. +We can only perform arithmetic in 𝔽p (the scalar field), but we need to prove correctness in 𝔽q (the base field). +Since $q \neq p$, so we cannot directly compute in 𝔽q using 𝔽p arithmetic. | Symbol | LaTeX | Value | Description | | ------ | ----- | -------------------------------------------------------------------- | ------------------------------- | | q | `q` | `0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` | BN254 base field modulus (𝔽q) | -| r | `r` | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽r) | +| p | `p` | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽p) | ### Solution Approach @@ -260,11 +260,11 @@ $$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdo **Key insight:** If this equation holds: -1. **Modulo 2²⁷²** (via limb arithmetic in 𝔽r), AND -2. **Modulo r** (native 𝔽r computation), AND +1. **Modulo 2²⁷²** (via limb arithmetic in 𝔽p), AND +2. **Modulo p** (native 𝔽p computation), AND 3. All values are properly range-constrained -Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot r > 2^{514}$ > max possible value), which implies it holds modulo q. +Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot p > 2^{514}$ > max possible value), which implies it holds modulo q. See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. ## Non-Native Field Relations @@ -275,7 +275,7 @@ The non-native field relation is enforced through **three separate subrelations* | ----------- | --------------------- | --------- | ------------------------------------- | | 1 | Lower mod 2²⁷² check | $2^{136}$ | Limbs 0, 1 | | 2 | Higher mod 2²⁷² check | $2^{136}$ | Limbs 2, 3 (with carry from subrel 1) | -| 3 | Native field check | $r$ | Full native reconstruction | +| 3 | Native field check | $p$ | Full native reconstruction | Together, these prove the relation holds in integers. @@ -296,55 +296,38 @@ We compute the accumulation using: The result should be: $\text{Result} = c^{\text{lo}} \cdot 2^{136}$ for some carry $c^{\text{lo}}$. -### Limb 0 Contribution +The limb 0 contribution is: -$$\boxed{T_0 := a_0^{\text{prev}} \cdot x_0 + \texttt{op} + P_{x,0}^{\text{lo}} \cdot v_0 + P_{y,0}^{\text{lo}} \cdot (v^2)_0 + z_{1,0} \cdot (v^3)_0 + z_{2,0} \cdot (v^4)_0 + q_0 \cdot \bar{q}_0 - a_0^{\text{curr}}}$$ - -**Expanded with all products:** - -| Term | Product | Weight | -| ----------------------------------- | ------------------------------------------------- | ------ | -| $a_0^{\text{prev}} \cdot x_0$ | Previous acc limb 0 Γ— evaluation challenge limb 0 | $2^0$ | -| $\texttt{op}$ | Operation code (small value ≀ 8) | $2^0$ | -| $P_{x,0}^{\text{lo}} \cdot v_0$ | P.x low limb 0 Γ— batching challenge limb 0 | $2^0$ | -| $P_{y,0}^{\text{lo}} \cdot (v^2)_0$ | P.y low limb 0 Γ— vΒ² limb 0 | $2^0$ | -| $z_{1,0} \cdot (v^3)_0$ | z₁ limb 0 Γ— vΒ³ limb 0 | $2^0$ | -| $z_{2,0} \cdot (v^4)_0$ | zβ‚‚ limb 0 Γ— v⁴ limb 0 | $2^0$ | -| $q_0 \cdot \bar{q}_0$ | Quotient limb 0 Γ— negative modulus limb 0 | $2^0$ | -| $-a_0^{\text{curr}}$ | Negative of current accumulator limb 0 | $2^0$ | +$$ +\boxed{ + \begin{align*} + T_0 := &\; a_0^{\text{prev}} \cdot x_0 & \\ + &+ \texttt{op} \\ + &+ P_{x,0}^{\text{lo}} \cdot v_0 \\ + &+ P_{y,0}^{\text{lo}} \cdot (v^2)_0 \\ + &+ z_{1,0} \cdot (v^3)_0 \\ + &+ z_{2,0} \cdot (v^4)_0 \\ + &+ q_0 \cdot \bar{q}_0 \\ + &- a_0^{\text{curr}} + \end{align*} +} +$$ -### Limb 1 Contribution +The limb 1 contribution is: $$ -\boxed{\begin{align}T_1 := &\; a_1^{\text{prev}} \cdot x_0 + a_0^{\text{prev}} \cdot x_1 \\ +\boxed{\begin{align*} +T_1 := &\; a_1^{\text{prev}} \cdot x_0 + a_0^{\text{prev}} \cdot x_1 & \\ &+ P_{x,0}^{\text{lo}} \cdot v_1 + P_{x,1}^{\text{lo}} \cdot v_0 \\ &+ P_{y,0}^{\text{lo}} \cdot (v^2)_1 + P_{y,1}^{\text{lo}} \cdot (v^2)_0 \\ &+ z_{1,0} \cdot (v^3)_1 + z_{1,1} \cdot (v^3)_0 \\ &+ z_{2,0} \cdot (v^4)_1 + z_{2,1} \cdot (v^4)_0 \\ &+ q_0 \cdot \bar{q}_1 + q_1 \cdot \bar{q}_0 \\ &- a_1^{\text{curr}} -\end{align}} +\end{align*}} $$ -**Expanded with all cross-products:** - -| Term | Product | Weight | -| ----------------------------------- | --------------------------------------- | -------- | -| $a_1^{\text{prev}} \cdot x_0$ | Prev acc limb 1 Γ— eval challenge limb 0 | $2^{68}$ | -| $a_0^{\text{prev}} \cdot x_1$ | Prev acc limb 0 Γ— eval challenge limb 1 | $2^{68}$ | -| $P_{x,0}^{\text{lo}} \cdot v_1$ | P.x low limb 0 Γ— batching limb 1 | $2^{68}$ | -| $P_{x,1}^{\text{lo}} \cdot v_0$ | P.x low limb 1 Γ— batching limb 0 | $2^{68}$ | -| $P_{y,0}^{\text{lo}} \cdot (v^2)_1$ | P.y low limb 0 Γ— vΒ² limb 1 | $2^{68}$ | -| $P_{y,1}^{\text{lo}} \cdot (v^2)_0$ | P.y low limb 1 Γ— vΒ² limb 0 | $2^{68}$ | -| $z_{1,0} \cdot (v^3)_1$ | z₁ limb 0 Γ— vΒ³ limb 1 | $2^{68}$ | -| $z_{1,1} \cdot (v^3)_0$ | z₁ limb 1 Γ— vΒ³ limb 0 | $2^{68}$ | -| $z_{2,0} \cdot (v^4)_1$ | zβ‚‚ limb 0 Γ— v⁴ limb 1 | $2^{68}$ | -| $z_{2,1} \cdot (v^4)_0$ | zβ‚‚ limb 1 Γ— v⁴ limb 0 | $2^{68}$ | -| $q_0 \cdot \bar{q}_1$ | Quotient limb 0 Γ— neg mod limb 1 | $2^{68}$ | -| $q_1 \cdot \bar{q}_0$ | Quotient limb 1 Γ— neg mod limb 0 | $2^{68}$ | -| $-a_1^{\text{curr}}$ | Negative of current acc limb 1 | $2^{68}$ | - -### Combined Subrelation 1 Formula +Thus, the combined subrelation is: $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_0 + 2^{68} \cdot T_1 - 2^{136} \cdot c^{\text{lo}} \right) = 0}$$ @@ -378,10 +361,11 @@ We compute using: The result should be: $\text{Result} = c^{\text{hi}} \cdot 2^{136}$ for some carry $c^{\text{hi}}$. -### Limb 2 Contribution (with Carry) +The limb 2 contribution (with carry) is: $$ -\boxed{\begin{align}T_2 := &\; c^{\text{lo}} \quad \text{(carry from subrelation 1)} \\ +\boxed{\begin{align*} +T_2 := &\; c^{\text{lo}} \quad \text{(carry from subrelation 1)} & \\ &+ a_2^{\text{prev}} \cdot x_0 + a_1^{\text{prev}} \cdot x_1 + a_0^{\text{prev}} \cdot x_2 \\ &+ P_{x,0}^{\text{hi}} \cdot v_0 + P_{x,1}^{\text{lo}} \cdot v_1 + P_{x,0}^{\text{lo}} \cdot v_2 \\ &+ P_{y,0}^{\text{hi}} \cdot (v^2)_0 + P_{y,1}^{\text{lo}} \cdot (v^2)_1 + P_{y,0}^{\text{lo}} \cdot (v^2)_2 \\ @@ -389,46 +373,24 @@ $$ &+ z_{2,1} \cdot (v^4)_1 + z_{2,0} \cdot (v^4)_2 \\ &+ q_2 \cdot \bar{q}_0 + q_1 \cdot \bar{q}_1 + q_0 \cdot \bar{q}_2 \\ &- a_2^{\text{curr}} -\end{align}} +\end{align*}} $$ -**Key cross-products at weight $2^{136}$:** - -| Term | Product | Description | -| ------------------------------- | -------------------------- | ---------------------------------- | -| $c^{\text{lo}}$ | Carry | From lower 136-bit computation | -| $a_2^{\text{prev}} \cdot x_0$ | Acc limb 2 Γ— eval limb 0 | Direct limb 2 term | -| $a_1^{\text{prev}} \cdot x_1$ | Acc limb 1 Γ— eval limb 1 | Cross-product $(1,1)$ | -| $a_0^{\text{prev}} \cdot x_2$ | Acc limb 0 Γ— eval limb 2 | Cross-product $(0,2)$ | -| $P_{x,0}^{\text{hi}} \cdot v_0$ | P.x high limb 0 Γ— v limb 0 | High limbs start here | -| $P_{x,1}^{\text{lo}} \cdot v_1$ | P.x low limb 1 Γ— v limb 1 | Cross-product | -| $P_{x,0}^{\text{lo}} \cdot v_2$ | P.x low limb 0 Γ— v limb 2 | Cross-product | -| ... | (similar for P.y, z₁, zβ‚‚) | All combinations summing to limb 2 | - -### Limb 3 Contribution +The limb 3 contribution is: $$ -\boxed{\begin{align}T_3 := &\; a_3^{\text{prev}} \cdot x_0 + a_2^{\text{prev}} \cdot x_1 + a_1^{\text{prev}} \cdot x_2 + a_0^{\text{prev}} \cdot x_3 \\ +\boxed{\begin{align*} +T_3 := &\; a_3^{\text{prev}} \cdot x_0 + a_2^{\text{prev}} \cdot x_1 + a_1^{\text{prev}} \cdot x_2 + a_0^{\text{prev}} \cdot x_3 & \\ &+ P_{x,1}^{\text{hi}} \cdot v_0 + P_{x,0}^{\text{hi}} \cdot v_1 + P_{x,1}^{\text{lo}} \cdot v_2 + P_{x,0}^{\text{lo}} \cdot v_3 \\ &+ P_{y,1}^{\text{hi}} \cdot (v^2)_0 + P_{y,0}^{\text{hi}} \cdot (v^2)_1 + P_{y,1}^{\text{lo}} \cdot (v^2)_2 + P_{y,0}^{\text{lo}} \cdot (v^2)_3 \\ &+ z_{1,1} \cdot (v^3)_2 + z_{1,0} \cdot (v^3)_3 \\ &+ z_{2,1} \cdot (v^4)_2 + z_{2,0} \cdot (v^4)_3 \\ &+ q_3 \cdot \bar{q}_0 + q_2 \cdot \bar{q}_1 + q_1 \cdot \bar{q}_2 + q_0 \cdot \bar{q}_3 \\ &- a_3^{\text{curr}} -\end{align}} +\end{align*}} $$ -**Key cross-products at weight $2^{204}$:** - -| Term | Product | Description | -| ----------------------------- | ------------------------ | ---------------------------------- | -| $a_3^{\text{prev}} \cdot x_0$ | Acc limb 3 Γ— eval limb 0 | Direct limb 3 term | -| $a_2^{\text{prev}} \cdot x_1$ | Acc limb 2 Γ— eval limb 1 | Cross-product $(2,1)$ | -| $a_1^{\text{prev}} \cdot x_2$ | Acc limb 1 Γ— eval limb 2 | Cross-product $(1,2)$ | -| $a_0^{\text{prev}} \cdot x_3$ | Acc limb 0 Γ— eval limb 3 | Cross-product $(0,3)$ | -| ... | (all 4-limb products) | All combinations summing to limb 3 | - -### Combined Subrelation 2 Formula +The combined subrelation 2 is: $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_2 + 2^{68} \cdot T_3 - 2^{136} \cdot c^{\text{hi}} \right) = 0}$$ @@ -448,30 +410,31 @@ $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_2 + 2^{68} \cdot T_3 - ### Goal -Prove the accumulation formula holds when computed directly in 𝔽r (the native field). +Prove the accumulation formula holds when computed directly in 𝔽p (the native field). ### Reconstruction First, reconstruct all values from their limbs: $$ -\begin{align} -\tilde{P}_x &= P_{x,0}^{\text{lo}} + 2^{68} \cdot P_{x,1}^{\text{lo}} + 2^{136} \cdot P_{x,0}^{\text{hi}} + 2^{204} \cdot P_{x,1}^{\text{hi}} \pmod{r} \\ -\tilde{P}_y &= P_{y,0}^{\text{lo}} + 2^{68} \cdot P_{y,1}^{\text{lo}} + 2^{136} \cdot P_{y,0}^{\text{hi}} + 2^{204} \cdot P_{y,1}^{\text{hi}} \pmod{r} \\ -\tilde{z}_1 &= z_{1,0} + 2^{68} \cdot z_{1,1} \pmod{r} \\ -\tilde{z}_2 &= z_{2,0} + 2^{68} \cdot z_{2,1} \pmod{r} \\ -\tilde{a}^{\text{prev}} &= a_0^{\text{prev}} + 2^{68} \cdot a_1^{\text{prev}} + 2^{136} \cdot a_2^{\text{prev}} + 2^{204} \cdot a_3^{\text{prev}} \pmod{r} \\ -\tilde{a}^{\text{curr}} &= a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}} \pmod{r} \\ -\tilde{\mathcal{Q}} &= q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3 \pmod{r} -\end{align} +\begin{align*} +\tilde{P}_x &= P_{x,0}^{\text{lo}} + 2^{68} \cdot P_{x,1}^{\text{lo}} + 2^{136} \cdot P_{x,0}^{\text{hi}} + 2^{204} \cdot P_{x,1}^{\text{hi}} \pmod{p} \\ +\tilde{P}_y &= P_{y,0}^{\text{lo}} + 2^{68} \cdot P_{y,1}^{\text{lo}} + 2^{136} \cdot P_{y,0}^{\text{hi}} + 2^{204} \cdot P_{y,1}^{\text{hi}} \pmod{p} \\ +\tilde{z}_1 &= z_{1,0} + 2^{68} \cdot z_{1,1} \pmod{p} \\ +\tilde{z}_2 &= z_{2,0} + 2^{68} \cdot z_{2,1} \pmod{p} \\ +\tilde{a}^{\text{prev}} &= a_0^{\text{prev}} + 2^{68} \cdot a_1^{\text{prev}} + 2^{136} \cdot a_2^{\text{prev}} + 2^{204} \cdot a_3^{\text{prev}} \pmod{p} \\ +\tilde{a}^{\text{curr}} &= a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}} \pmod{p} \\ +\tilde{\mathcal{Q}} &= q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3 \pmod{p} +\end{align*} $$ -**Note:** The tilde $\tilde{}$ indicates these are native field reconstructions in 𝔽r, not the original 𝔽q values. +**Note:** The tilde indicates these are native field reconstructions in 𝔽p, not the original 𝔽q values. -### Subrelation 3 Formula +The subrelation 3 is then: $$ -\boxed{\begin{align}L_{\text{even}} \cdot \texttt{op} \cdot \Big( &\tilde{a}^{\text{prev}} \cdot x_4 \\ +\boxed{\begin{align*} +L_{\text{even}} \cdot \texttt{op} \cdot \Big( &\tilde{a}^{\text{prev}} \cdot x_4 & \\ &+ \texttt{op} \\ &+ \tilde{P}_x \cdot v_4 \\ &+ \tilde{P}_y \cdot (v^2)_4 \\ @@ -479,20 +442,20 @@ $$ &+ \tilde{z}_2 \cdot (v^4)_4 \\ &+ \tilde{\mathcal{Q}} \cdot \bar{q}_4 \\ &- \tilde{a}^{\text{curr}} \Big) = 0 -\end{align}} +\end{align*}} $$ Where: -- All arithmetic is performed in $\mathbb{F}_{r}$ +- All arithmetic is performed in $\mathbb{F}_{p}$ - $x_4, v_4, (v^2)_4, (v^3)_4, (v^4)_4$ are the native field representations of the challenges -- $\bar{q}_4 = -q \pmod{r}$ +- $\bar{q}_4 = -q \pmod{p}$ **Interpretation:** -- Reconstruct all limbed values back to native $\mathbb{F}_{r}$ elements -- Compute the accumulation formula directly in $\mathbb{F}_{r}$ -- If subrelations 1 and 2 prove it holds mod $2^{272}$, and subrelation 3 proves it holds mod $r$, then it holds in integers +- Reconstruct all limbed values back to native $\mathbb{F}_{p}$ elements +- Compute the accumulation formula directly in $\mathbb{F}_{p}$ +- If subrelations 1 and 2 prove it holds mod $2^{272}$, and subrelation 3 proves it holds mod $p$, then it holds in integers --- @@ -504,7 +467,7 @@ We prove the accumulation identity holds in three ways: 1. **Modulo $2^{136}$ (lower):** Subrelation 1 2. **Modulo $2^{136}$ (higher):** Subrelation 2, which together with 1 gives mod $2^{272}$ -3. **Modulo $r$:** Subrelation 3 +3. **Modulo $p$:** Subrelation 3 ### Chinese Remainder Theorem Intuition @@ -512,9 +475,9 @@ If an equation holds modulo $M_1$ and modulo $M_2$ where $\gcd(M_1, M_2) = 1$, t **Application:** -- $\gcd(2^{272}, r) = 1$ (since $r$ is odd prime) -- If equation holds mod $2^{272}$ AND mod $r$ -- Then it holds mod $2^{272} \cdot r$ +- $\gcd(2^{272}, p) = 1$ (since $p$ is odd prime) +- If equation holds mod $2^{272}$ AND mod $p$ +- Then it holds mod $2^{272} \cdot p$ ### Maximum Value Bound @@ -526,12 +489,11 @@ Each factor is at most $2^{254}$, so: $$\text{Max} < 2^{254} \cdot 2^{254} + 4 \cdot 2^{254} \cdot 2^{254} < 5 \cdot 2^{508} < 2^{511}$$ -**Key inequality:** -$$2^{272} \cdot r > 2^{272} \cdot 2^{254} = 2^{526} > 2^{511} > \text{Max}$$ +$$\implies 2^{272} \cdot p > 2^{272} \cdot 2^{253} = 2^{525} > 2^{511} > \text{Max}$$ **Conclusion:** -- If the equation holds mod $2^{272} \cdot r$ +- If the equation holds mod $2^{272} \cdot p$ - AND all values are bounded as above - THEN the equation holds in integers (no wraparound possible) - THEREFORE it holds modulo any smaller modulus, including $q$ @@ -589,7 +551,7 @@ $$ \end{align}} $$ -Where all $\tilde{\cdot}$ values are reconstructed from limbs in $\mathbb{F}_{r}$. +Where all $\tilde{\cdot}$ values are reconstructed from limbs in $\mathbb{F}_{p}$. ### Combined Guarantee @@ -597,8 +559,6 @@ Where all $\tilde{\cdot}$ values are reconstructed from limbs in $\mathbb{F}_{r} $$a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ -is **provably correct in $\mathbb{F}_{q}$**, despite being computed entirely in $\mathbb{F}_{r}$. +is **provably correct in $\mathbb{F}_{q}$**, despite being computed entirely in $\mathbb{F}_{p}$. --- - -**This completes the mathematical specification of the Non-Native Field Relation.** diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp index b682b17277fb..ac8ded1a3da1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp @@ -135,33 +135,38 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati const auto& v_3_4 = params.batching_challenge_v[3][4]; // Fetch witness values + // Pβ‚“ = (Pβ‚“,₃ || Pβ‚“,β‚‚ || Pβ‚“,₁ || Pβ‚“,β‚€) + // Pα΅§ = (Pα΅§,₃ || Pα΅§,β‚‚ || Pα΅§,₁ || Pα΅§,β‚€) + // z₁ = (z₁,₁ || z₁,β‚€) + // zβ‚‚ = (zβ‚‚,₁ || zβ‚‚,β‚€) + // Q = (q₃ || qβ‚‚ || q₁ || qβ‚€) const auto& op = View(in.op); - const auto& p_x_low_limbs = View(in.p_x_low_limbs); - const auto& p_y_low_limbs = View(in.p_y_low_limbs); - const auto& p_x_high_limbs = View(in.p_x_high_limbs); - const auto& p_y_high_limbs = View(in.p_y_high_limbs); + const auto& p_x_limb_0 = View(in.p_x_low_limbs); + const auto& p_y_limb_0 = View(in.p_y_low_limbs); + const auto& p_x_limb_2 = View(in.p_x_high_limbs); + const auto& p_y_limb_2 = View(in.p_y_high_limbs); const auto& accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); const auto& accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); const auto& accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); const auto& accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); - const auto& z_low_limbs = View(in.z_low_limbs); - const auto& z_high_limbs = View(in.z_high_limbs); - const auto& quotient_low_binary_limbs = View(in.quotient_low_binary_limbs); - const auto& quotient_high_binary_limbs = View(in.quotient_high_binary_limbs); - const auto& p_x_low_limbs_shift = View(in.p_x_low_limbs_shift); - const auto& p_y_low_limbs_shift = View(in.p_y_low_limbs_shift); - const auto& p_x_high_limbs_shift = View(in.p_x_high_limbs_shift); - const auto& p_y_high_limbs_shift = View(in.p_y_high_limbs_shift); - const auto& accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); - const auto& accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); - const auto& accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); - const auto& accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); - const auto& z_low_limbs_shift = View(in.z_low_limbs_shift); - const auto& z_high_limbs_shift = View(in.z_high_limbs_shift); - const auto& quotient_low_binary_limbs_shift = View(in.quotient_low_binary_limbs_shift); - const auto& quotient_high_binary_limbs_shift = View(in.quotient_high_binary_limbs_shift); - const auto& relation_wide_limbs = View(in.relation_wide_limbs); - const auto& relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); + const auto& z_1_limb_0 = View(in.z_low_limbs); + const auto& z_1_limb_1 = View(in.z_high_limbs); + const auto& quotient_binary_limbs_0 = View(in.quotient_low_binary_limbs); + const auto& quotient_binary_limbs_1 = View(in.quotient_high_binary_limbs); + const auto& p_x_limb_1 = View(in.p_x_low_limbs_shift); + const auto& p_y_limb_1 = View(in.p_y_low_limbs_shift); + const auto& p_x_limb_3 = View(in.p_x_high_limbs_shift); + const auto& p_y_limb_3 = View(in.p_y_high_limbs_shift); + const auto& prev_accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0_shift); + const auto& prev_accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1_shift); + const auto& prev_accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2_shift); + const auto& prev_accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3_shift); + const auto& z_2_limb_0 = View(in.z_low_limbs_shift); + const auto& z_2_limb_1 = View(in.z_high_limbs_shift); + const auto& quotient_binary_limbs_2 = View(in.quotient_low_binary_limbs_shift); + const auto& quotient_binary_limbs_3 = View(in.quotient_high_binary_limbs_shift); + const auto& relation_wide_limbs_lo = View(in.relation_wide_limbs); + const auto& relation_wide_limbs_hi = View(in.relation_wide_limbs_shift); const auto& lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); /** @@ -174,33 +179,33 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati */ // clang-format off // Tβ‚€: Limb 0 contribution (all products contributing at weight 2⁰) - auto tmp = accumulators_binary_limbs_0_shift * evaluation_input_x_0 + auto tmp = prev_accumulators_binary_limbs_0 * evaluation_input_x_0 + op - + p_x_low_limbs * v_0_0 - + p_y_low_limbs * v_1_0 - + z_low_limbs * v_2_0 - + z_low_limbs_shift * v_3_0 - + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + + p_x_limb_0 * v_0_0 + + p_y_limb_0 * v_1_0 + + z_1_limb_0 * v_2_0 + + z_2_limb_0 * v_3_0 + + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0; // T₁: Limb 1 contribution (all cross-products contributing at weight 2⁢⁸) - tmp += (accumulators_binary_limbs_1_shift * evaluation_input_x_0 - + accumulators_binary_limbs_0_shift * evaluation_input_x_1 - + p_x_low_limbs * v_0_1 - + p_x_low_limbs_shift * v_0_0 - + p_y_low_limbs * v_1_1 - + p_y_low_limbs_shift * v_1_0 - + z_low_limbs * v_2_1 - + z_high_limbs * v_2_0 - + z_low_limbs_shift * v_3_1 - + z_high_limbs_shift * v_3_0 - + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] - + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] + tmp += (prev_accumulators_binary_limbs_1 * evaluation_input_x_0 + + prev_accumulators_binary_limbs_0 * evaluation_input_x_1 + + p_x_limb_0 * v_0_1 + + p_x_limb_1 * v_0_0 + + p_y_limb_0 * v_1_1 + + p_y_limb_1 * v_1_0 + + z_1_limb_0 * v_2_1 + + z_1_limb_1 * v_2_0 + + z_2_limb_0 * v_3_1 + + z_2_limb_1 * v_3_0 + + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[1] + + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_1) * shift ; // clang-format on // Subtract 2¹³⁢·c_lo: if the result is zero, lower 136 bits are correct - tmp -= relation_wide_limbs * shiftx2; + tmp -= relation_wide_limbs_lo * shiftx2; tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<0>(accumulators) += tmp; @@ -216,51 +221,51 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati */ // clang-format off // Tβ‚‚: Limb 2 contribution (with carry from lower 136 bits) - tmp = relation_wide_limbs - + accumulators_binary_limbs_2_shift * evaluation_input_x_0 - + accumulators_binary_limbs_1_shift * evaluation_input_x_1 - + accumulators_binary_limbs_0_shift * evaluation_input_x_2 - + p_x_high_limbs * v_0_0 - + p_x_low_limbs_shift * v_0_1 - + p_x_low_limbs * v_0_2 - + p_y_high_limbs * v_1_0 - + p_y_low_limbs_shift * v_1_1 - + p_y_low_limbs * v_1_2 - + z_high_limbs * v_2_1 - + z_low_limbs * v_2_2 - + z_high_limbs_shift * v_3_1 - + z_low_limbs_shift * v_3_2 - + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] - + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] + tmp = relation_wide_limbs_lo + + prev_accumulators_binary_limbs_2 * evaluation_input_x_0 + + prev_accumulators_binary_limbs_1 * evaluation_input_x_1 + + prev_accumulators_binary_limbs_0 * evaluation_input_x_2 + + p_x_limb_2 * v_0_0 + + p_x_limb_1 * v_0_1 + + p_x_limb_0 * v_0_2 + + p_y_limb_2 * v_1_0 + + p_y_limb_1 * v_1_1 + + p_y_limb_0 * v_1_2 + + z_1_limb_1 * v_2_1 + + z_1_limb_0 * v_2_2 + + z_2_limb_1 * v_3_1 + + z_2_limb_0 * v_3_2 + + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[0] + + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[1] + + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[2] - accumulators_binary_limbs_2; // T₃: Limb 3 contribution (all cross-products contributing at weight 2²⁰⁴) - tmp += (accumulators_binary_limbs_3_shift * evaluation_input_x_0 - + accumulators_binary_limbs_2_shift * evaluation_input_x_1 - + accumulators_binary_limbs_1_shift * evaluation_input_x_2 - + accumulators_binary_limbs_0_shift * evaluation_input_x_3 - + p_x_high_limbs_shift * v_0_0 - + p_x_high_limbs * v_0_1 - + p_x_low_limbs_shift * v_0_2 - + p_x_low_limbs * v_0_3 - + p_y_high_limbs_shift * v_1_0 - + p_y_high_limbs * v_1_1 - + p_y_low_limbs_shift * v_1_2 - + p_y_low_limbs * v_1_3 - + z_high_limbs * v_2_2 - + z_low_limbs * v_2_3 - + z_high_limbs_shift * v_3_2 - + z_low_limbs_shift * v_3_3 - + quotient_high_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] - + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] - + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[2] - + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[3] + tmp += (prev_accumulators_binary_limbs_3 * evaluation_input_x_0 + + prev_accumulators_binary_limbs_2 * evaluation_input_x_1 + + prev_accumulators_binary_limbs_1 * evaluation_input_x_2 + + prev_accumulators_binary_limbs_0 * evaluation_input_x_3 + + p_x_limb_3 * v_0_0 + + p_x_limb_2 * v_0_1 + + p_x_limb_1 * v_0_2 + + p_x_limb_0 * v_0_3 + + p_y_limb_3 * v_1_0 + + p_y_limb_2 * v_1_1 + + p_y_limb_1 * v_1_2 + + p_y_limb_0 * v_1_3 + + z_1_limb_1 * v_2_2 + + z_1_limb_0 * v_2_3 + + z_2_limb_1 * v_3_2 + + z_2_limb_0 * v_3_3 + + quotient_binary_limbs_3 * NEGATIVE_MODULUS_LIMBS[0] + + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[1] + + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[2] + + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[3] - accumulators_binary_limbs_3) * shift; // clang-format on // Subtract 2¹³⁢·c_hi: if the result is zero, higher 136 bits are correct - tmp -= relation_wide_limbs_shift * shiftx2; + tmp -= relation_wide_limbs_hi * shiftx2; tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<1>(accumulators) += tmp; @@ -273,24 +278,20 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati }; // Reconstruct native 𝔽ᡣ representations from binary limbs - auto reconstructed_p_x = - reconstruct_from_four(p_x_low_limbs, p_x_low_limbs_shift, p_x_high_limbs, p_x_high_limbs_shift); - auto reconstructed_p_y = - reconstruct_from_four(p_y_low_limbs, p_y_low_limbs_shift, p_y_high_limbs, p_y_high_limbs_shift); - auto reconstructed_previous_accumulator = reconstruct_from_four(accumulators_binary_limbs_0_shift, - accumulators_binary_limbs_1_shift, - accumulators_binary_limbs_2_shift, - accumulators_binary_limbs_3_shift); + auto reconstructed_p_x = reconstruct_from_four(p_x_limb_0, p_x_limb_1, p_x_limb_2, p_x_limb_3); + auto reconstructed_p_y = reconstruct_from_four(p_y_limb_0, p_y_limb_1, p_y_limb_2, p_y_limb_3); + auto reconstructed_previous_accumulator = reconstruct_from_four(prev_accumulators_binary_limbs_0, + prev_accumulators_binary_limbs_1, + prev_accumulators_binary_limbs_2, + prev_accumulators_binary_limbs_3); auto reconstructed_current_accumulator = reconstruct_from_four(accumulators_binary_limbs_0, accumulators_binary_limbs_1, accumulators_binary_limbs_2, accumulators_binary_limbs_3); - auto reconstructed_z1 = reconstruct_from_two(z_low_limbs, z_high_limbs); - auto reconstructed_z2 = reconstruct_from_two(z_low_limbs_shift, z_high_limbs_shift); - auto reconstructed_quotient = reconstruct_from_four(quotient_low_binary_limbs, - quotient_low_binary_limbs_shift, - quotient_high_binary_limbs, - quotient_high_binary_limbs_shift); + auto reconstructed_z1 = reconstruct_from_two(z_1_limb_0, z_1_limb_1); + auto reconstructed_z2 = reconstruct_from_two(z_2_limb_0, z_2_limb_1); + auto reconstructed_quotient = reconstruct_from_four( + quotient_binary_limbs_0, quotient_binary_limbs_1, quotient_binary_limbs_2, quotient_binary_limbs_3); /** * Contribution (3): Subrelation 3 - Native Field Check diff --git a/noir/noir-repo b/noir/noir-repo index c9a8bf882069..1a930357477f 160000 --- a/noir/noir-repo +++ b/noir/noir-repo @@ -1 +1 @@ -Subproject commit c9a8bf882069681672e68b2612e4119592c4485a +Subproject commit 1a930357477fc0c210dc5a8960680282d4cfa24e From 5dc2759b44889eeb04622a8c498d3fc906f6f226 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 9 Dec 2025 09:03:11 +0000 Subject: [PATCH 05/29] v pow. --- ...nslator_non_native_field_relation_impl.hpp | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp index ac8ded1a3da1..6547f845b15b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp @@ -107,32 +107,32 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati const auto& evaluation_input_x_4 = params.evaluation_input_x[4]; // Limbs of batching challenge v - const auto& v_0_0 = params.batching_challenge_v[0][0]; - const auto& v_0_1 = params.batching_challenge_v[0][1]; - const auto& v_0_2 = params.batching_challenge_v[0][2]; - const auto& v_0_3 = params.batching_challenge_v[0][3]; - const auto& v_0_4 = params.batching_challenge_v[0][4]; + const auto& v_0 = params.batching_challenge_v[0][0]; + const auto& v_1 = params.batching_challenge_v[0][1]; + const auto& v_2 = params.batching_challenge_v[0][2]; + const auto& v_3 = params.batching_challenge_v[0][3]; + const auto& v_4 = params.batching_challenge_v[0][4]; // Limbs of batching challenge vΒ² - const auto& v_1_0 = params.batching_challenge_v[1][0]; - const auto& v_1_1 = params.batching_challenge_v[1][1]; - const auto& v_1_2 = params.batching_challenge_v[1][2]; - const auto& v_1_3 = params.batching_challenge_v[1][3]; - const auto& v_1_4 = params.batching_challenge_v[1][4]; + const auto& v_sqr_0 = params.batching_challenge_v[1][0]; + const auto& v_sqr_1 = params.batching_challenge_v[1][1]; + const auto& v_sqr_2 = params.batching_challenge_v[1][2]; + const auto& v_sqr_3 = params.batching_challenge_v[1][3]; + const auto& v_sqr_4 = params.batching_challenge_v[1][4]; // Limbs of batching challenge vΒ³ - const auto& v_2_0 = params.batching_challenge_v[2][0]; - const auto& v_2_1 = params.batching_challenge_v[2][1]; - const auto& v_2_2 = params.batching_challenge_v[2][2]; - const auto& v_2_3 = params.batching_challenge_v[2][3]; - const auto& v_2_4 = params.batching_challenge_v[2][4]; + const auto& v_cube_0 = params.batching_challenge_v[2][0]; + const auto& v_cube_1 = params.batching_challenge_v[2][1]; + const auto& v_cube_2 = params.batching_challenge_v[2][2]; + const auto& v_cube_3 = params.batching_challenge_v[2][3]; + const auto& v_cube_4 = params.batching_challenge_v[2][4]; // Limbs of batching challenge v⁴ - const auto& v_3_0 = params.batching_challenge_v[3][0]; - const auto& v_3_1 = params.batching_challenge_v[3][1]; - const auto& v_3_2 = params.batching_challenge_v[3][2]; - const auto& v_3_3 = params.batching_challenge_v[3][3]; - const auto& v_3_4 = params.batching_challenge_v[3][4]; + const auto& v_quad_0 = params.batching_challenge_v[3][0]; + const auto& v_quad_1 = params.batching_challenge_v[3][1]; + const auto& v_quad_2 = params.batching_challenge_v[3][2]; + const auto& v_quad_3 = params.batching_challenge_v[3][3]; + const auto& v_quad_4 = params.batching_challenge_v[3][4]; // Fetch witness values // Pβ‚“ = (Pβ‚“,₃ || Pβ‚“,β‚‚ || Pβ‚“,₁ || Pβ‚“,β‚€) @@ -181,24 +181,24 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati // Tβ‚€: Limb 0 contribution (all products contributing at weight 2⁰) auto tmp = prev_accumulators_binary_limbs_0 * evaluation_input_x_0 + op - + p_x_limb_0 * v_0_0 - + p_y_limb_0 * v_1_0 - + z_1_limb_0 * v_2_0 - + z_2_limb_0 * v_3_0 + + p_x_limb_0 * v_0 + + p_y_limb_0 * v_0 + + z_1_limb_0 * v_0 + + z_2_limb_0 * v_0 + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0; // T₁: Limb 1 contribution (all cross-products contributing at weight 2⁢⁸) tmp += (prev_accumulators_binary_limbs_1 * evaluation_input_x_0 + prev_accumulators_binary_limbs_0 * evaluation_input_x_1 - + p_x_limb_0 * v_0_1 - + p_x_limb_1 * v_0_0 - + p_y_limb_0 * v_1_1 - + p_y_limb_1 * v_1_0 - + z_1_limb_0 * v_2_1 - + z_1_limb_1 * v_2_0 - + z_2_limb_0 * v_3_1 - + z_2_limb_1 * v_3_0 + + p_x_limb_0 * v_1 + + p_x_limb_1 * v_0 + + p_y_limb_0 * v_sqr_1 + + p_y_limb_1 * v_sqr_0 + + z_1_limb_0 * v_cube_1 + + z_1_limb_1 * v_cube_0 + + z_2_limb_0 * v_quad_1 + + z_2_limb_1 * v_quad_0 + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[1] + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_1) @@ -225,16 +225,16 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati + prev_accumulators_binary_limbs_2 * evaluation_input_x_0 + prev_accumulators_binary_limbs_1 * evaluation_input_x_1 + prev_accumulators_binary_limbs_0 * evaluation_input_x_2 - + p_x_limb_2 * v_0_0 - + p_x_limb_1 * v_0_1 - + p_x_limb_0 * v_0_2 - + p_y_limb_2 * v_1_0 - + p_y_limb_1 * v_1_1 - + p_y_limb_0 * v_1_2 - + z_1_limb_1 * v_2_1 - + z_1_limb_0 * v_2_2 - + z_2_limb_1 * v_3_1 - + z_2_limb_0 * v_3_2 + + p_x_limb_2 * v_0 + + p_x_limb_1 * v_1 + + p_x_limb_0 * v_2 + + p_y_limb_2 * v_sqr_0 + + p_y_limb_1 * v_sqr_1 + + p_y_limb_0 * v_sqr_2 + + z_1_limb_1 * v_cube_1 + + z_1_limb_0 * v_cube_2 + + z_2_limb_1 * v_quad_1 + + z_2_limb_0 * v_quad_2 + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[0] + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[1] + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[2] @@ -245,18 +245,18 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati + prev_accumulators_binary_limbs_2 * evaluation_input_x_1 + prev_accumulators_binary_limbs_1 * evaluation_input_x_2 + prev_accumulators_binary_limbs_0 * evaluation_input_x_3 - + p_x_limb_3 * v_0_0 - + p_x_limb_2 * v_0_1 - + p_x_limb_1 * v_0_2 - + p_x_limb_0 * v_0_3 - + p_y_limb_3 * v_1_0 - + p_y_limb_2 * v_1_1 - + p_y_limb_1 * v_1_2 - + p_y_limb_0 * v_1_3 - + z_1_limb_1 * v_2_2 - + z_1_limb_0 * v_2_3 - + z_2_limb_1 * v_3_2 - + z_2_limb_0 * v_3_3 + + p_x_limb_3 * v_0 + + p_x_limb_2 * v_1 + + p_x_limb_1 * v_2 + + p_x_limb_0 * v_3 + + p_y_limb_3 * v_sqr_0 + + p_y_limb_2 * v_sqr_1 + + p_y_limb_1 * v_sqr_2 + + p_y_limb_0 * v_sqr_3 + + z_1_limb_1 * v_cube_2 + + z_1_limb_0 * v_cube_3 + + z_2_limb_1 * v_quad_2 + + z_2_limb_0 * v_quad_3 + quotient_binary_limbs_3 * NEGATIVE_MODULUS_LIMBS[0] + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[1] + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[2] @@ -305,10 +305,10 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati // Compute accumulation formula using native 𝔽ᡣ arithmetic (limb index 4) tmp = reconstructed_previous_accumulator * evaluation_input_x_4 + op - + reconstructed_p_x * v_0_4 - + reconstructed_p_y * v_1_4 - + reconstructed_z1 * v_2_4 - + reconstructed_z2 * v_3_4 + + reconstructed_p_x * v_4 + + reconstructed_p_y * v_sqr_4 + + reconstructed_z1 * v_cube_4 + + reconstructed_z2 * v_quad_4 + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator; // clang-format on From c36266b00e79e38cea8e4cb7ce3f87986fe1244f Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 9 Dec 2025 09:19:07 +0000 Subject: [PATCH 06/29] fix. --- TRANSLATOR_NON_NATIVE_FIELD_MATH.md | 64 +------------------ ...nslator_non_native_field_relation_impl.hpp | 6 +- 2 files changed, 5 insertions(+), 65 deletions(-) diff --git a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md index e5a51b977b51..6e075e2aeafc 100644 --- a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md +++ b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md @@ -281,14 +281,10 @@ Together, these prove the relation holds in integers. --- -## Subrelation 1: Lower Mod 2¹³⁢ Check - -### Goal +### Subrelation 1: Lower Mod 2¹³⁢ Check Prove that when we compute the accumulation formula using limbs 0 and 1, the result is a multiple of $2^{136}$. -### The Computation - We compute the accumulation using: - Limb 0 terms (contribute at weight $2^0$) @@ -345,14 +341,10 @@ $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_0 + 2^{68} \cdot T_1 - --- -## Subrelation 2: Higher Mod 2¹³⁢ Check - -### Goal +### Subrelation 2: Higher Mod 2¹³⁢ Check Prove that when we compute the accumulation formula using limbs 2 and 3, plus the carry from subrelation 1, the result is a multiple of $2^{136}$. -### The Computation - We compute using: - The carry $c^{\text{lo}}$ from subrelation 1 @@ -408,12 +400,8 @@ $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_2 + 2^{68} \cdot T_3 - ## Subrelation 3: Native Field Check -### Goal - Prove the accumulation formula holds when computed directly in 𝔽p (the native field). -### Reconstruction - First, reconstruct all values from their limbs: $$ @@ -514,51 +502,3 @@ The soundness argument **requires** that all limbs are properly range-constraine --- -## Complete Constraint System - -### Subrelation 1: Lower 136 Bits - -$$ -\boxed{\begin{align} -&L_{\text{even}} \cdot \texttt{op} \cdot \Bigg[ \\ -&\quad \underbrace{a_0^{\text{prev}} \cdot x_0 + \texttt{op} + \sum_{j} \text{(limb 0 products)}_j - a_0^{\text{curr}}}_{\text{Limb 0: } T_0} \\ -&\quad + 2^{68} \cdot \underbrace{\sum_{i,j: i+j=1} \text{(limb } i \text{ Γ— limb } j \text{ products)} - a_1^{\text{curr}}}_{\text{Limb 1: } T_1} \\ -&\quad - 2^{136} \cdot c^{\text{lo}} \\ -&\Bigg] = 0 -\end{align}} -$$ - -### Subrelation 2: Higher 136 Bits - -$$ -\boxed{\begin{align} -&L_{\text{even}} \cdot \texttt{op} \cdot \Bigg[ \\ -&\quad \underbrace{c^{\text{lo}} + \sum_{i,j: i+j=2} \text{(limb } i \text{ Γ— limb } j \text{ products)} - a_2^{\text{curr}}}_{\text{Limb 2: } T_2} \\ -&\quad + 2^{68} \cdot \underbrace{\sum_{i,j: i+j=3} \text{(limb } i \text{ Γ— limb } j \text{ products)} - a_3^{\text{curr}}}_{\text{Limb 3: } T_3} \\ -&\quad - 2^{136} \cdot c^{\text{hi}} \\ -&\Bigg] = 0 -\end{align}} -$$ - -### Subrelation 3: Native Field - -$$ -\boxed{\begin{align} -&L_{\text{even}} \cdot \texttt{op} \cdot \Bigg[ \\ -&\quad \tilde{a}^{\text{prev}} \cdot x_4 + \texttt{op} + \tilde{P}_x \cdot v_4 + \tilde{P}_y \cdot (v^2)_4 \\ -&\quad + \tilde{z}_1 \cdot (v^3)_4 + \tilde{z}_2 \cdot (v^4)_4 + \tilde{\mathcal{Q}} \cdot \bar{q}_4 - \tilde{a}^{\text{curr}} \\ -&\Bigg] = 0 -\end{align}} -$$ - -Where all $\tilde{\cdot}$ values are reconstructed from limbs in $\mathbb{F}_{p}$. - -### Combined Guarantee - -**If all three subrelations hold**, then: - -$$a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ - -is **provably correct in $\mathbb{F}_{q}$**, despite being computed entirely in $\mathbb{F}_{p}$. - ---- diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp index 6547f845b15b..a4bc7366d5ad 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp @@ -182,9 +182,9 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati auto tmp = prev_accumulators_binary_limbs_0 * evaluation_input_x_0 + op + p_x_limb_0 * v_0 - + p_y_limb_0 * v_0 - + z_1_limb_0 * v_0 - + z_2_limb_0 * v_0 + + p_y_limb_0 * v_sqr_0 + + z_1_limb_0 * v_cube_0 + + z_2_limb_0 * v_quad_0 + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0; From 273711dc8212a0f3784b26114db4cea80505b5e1 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Thu, 11 Dec 2025 09:06:55 +0000 Subject: [PATCH 07/29] decomp relations. --- TRANSLATOR_NON_NATIVE_FIELD_MATH.md | 263 +++++- ...translator_decomposition_relation_impl.hpp | 778 ++++++++++-------- 2 files changed, 691 insertions(+), 350 deletions(-) diff --git a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md index 6e075e2aeafc..cba9d1e23ebe 100644 --- a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md +++ b/TRANSLATOR_NON_NATIVE_FIELD_MATH.md @@ -66,23 +66,85 @@ These columns store finer-grained limb decompositions for non-native arithmetic: #### 3. Range Constraint Microlimb Columns (64 columns) -Each limb is further decomposed into **14-bit microlimbs** for range checking: - -| Column Group | Count | Decomposition | Range per Microlimb | -| ------------------------------------------- | ----- | -------------------------------- | ------------------- | -| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail (shifted by 4) | [0, 2¹⁴) each | -| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `Z_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_*` | 6 | 5Γ—14-bit + 1 tail | [0, 2¹⁴) each | -| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_*` | 4 | 6Γ—14-bit (84 bits total) | [0, 2¹⁴) each | - -**Tail microlimb**: The "\_TAIL" column contains the highest 14-bit microlimb multiplied by 4, providing a stricter constraint to ensure the total limb doesn't overflow its intended bit width. +Each limb is further decomposed into **14-bit microlimbs** for range checking. Each 68-bit limb has 5 microlimbs (14 bits each) plus a "tail" microlimb that enforces tight range constraints. The columns are organized as follows: + +| Column Group | Even Row (2i) | Odd Row (2i+1) | +| ---------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------- | +| Coordinate $P_x$ microlimbs | | | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_0` | $P_{x,0}[0]$ | $P_{x,1}[0]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_1` | $P_{x,0}[1]$ | $P_{x,1}[1]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_2` | $P_{x,0}[2]$ | $P_{x,1}[2]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_3` | $P_{x,0}[3]$ | $P_{x,1}[3]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_4` | $P_{x,0}[4]$ | $P_{x,1}[4]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $P_{x,2}[0]$ | $P_{x,3}[0]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $P_{x,2}[1]$ | $P_{x,3}[1]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $P_{x,2}[2]$ | $P_{x,3}[2]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $P_{x,2}[3]$ | $P_{x,3}[3]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $P_{x,2}[4]$ | $\textcolor{yellow}{P_{x,3}[\textsf{tail}]}$ (reassigned) | +| Coordinate $P_y$ microlimbs | | | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0` | $P_{y,0}[0]$ | $P_{y,1}[0]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_1` | $P_{y,0}[1]$ | $P_{y,1}[1]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_2` | $P_{y,0}[2]$ | $P_{y,1}[2]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_3` | $P_{y,0}[3]$ | $P_{y,1}[3]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_4` | $P_{y,0}[4]$ | $P_{y,1}[4]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $P_{y,2}[0]$ | $P_{y,3}[0]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $P_{y,2}[1]$ | $P_{y,3}[1]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $P_{y,2}[2]$ | $P_{y,3}[2]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $P_{y,2}[3]$ | $P_{y,3}[3]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $P_{y,2}[4]$ | $\textcolor{yellow}{P_{y,3}[\textsf{tail}]}$ (reassigned) | +| Coordinate $z_1$ microlimbs | | | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_0` | $z_{1,0}[0]$ | $z_{2,0}[0]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_1` | $z_{1,0}[1]$ | $z_{2,0}[1]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,0}[2]$ | $z_{2,0}[2]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_3` | $z_{1,0}[3]$ | $z_{2,0}[3]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_4` | $z_{1,0}[4]$ | $z_{2,0}[4]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $z_{1,1}[0]$ | $z_{2,1}[0]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $z_{1,1}[1]$ | $z_{2,1}[1]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,1}[2]$ | $z_{2,1}[2]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $z_{1,1}[3]$ | $z_{2,1}[3]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $z_{1,1}[4]$ | $z_{2,1}[4]$ | +| Accumulator microlimbs | | | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0` | $a_{0}^{\text{curr}}[0]$ | $a_{1}^{\text{curr}}[0]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_1` | $a_{0}^{\text{curr}}[1]$ | $a_{1}^{\text{curr}}[1]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_2` | $a_{0}^{\text{curr}}[2]$ | $a_{1}^{\text{curr}}[2]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_3` | $a_{0}^{\text{curr}}[3]$ | $a_{1}^{\text{curr}}[3]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_4` | $a_{0}^{\text{curr}}[4]$ | $a_{1}^{\text{curr}}[4]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $a_{2}^{\text{curr}}[0]$ | $a_{3}^{\text{curr}}[0]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $a_{2}^{\text{curr}}[1]$ | $a_{3}^{\text{curr}}[1]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $a_{2}^{\text{curr}}[2]$ | $a_{3}^{\text{curr}}[2]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $a_{2}^{\text{curr}}[3]$ | $a_{3}^{\text{curr}}[3]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $a_{2}^{\text{curr}}[4]$ | $\textcolor{yellow}{a_{3}[\textsf{tail}]}$ (reassigned) | +| Quotient microlimbs | | | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_0` | $q_{0}[0]$ | $q_{1}[0]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_1` | $q_{0}[1]$ | $q_{1}[1]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_2` | $q_{0}[2]$ | $q_{1}[2]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_3` | $q_{0}[3]$ | $q_{1}[3]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_4` | $q_{0}[4]$ | $q_{1}[4]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $q_{2}[0]$ | $q_{3}[0]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $q_{2}[1]$ | $q_{3}[1]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $q_{2}[2]$ | $q_{3}[2]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $q_{2}[3]$ | $q_{3}[3]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $q_{2}[4]$ | $\textcolor{yellow}{q_{3}[\textsf{tail}]}$ (reassigned) | +| Carry microlimbs | | | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0` | $c^{\text{lo}}[0]$ | $c^{\text{hi}}[0]$ | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_1` | $c^{\text{lo}}[1]$ | $c^{\text{hi}}[1]$ | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_2` | $c^{\text{lo}}[2]$ | $c^{\text{hi}}[2]$ | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_3` | $c^{\text{lo}}[3]$ | $c^{\text{hi}}[3]$ | +| Tail microlimbs | | | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{x,0}[\textsf{tail}]}$ | $\textcolor{yellow}{P_{x,1}[\textsf{tail}]}$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{x,2}[\textsf{tail}]}$ | $c^{\text{lo}}[4]$ (reassigned) | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{y,0}[\textsf{tail}]}$ | $\textcolor{yellow}{P_{y,1}[\textsf{tail}]}$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{y,2}[\textsf{tail}]}$ | $c^{\text{hi}}[4]$ (reassigned) | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{z_{1,0}[\textsf{tail}]}$ | $\textcolor{yellow}{z_{2,0}[\textsf{tail}]}$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{z_{1,1}[\textsf{tail}]}$ | $\textcolor{yellow}{z_{2,1}[\textsf{tail}]}$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{a_{0}^{\text{curr}}[\textsf{tail}]}$ | $\textcolor{yellow}{a_{1}^{\text{curr}}[\textsf{tail}]}$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{a_{2}^{\text{curr}}[\textsf{tail}]}$ | $c^{\text{lo}}[5]$ (reassigned) | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{0}[\textsf{tail}]}$ | $\textcolor{yellow}{q_{1}[\textsf{tail}]}$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{2}[\textsf{tail}]}$ | $c^{\text{hi}}[5]$ (reassigned) | +| | | | + +The tail microlimbs are shown in yellow and we will explain their role in enforcing tight range constraints in the following sections. +We reuse columns in some cases (to save space) by reassigning them to hold tail microlimbs. For example since limb $P_{x, 3}$ is only 50 bits, it only needs 4 full 14-bit microlimbs. So the odd row in the 5th microlimb column `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` is reassigned to hold the tail microlimb for $P_{x,3}$. ### Active Constraints by Row Type @@ -502,3 +564,170 @@ The soundness argument **requires** that all limbs are properly range-constraine --- +## Decomposition Relation: Mathematical Specification + +### Purpose and Overview + +The decomposition relation enforces the integrity of the limb decomposition system. While the Non-Native Field Relation proves the accumulation formula is correct, the Decomposition Relation proves all limb decompositions are valid. + +The relation consists of 48 subrelations organized into five categories: + +1. Accumulator microlimb decomposition (4 subrelations): Active when $L_{\text{even}} \cdot \texttt{op} = 1$ +2. Point & Scalar microlimb decomposition (18 subrelations): Active when $L_{\text{even}} = 1$ +3. Wide limb decomposition (2 subrelations): Decompose 84-bit carry limbs +4. Range constraint tightening (20 subrelations): Enforce stricter bounds on highest microlimbs +5. Transcript composition (6 subrelations): Prove 68-bit limbs reconstruct transcript values + +These work with the **Delta Range Constraint** permutation argument that proves each microlimb is in $[0, 2^{14})$. + +--- + +### The 14-bit Microlimb System + +**Two-level decomposition hierarchy:** + +1. Level 1 (68-bit limbs): 254-bit values β†’ 68 + 68 + 68 + 50 bits +2. Level 2 (14-bit microlimbs): 68-bit limbs β†’ 14 + 14 + 14 + 14 + 12 bits + +Microlimb reconstruction formula for a 68-bit limb $\ell$ with microlimbs $m_0, \ldots, m_4$: + +$$\boxed{\ell = m_0 + m_1 \cdot 2^{14} + m_2 \cdot 2^{28} + m_3 \cdot 2^{42} + m_4 \cdot 2^{56}}$$ + +**Range constraints:** + +- All microlimbs $m_j \in [0, 2^{14})$ (enforced by permutation) +- For 68-bit limbs: $m_4 \in [0, 2^{12})$ +- For 50-bit limbs: $m_3 \in [0, 2^{8})$ +- For 52-bit limbs: $m_3 \in [0, 2^{10})$ +- For 60-bit limbs: $m_4 \in [0, 2^{4})$ + +--- + +### Categories 1-2: Microlimb Decomposition (Subrelations 0-19) + +**General pattern** for decomposing a limb $\ell_i$ into microlimbs $\{\ell_{i,j}\}$: +$$\boxed{L_{\text{selector}} \cdot \left( \sum_{j=0}^{k} \ell_{i,j} \cdot 2^{14j} - \ell_i \right) = 0}$$ + +where $k=4$ for 68/60-bit limbs and $k=3$ for 50/52-bit limbs. + +**Subrelations 0-3:** Accumulator limbs $(a_0, a_1, a_2, a_3)$ with selector $L_{\text{even}} \cdot \texttt{op}$ + +- $a_3$ is 50-bit (uses only 4 microlimbs) + +**Subrelations 4-19:** Point coordinates and scalars with selector $L_{\text{even}}$ + +| Element | Limbs decomposed | Number of subrelations | Note | +| ------------- | ------------------------------------------------------------------------------------------ | ---------------------- | --------------------------------- | +| $P_y$ | $P_{y,0}^{\text{lo}}, \ P_{y,1}^{\text{lo}}, \ P_{y,0}^{\text{hi}}, \ P_{y,1}^{\text{hi}}$ | 4 | 68 + 68 + 68 + 50 bits | +| $z_1, z_2$ | $z_{1,0}, \ z_{2,0}, \ z_{1,1}, \ z_{2,1}$ | 4 | Each $z$ is 128-bit: 68 + 60 bits | +| $P_x$ | $P_{x,0}^{\text{lo}}, \ P_{x,1}^{\text{lo}}, \ P_{x,0}^{\text{hi}}, \ P_{x,1}^{\text{hi}}$ | 4 | 68 + 68 + 68 + 50 bits | +| $\mathcal{Q}$ | $q_0, q_1, q_2, q_3$ | 4 | 68 + 68 + 68 + 52 bits | +| | | | | + +--- + +### Category 3: Wide Limb Decomposition (Subrelations 20-21) + +Carry limbs $c^{\text{lo}}, c^{\text{hi}}$ are **84 bits** (6 Γ— 14-bit microlimbs). To save space, the 5th and 6th microlimbs are stored in unused "tail" columns: + +$$\boxed{L_{\text{even}} \cdot \left( \sum_{j=0}^{3} c_{i,j} \cdot 2^{14j} + c_{i,4} \cdot 2^{56} + c_{i,5} \cdot 2^{70} - c^{(i)} \right) = 0}$$ + +where $c^{(0)} = c^{\text{lo}}$, $c^{(1)} = c^{\text{hi}}$. + +**Microlimb reuse:** + +- $c_{0,4}^{\text{micro}}$ = `p_x_high_limbs_range_constraint_tail_shift` +- $c_{0,5}^{\text{micro}}$ = `accumulator_high_limbs_range_constraint_tail_shift` +- $c_{1,4}^{\text{micro}}$ = `p_y_high_limbs_range_constraint_tail_shift` +- $c_{1,5}^{\text{micro}}$ = `quotient_high_limbs_range_constraint_tail_shift` + +--- + +### Category 4: Range Constraint Tightening (Subrelations 22-41) + +For limbs with $b = 14k + r$ bits (where $0 < r < 14$), the highest microlimb $m_k$ must satisfy $m_k < 2^r$. + +**Shift-and-scale technique:** + +For proving $m_k < 2^r$, we add a new variable $m_k^{\text{tail}}\in [0, 2^{14})$ defined as: + +$$m_k^{\text{tail}} := m_k \ll (14 - r).$$ + +Then enforce: + +$$\boxed{L_{\text{even}} \cdot \left( m_k \cdot 2^{14-r} - m_k^{\text{tail}} \right) = 0}$$ + +implying $m_k \in [0, 2^r)$. + +**Shift factors:** + +- $2^2 = 4$: Constrains to 12 bits (68-bit limbs) +- $2^4 = 16$: Constrains to 10 bits (52-bit limbs) +- $2^6 = 64$: Constrains to 8 bits (50-bit limbs) +- $2^{10} = 1024$: Constrains to 4 bits (60-bit limbs) + +**Subrelations 22-41** apply this pattern to: + +- $P_x$ limbs (4 constraints): 12, 12, 12, 8 bits +- $P_y$ limbs (4 constraints): 12, 12, 12, 8 bits +- $z_1, z_2$ limbs (4 constraints): 12, 12, 4, 4 bits +- Accumulator limbs (4 constraints): 12, 12, 12, 8 bits +- Quotient limbs (4 constraints): 12, 12, 12, 10 bits + +--- + +### Category 5: Transcript Value Composition (Subrelations 42-47) + +These prove that 68-bit limbs correctly reconstruct EccOpQueue transcript values. + +**General pattern** for composing two limbs into a transcript value: +$$\boxed{L_{\text{even}} \cdot \left( \ell_{\text{low}} + 2^{68} \cdot \ell_{\text{high}} - \text{transcript}_{\text{value}} \right) = 0}$$ + +**Subrelations:** + +- **42-43:** $P_x$ composition: $P_{x,\text{lo}}$ (136-bit) and $P_{x,\text{hi}}$ (118-bit) +- **44-45:** $P_y$ composition: $P_{y,\text{lo}}$ (136-bit) and $P_{y,\text{hi}}$ (118-bit) +- **46-47:** $z_1, z_2$ composition: (128-bit each) + +**EccOpQueue encoding** (even/odd rows): + +- `X_LO_Y_HI`: $P_{x,\text{lo}}$ / $P_{y,\text{hi}}$ +- `X_HI_Z_1`: $P_{x,\text{hi}}$ / $z_1$ +- `Y_LO_Z_2`: $P_{y,\text{lo}}$ / $z_2$ + +--- + +### Complete Decomposition Relation Summary + +The Decomposition Relation enforces 48 independent constraints: + +| Subrelations | Category | Purpose | +| ------------ | ---------------------------- | ---------------------------------------------------------- | +| 0-3 | Accumulator microlimb decomp | Prove $a_i^{\text{curr}}$ correctly decomposes (4 limbs) | +| 4-7 | $P_y$ microlimb decomp | Prove $P_y$ limbs correctly decompose (4 limbs) | +| 8-11 | $z_1, z_2$ microlimb decomp | Prove $z$ limbs correctly decompose (2 values Γ— 2 limbs) | +| 12-15 | $P_x$ microlimb decomp | Prove $P_x$ limbs correctly decompose (4 limbs) | +| 16-19 | Quotient microlimb decomp | Prove $\mathcal{Q}$ limbs correctly decompose (4 limbs) | +| 20-21 | Wide limb decomp | Prove carry limbs $c^{\text{lo}}, c^{\text{hi}}$ decompose | +| 22-25 | $P_x$ range tightening | Constrain $P_x$ highest microlimbs to 12/8 bits | +| 26-29 | $P_y$ range tightening | Constrain $P_y$ highest microlimbs to 12/8 bits | +| 30-33 | $z$ range tightening | Constrain $z$ highest microlimbs to 12/4 bits | +| 34-37 | Accumulator range tightening | Constrain accumulator highest microlimbs to 12/8 bits | +| 38-41 | Quotient range tightening | Constrain quotient highest microlimbs to 12/10 bits | +| 42-47 | Transcript value composition | Prove 68-bit limbs correctly form transcript values | + +### Interaction with Delta Range Constraint + +The Decomposition Relation works in tandem with the Delta Range Constraint (a separate permutation argument): + +**Delta Range Constraint proves:** Every microlimb column (all `*_range_constraint_*` columns) contains only values in $[0, 2^{14})$. + +**Decomposition Relation proves:** + +1. Large limbs are correctly reconstructed from microlimbs +2. Highest microlimbs are more strictly bounded (4, 8, 10, or 12 bits) +3. Transcript values are correctly formed from 68-bit limbs + +**Together they guarantee:** All limb decompositions are valid and all values are correctly range-constrained. + +--- diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp index fcbe7b13dd7f..768039e3da23 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp @@ -13,13 +13,15 @@ namespace bb { * @brief Expression for decomposition of various values into smaller limbs or microlimbs. * @details This relation enforces three types of subrelations: * 1) A subrelation decomposing a value from the transcript (for example, z1) into 68-bit limbs. These relations - * will have the structure `lagrange_even_in_minicircuitβ‹…(a - a_low - a_highβ‹…2⁢⁸)` - * 2) A subrelation decomposing a value of one of the limbs used in bigfield computation (for example, the lower - * wide relation limb) into 14-bit limbs. These relations will have the structure `lagrange_even_in_minicircuitβ‹…(a - - * a_0 - a_1β‹…2¹⁴ - - * ....)` 3) A subrelation making a microlimb range constraint more constraining. For example, we want to constrain - * some values to 12 bits instead of 14. So we add a constraint `lagrange_even_in_minicircuitβ‹…(a_highestβ‹…4 - - * a_tail)`. In a separate relation both a_highest and a_tail are constrained to be 14 bits, but this relation + * will have the structure + * `lagrange_even_in_minicircuitβ‹…(a - a_low - a_highβ‹…2⁢⁸)` + * 2) A subrelation decomposing a value of one of the limbs used in bigfield computation (for example, the lower + * wide relation limb) into 14-bit limbs. These relations will have the structure + * `lagrange_even_in_minicircuitβ‹…(a - a_0 - a_1β‹…2¹⁴ - ....)` + * 3) A subrelation making a microlimb range constraint more constraining. For example, we want to constrain + * some values to 12 bits instead of 14. So we add a constraint + * `lagrange_even_in_minicircuitβ‹…(a_highestβ‹…4 - a_tail)`. + * In a separate relation both a_highest and a_tail are constrained to be 14 bits, but this relation * changes the constraint on a_highest to be 12 bits. * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` @@ -44,76 +46,92 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio using View = typename Accumulator::View; // Values to multiply an element by to perform an appropriate shift - static auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); - static auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; + static constexpr auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); + static constexpr auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; + static constexpr auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; + static constexpr auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; + // A = (A₃ || Aβ‚‚ || A₁ || Aβ‚€) auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); - auto accumulator_low_limbs_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0); - auto accumulator_low_limbs_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1); - auto accumulator_low_limbs_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2); - auto accumulator_low_limbs_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3); - auto accumulator_low_limbs_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); - auto accumulator_low_limbs_range_constraint_0_shift = View(in.accumulator_low_limbs_range_constraint_0_shift); - auto accumulator_low_limbs_range_constraint_1_shift = View(in.accumulator_low_limbs_range_constraint_1_shift); - auto accumulator_low_limbs_range_constraint_2_shift = View(in.accumulator_low_limbs_range_constraint_2_shift); - auto accumulator_low_limbs_range_constraint_3_shift = View(in.accumulator_low_limbs_range_constraint_3_shift); - auto accumulator_low_limbs_range_constraint_4_shift = View(in.accumulator_low_limbs_range_constraint_4_shift); - auto accumulator_high_limbs_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0); - auto accumulator_high_limbs_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1); - auto accumulator_high_limbs_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2); - auto accumulator_high_limbs_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3); - auto accumulator_high_limbs_range_constraint_4 = View(in.accumulator_high_limbs_range_constraint_4); - auto accumulator_high_limbs_range_constraint_0_shift = View(in.accumulator_high_limbs_range_constraint_0_shift); - auto accumulator_high_limbs_range_constraint_1_shift = View(in.accumulator_high_limbs_range_constraint_1_shift); - auto accumulator_high_limbs_range_constraint_2_shift = View(in.accumulator_high_limbs_range_constraint_2_shift); - auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); + + // Aβ‚€ = (Aβ‚€,β‚„ || Aβ‚€,₃ || Aβ‚€,β‚‚ || Aβ‚€,₁ || Aβ‚€,β‚€) (68-bit limb) + auto accumulator_limb_0_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0); + auto accumulator_limb_0_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1); + auto accumulator_limb_0_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2); + auto accumulator_limb_0_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3); + auto accumulator_limb_0_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); + + // A₁ = (A₁,β‚„ || A₁,₃ || A₁,β‚‚ || A₁,₁ || A₁,β‚€) (68-bit limb) + auto accumulator_limb_1_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0_shift); + auto accumulator_limb_1_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1_shift); + auto accumulator_limb_1_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2_shift); + auto accumulator_limb_1_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3_shift); + auto accumulator_limb_1_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4_shift); + + // Aβ‚‚ = (Aβ‚‚,β‚„ || Aβ‚‚,₃ || Aβ‚‚,β‚‚ || Aβ‚‚,₁ || Aβ‚‚,β‚€) (68-bit limb) + auto accumulator_limb_2_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0); + auto accumulator_limb_2_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1); + auto accumulator_limb_2_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2); + auto accumulator_limb_2_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3); + auto accumulator_limb_2_range_constraint_4 = View(in.accumulator_high_limbs_range_constraint_4); + + // A₃ = (A₃,₃ || A₃,β‚‚ || A₃,₁ || A₃,β‚€) (50-bit limb) + auto accumulator_limb_3_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0_shift); + auto accumulator_limb_3_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1_shift); + auto accumulator_limb_3_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2_shift); + auto accumulator_limb_3_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3_shift); + auto op = View(in.op); auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); auto not_even_or_no_op_scaled = lagrange_even_in_minicircuit * op * scaling_factor; // Contribution 1, accumulator lowest limb decomposition + // clang-format off auto tmp_1 = - ((accumulator_low_limbs_range_constraint_0 + accumulator_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - accumulator_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + ((accumulator_limb_0_range_constraint_0 + + accumulator_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + accumulator_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - accumulators_binary_limbs_0); tmp_1 *= not_even_or_no_op_scaled; std::get<0>(accumulators) += tmp_1; // Contribution 2, accumulator second limb decomposition - auto tmp_2 = ((accumulator_low_limbs_range_constraint_0_shift + - accumulator_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - accumulator_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - accumulator_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - accumulator_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - accumulators_binary_limbs_1); + auto tmp_2 = + ((accumulator_limb_1_range_constraint_0 + + accumulator_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + accumulator_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + accumulators_binary_limbs_1); tmp_2 *= not_even_or_no_op_scaled; std::get<1>(accumulators) += tmp_2; // Contribution 3, accumulator second highest limb decomposition auto tmp_3 = - ((accumulator_high_limbs_range_constraint_0 + accumulator_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - accumulator_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + ((accumulator_limb_2_range_constraint_0 + + accumulator_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + accumulator_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - accumulators_binary_limbs_2); tmp_3 *= not_even_or_no_op_scaled; std::get<2>(accumulators) += tmp_3; // Contribution 4, accumulator highest limb decomposition - auto tmp_4 = ((accumulator_high_limbs_range_constraint_0_shift + - accumulator_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - accumulator_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - accumulator_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - accumulators_binary_limbs_3); + auto tmp_4 = + ((accumulator_limb_3_range_constraint_0 + + accumulator_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - + accumulators_binary_limbs_3); tmp_4 *= not_even_or_no_op_scaled; std::get<3>(accumulators) += tmp_4; + // clang-format on }(); [&]() { @@ -121,14 +139,14 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio using View = typename Accumulator::View; // Value to multiply an element by to perform an appropriate shift - static auto LIMB_SHIFT = FF(uint256_t(1) << NUM_LIMB_BITS); + static constexpr auto LIMB_SHIFT = FF(uint256_t(1) << NUM_LIMB_BITS); // Values to multiply an element by to perform an appropriate shift - static auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); - static auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; - static auto MICRO_LIMB_SHIFTx5 = MICRO_LIMB_SHIFTx4 * MICRO_LIMB_SHIFT; + static constexpr auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); + static constexpr auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; + static constexpr auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; + static constexpr auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; + static constexpr auto MICRO_LIMB_SHIFTx5 = MICRO_LIMB_SHIFTx4 * MICRO_LIMB_SHIFT; auto accumulator_low_limbs_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); auto accumulator_low_limbs_range_constraint_4_shift = View(in.accumulator_low_limbs_range_constraint_4_shift); @@ -144,305 +162,405 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio static auto SHIFT_4_TO_14 = FF(1024); // Shift used to range constrain the last mircrolimb of 60-bit limbs from z scalars - auto p_x_low_limbs = View(in.p_x_low_limbs); - auto p_x_low_limbs_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0); - auto p_x_low_limbs_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1); - auto p_x_low_limbs_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2); - auto p_x_low_limbs_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3); - auto p_x_low_limbs_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4); - auto p_x_low_limbs_shift = View(in.p_x_low_limbs_shift); - auto p_x_low_limbs_range_constraint_0_shift = View(in.p_x_low_limbs_range_constraint_0_shift); - auto p_x_low_limbs_range_constraint_1_shift = View(in.p_x_low_limbs_range_constraint_1_shift); - auto p_x_low_limbs_range_constraint_2_shift = View(in.p_x_low_limbs_range_constraint_2_shift); - auto p_x_low_limbs_range_constraint_3_shift = View(in.p_x_low_limbs_range_constraint_3_shift); - auto p_x_low_limbs_range_constraint_4_shift = View(in.p_x_low_limbs_range_constraint_4_shift); - auto p_x_high_limbs = View(in.p_x_high_limbs); - auto p_x_high_limbs_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0); - auto p_x_high_limbs_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1); - auto p_x_high_limbs_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2); - auto p_x_high_limbs_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3); - auto p_x_high_limbs_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_4); - auto p_x_high_limbs_shift = View(in.p_x_high_limbs_shift); - auto p_x_high_limbs_range_constraint_0_shift = View(in.p_x_high_limbs_range_constraint_0_shift); - auto p_x_high_limbs_range_constraint_1_shift = View(in.p_x_high_limbs_range_constraint_1_shift); - auto p_x_high_limbs_range_constraint_2_shift = View(in.p_x_high_limbs_range_constraint_2_shift); - auto p_x_high_limbs_range_constraint_3_shift = View(in.p_x_high_limbs_range_constraint_3_shift); - auto p_y_low_limbs = View(in.p_y_low_limbs); - auto p_y_low_limbs_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0); - auto p_y_low_limbs_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1); - auto p_y_low_limbs_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2); - auto p_y_low_limbs_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3); - auto p_y_low_limbs_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4); - auto p_y_low_limbs_shift = View(in.p_y_low_limbs_shift); - auto p_y_low_limbs_range_constraint_0_shift = View(in.p_y_low_limbs_range_constraint_0_shift); - auto p_y_low_limbs_range_constraint_1_shift = View(in.p_y_low_limbs_range_constraint_1_shift); - auto p_y_low_limbs_range_constraint_2_shift = View(in.p_y_low_limbs_range_constraint_2_shift); - auto p_y_low_limbs_range_constraint_3_shift = View(in.p_y_low_limbs_range_constraint_3_shift); - auto p_y_low_limbs_range_constraint_4_shift = View(in.p_y_low_limbs_range_constraint_4_shift); - auto p_y_high_limbs = View(in.p_y_high_limbs); - auto p_y_high_limbs_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0); - auto p_y_high_limbs_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1); - auto p_y_high_limbs_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2); - auto p_y_high_limbs_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3); - auto p_y_high_limbs_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_4); - auto p_y_high_limbs_shift = View(in.p_y_high_limbs_shift); - auto p_y_high_limbs_range_constraint_0_shift = View(in.p_y_high_limbs_range_constraint_0_shift); - auto p_y_high_limbs_range_constraint_1_shift = View(in.p_y_high_limbs_range_constraint_1_shift); - auto p_y_high_limbs_range_constraint_2_shift = View(in.p_y_high_limbs_range_constraint_2_shift); - auto p_y_high_limbs_range_constraint_3_shift = View(in.p_y_high_limbs_range_constraint_3_shift); - auto z_low_limbs = View(in.z_low_limbs); - auto z_low_limbs_range_constraint_0 = View(in.z_low_limbs_range_constraint_0); - auto z_low_limbs_range_constraint_1 = View(in.z_low_limbs_range_constraint_1); - auto z_low_limbs_range_constraint_2 = View(in.z_low_limbs_range_constraint_2); - auto z_low_limbs_range_constraint_3 = View(in.z_low_limbs_range_constraint_3); - auto z_low_limbs_range_constraint_4 = View(in.z_low_limbs_range_constraint_4); - auto z_low_limbs_shift = View(in.z_low_limbs_shift); - auto z_low_limbs_range_constraint_0_shift = View(in.z_low_limbs_range_constraint_0_shift); - auto z_low_limbs_range_constraint_1_shift = View(in.z_low_limbs_range_constraint_1_shift); - auto z_low_limbs_range_constraint_2_shift = View(in.z_low_limbs_range_constraint_2_shift); - auto z_low_limbs_range_constraint_3_shift = View(in.z_low_limbs_range_constraint_3_shift); - auto z_low_limbs_range_constraint_4_shift = View(in.z_low_limbs_range_constraint_4_shift); - auto z_high_limbs = View(in.z_high_limbs); - auto z_high_limbs_range_constraint_0 = View(in.z_high_limbs_range_constraint_0); - auto z_high_limbs_range_constraint_1 = View(in.z_high_limbs_range_constraint_1); - auto z_high_limbs_range_constraint_2 = View(in.z_high_limbs_range_constraint_2); - auto z_high_limbs_range_constraint_3 = View(in.z_high_limbs_range_constraint_3); - auto z_high_limbs_range_constraint_4 = View(in.z_high_limbs_range_constraint_4); - auto z_high_limbs_shift = View(in.z_high_limbs_shift); - auto z_high_limbs_range_constraint_0_shift = View(in.z_high_limbs_range_constraint_0_shift); - auto z_high_limbs_range_constraint_1_shift = View(in.z_high_limbs_range_constraint_1_shift); - auto z_high_limbs_range_constraint_2_shift = View(in.z_high_limbs_range_constraint_2_shift); - auto z_high_limbs_range_constraint_3_shift = View(in.z_high_limbs_range_constraint_3_shift); - auto z_high_limbs_range_constraint_4_shift = View(in.z_high_limbs_range_constraint_4_shift); - auto quotient_low_binary_limbs = View(in.quotient_low_binary_limbs); - auto quotient_low_limbs_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0); - auto quotient_low_limbs_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1); - auto quotient_low_limbs_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2); - auto quotient_low_limbs_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3); - auto quotient_low_limbs_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4); - auto quotient_low_binary_limbs_shift = View(in.quotient_low_binary_limbs_shift); - auto quotient_low_limbs_range_constraint_0_shift = View(in.quotient_low_limbs_range_constraint_0_shift); - auto quotient_low_limbs_range_constraint_1_shift = View(in.quotient_low_limbs_range_constraint_1_shift); - auto quotient_low_limbs_range_constraint_2_shift = View(in.quotient_low_limbs_range_constraint_2_shift); - auto quotient_low_limbs_range_constraint_3_shift = View(in.quotient_low_limbs_range_constraint_3_shift); - auto quotient_low_limbs_range_constraint_4_shift = View(in.quotient_low_limbs_range_constraint_4_shift); - auto quotient_high_binary_limbs = View(in.quotient_high_binary_limbs); - auto quotient_high_limbs_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0); - auto quotient_high_limbs_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1); - auto quotient_high_limbs_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2); - auto quotient_high_limbs_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3); - auto quotient_high_limbs_range_constraint_4 = View(in.quotient_high_limbs_range_constraint_4); - auto quotient_high_binary_limbs_shift = View(in.quotient_high_binary_limbs_shift); - auto quotient_high_limbs_range_constraint_0_shift = View(in.quotient_high_limbs_range_constraint_0_shift); - auto quotient_high_limbs_range_constraint_1_shift = View(in.quotient_high_limbs_range_constraint_1_shift); - auto quotient_high_limbs_range_constraint_2_shift = View(in.quotient_high_limbs_range_constraint_2_shift); - auto quotient_high_limbs_range_constraint_3_shift = View(in.quotient_high_limbs_range_constraint_3_shift); - auto relation_wide_limbs = View(in.relation_wide_limbs); - auto relation_wide_limbs_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0); - auto relation_wide_limbs_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1); - auto relation_wide_limbs_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2); - auto relation_wide_limbs_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3); - auto p_x_high_limbs_range_constraint_tail_shift = View(in.p_x_high_limbs_range_constraint_tail_shift); - auto accumulator_high_limbs_range_constraint_tail_shift = - View(in.accumulator_high_limbs_range_constraint_tail_shift); - auto relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); - auto relation_wide_limbs_range_constraint_0_shift = View(in.relation_wide_limbs_range_constraint_0_shift); - auto relation_wide_limbs_range_constraint_1_shift = View(in.relation_wide_limbs_range_constraint_1_shift); - auto relation_wide_limbs_range_constraint_2_shift = View(in.relation_wide_limbs_range_constraint_2_shift); - auto relation_wide_limbs_range_constraint_3_shift = View(in.relation_wide_limbs_range_constraint_3_shift); - auto p_y_high_limbs_range_constraint_tail_shift = View(in.p_y_high_limbs_range_constraint_tail_shift); - auto quotient_high_limbs_range_constraint_tail_shift = View(in.quotient_high_limbs_range_constraint_tail_shift); - auto p_x_low_limbs_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail); - auto p_x_low_limbs_range_constraint_tail_shift = View(in.p_x_low_limbs_range_constraint_tail_shift); - auto p_x_high_limbs_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_tail); - auto p_x_high_limbs_range_constraint_4_shift = View(in.p_x_high_limbs_range_constraint_4_shift); - auto p_y_low_limbs_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail); - auto p_y_low_limbs_range_constraint_tail_shift = View(in.p_y_low_limbs_range_constraint_tail_shift); - auto p_y_high_limbs_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_tail); - auto p_y_high_limbs_range_constraint_4_shift = View(in.p_y_high_limbs_range_constraint_4_shift); - auto z_low_limbs_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail); - auto z_low_limbs_range_constraint_tail_shift = View(in.z_low_limbs_range_constraint_tail_shift); - auto z_high_limbs_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail); - auto z_high_limbs_range_constraint_tail_shift = View(in.z_high_limbs_range_constraint_tail_shift); - auto accumulator_low_limbs_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail); - auto accumulator_low_limbs_range_constraint_tail_shift = - View(in.accumulator_low_limbs_range_constraint_tail_shift); - auto accumulator_high_limbs_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_tail); - auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); - auto accumulator_high_limbs_range_constraint_4_shift = View(in.accumulator_high_limbs_range_constraint_4_shift); - auto quotient_low_limbs_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail); - auto quotient_low_limbs_range_constraint_tail_shift = View(in.quotient_low_limbs_range_constraint_tail_shift); - auto quotient_high_limbs_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_tail); - auto quotient_high_limbs_range_constraint_4_shift = View(in.quotient_high_limbs_range_constraint_4_shift); - auto x_lo_y_hi = View(in.x_lo_y_hi); - auto x_hi_z_1 = View(in.x_hi_z_1); - auto y_lo_z_2 = View(in.y_lo_z_2); - auto x_lo_y_hi_shift = View(in.x_lo_y_hi_shift); - auto x_hi_z_1_shift = View(in.x_hi_z_1_shift); - auto y_lo_z_2_shift = View(in.y_lo_z_2_shift); + // Basic notation: + // + // Pβ‚“ = (Pβ‚“,₃ || Pβ‚“,β‚‚ || Pβ‚“,₁ || Pβ‚“,β‚€) + // Pα΅§ = (Pα΅§,₃ || Pα΅§,β‚‚ || Pα΅§,₁ || Pα΅§,β‚€) + // z₁ = (z₁,₁ || z₁,β‚€) + // zβ‚‚ = (zβ‚‚,₁ || zβ‚‚,β‚€) + // Q = (q₃ || qβ‚‚ || q₁ || qβ‚€) + // + // Each of these is further decomposed into 14-bit microlimbs as follows: + // + // Pβ‚“,β‚€ = (Pβ‚“,β‚€[4] || Pβ‚“,β‚€[3] || Pβ‚“,β‚€[2] || Pβ‚“,β‚€[1] || Pβ‚“,β‚€[0]) + auto p_x_limb_0 = View(in.p_x_low_limbs); + auto p_x_limb_0_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0); + auto p_x_limb_0_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1); + auto p_x_limb_0_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2); + auto p_x_limb_0_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3); + auto p_x_limb_0_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4); + + // Pβ‚“,₁ = (Pβ‚“,₁[4] || Pβ‚“,₁[3] || Pβ‚“,₁[2] || Pβ‚“,₁[1] || Pβ‚“,₁[0]) + auto p_x_limb_1 = View(in.p_x_low_limbs_shift); + auto p_x_limb_1_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0_shift); + auto p_x_limb_1_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1_shift); + auto p_x_limb_1_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2_shift); + auto p_x_limb_1_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3_shift); + auto p_x_limb_1_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4_shift); + + // Pβ‚“,β‚‚ = (Pβ‚“,β‚‚[4] || Pβ‚“,β‚‚[3] || Pβ‚“,β‚‚[2] || Pβ‚“,β‚‚[1] || Pβ‚“,β‚‚[0]) + auto p_x_limb_2 = View(in.p_x_high_limbs); + auto p_x_limb_2_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0); + auto p_x_limb_2_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1); + auto p_x_limb_2_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2); + auto p_x_limb_2_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3); + auto p_x_limb_2_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_4); + + // Pβ‚“,₃ = (Pβ‚“,₃[4] || Pβ‚“,₃[3] || Pβ‚“,₃[2] || Pβ‚“,₃[1] || Pβ‚“,₃[0]) + auto p_x_limb_3 = View(in.p_x_high_limbs_shift); + auto p_x_limb_3_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0_shift); + auto p_x_limb_3_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1_shift); + auto p_x_limb_3_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2_shift); + auto p_x_limb_3_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3_shift); + + // Pα΅§,β‚€ = (Pα΅§,β‚€[4] || Pα΅§,β‚€[3] || Pα΅§,β‚€[2] || Pα΅§,β‚€[1] || Pα΅§,β‚€[0]) + auto p_y_limb_0 = View(in.p_y_low_limbs); + auto p_y_limb_0_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0); + auto p_y_limb_0_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1); + auto p_y_limb_0_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2); + auto p_y_limb_0_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3); + auto p_y_limb_0_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4); + + // Pα΅§,₁ = (Pα΅§,₁[4] || Pα΅§,₁[3] || Pα΅§,₁[2] || Pα΅§,₁[1] || Pα΅§,₁[0]) + auto p_y_limb_1 = View(in.p_y_low_limbs_shift); + auto p_y_limb_1_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0_shift); + auto p_y_limb_1_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1_shift); + auto p_y_limb_1_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2_shift); + auto p_y_limb_1_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3_shift); + auto p_y_limb_1_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4_shift); + + // Pα΅§,β‚‚ = (Pα΅§,β‚‚[4] || Pα΅§,β‚‚[3] || Pα΅§,β‚‚[2] || Pα΅§,β‚‚[1] || Pα΅§,β‚‚[0]) + auto p_y_limb_2 = View(in.p_y_high_limbs); + auto p_y_limb_2_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0); + auto p_y_limb_2_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1); + auto p_y_limb_2_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2); + auto p_y_limb_2_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3); + auto p_y_limb_2_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_4); + + // Pα΅§,₃ = (Pα΅§,₃[3] || Pα΅§,₃[2] || Pα΅§,₃[1] || Pα΅§,₃[0]) + auto p_y_limb_3 = View(in.p_y_high_limbs_shift); + auto p_y_limb_3_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0_shift); + auto p_y_limb_3_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1_shift); + auto p_y_limb_3_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2_shift); + auto p_y_limb_3_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3_shift); + + // z₁,β‚€ = (z₁,β‚€[4] || z₁,β‚€[3] || z₁,β‚€[2] || z₁,β‚€[1] || z₁,β‚€[0]) + auto z_1_limb_0 = View(in.z_low_limbs); + auto z_1_limb_0_range_constraint_0 = View(in.z_low_limbs_range_constraint_0); + auto z_1_limb_0_range_constraint_1 = View(in.z_low_limbs_range_constraint_1); + auto z_1_limb_0_range_constraint_2 = View(in.z_low_limbs_range_constraint_2); + auto z_1_limb_0_range_constraint_3 = View(in.z_low_limbs_range_constraint_3); + auto z_1_limb_0_range_constraint_4 = View(in.z_low_limbs_range_constraint_4); + + // zβ‚‚,β‚€ = (zβ‚‚,β‚€[4] || zβ‚‚,β‚€[3] || zβ‚‚,β‚€[2] || zβ‚‚,β‚€[1] || zβ‚‚,β‚€[0]) + auto z_2_limb_0 = View(in.z_low_limbs_shift); + auto z_2_limb_0_range_constraint_0 = View(in.z_low_limbs_range_constraint_0_shift); + auto z_2_limb_0_range_constraint_1 = View(in.z_low_limbs_range_constraint_1_shift); + auto z_2_limb_0_range_constraint_2 = View(in.z_low_limbs_range_constraint_2_shift); + auto z_2_limb_0_range_constraint_3 = View(in.z_low_limbs_range_constraint_3_shift); + auto z_2_limb_0_range_constraint_4 = View(in.z_low_limbs_range_constraint_4_shift); + + // z₁,₁ = (z₁,₁[4] || z₁,₁[3] || z₁,₁[2] || z₁,₁[1] || z₁,₁[0]) + auto z_1_limb_1 = View(in.z_high_limbs); + auto z_1_limb_1_range_constraint_0 = View(in.z_high_limbs_range_constraint_0); + auto z_1_limb_1_range_constraint_1 = View(in.z_high_limbs_range_constraint_1); + auto z_1_limb_1_range_constraint_2 = View(in.z_high_limbs_range_constraint_2); + auto z_1_limb_1_range_constraint_3 = View(in.z_high_limbs_range_constraint_3); + auto z_1_limb_1_range_constraint_4 = View(in.z_high_limbs_range_constraint_4); + + // zβ‚‚,₁ = (zβ‚‚,₁[4] || zβ‚‚,₁[3] || zβ‚‚,₁[2] || zβ‚‚,₁[1] || zβ‚‚,₁[0]) + auto z_2_limb_1 = View(in.z_high_limbs_shift); + auto z_2_limb_1_range_constraint_0 = View(in.z_high_limbs_range_constraint_0_shift); + auto z_2_limb_1_range_constraint_1 = View(in.z_high_limbs_range_constraint_1_shift); + auto z_2_limb_1_range_constraint_2 = View(in.z_high_limbs_range_constraint_2_shift); + auto z_2_limb_1_range_constraint_3 = View(in.z_high_limbs_range_constraint_3_shift); + auto z_2_limb_1_range_constraint_4 = View(in.z_high_limbs_range_constraint_4_shift); + + // Qβ‚€ = (Qβ‚€[4] || Qβ‚€[3] || Qβ‚€[2] || Qβ‚€[1] || Qβ‚€[0]) + auto quotient_binary_limbs_0 = View(in.quotient_low_binary_limbs); + auto quotient_limb_0_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0); + auto quotient_limb_0_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1); + auto quotient_limb_0_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2); + auto quotient_limb_0_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3); + auto quotient_limb_0_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4); + + // Q₁ = (Q₁[4] || Q₁[3] || Q₁[2] || Q₁[1] || Q₁[0]) + auto quotient_binary_limbs_1 = View(in.quotient_low_binary_limbs_shift); + auto quotient_limb_1_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0_shift); + auto quotient_limb_1_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1_shift); + auto quotient_limb_1_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2_shift); + auto quotient_limb_1_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3_shift); + auto quotient_limb_1_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4_shift); + + // Qβ‚‚ = (Qβ‚‚[4] || Qβ‚‚[3] || Qβ‚‚[2] || Qβ‚‚[1] || Qβ‚‚[0]) + auto quotient_binary_limbs_2 = View(in.quotient_high_binary_limbs); + auto quotient_limb_2_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0); + auto quotient_limb_2_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1); + auto quotient_limb_2_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2); + auto quotient_limb_2_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3); + auto quotient_limb_2_range_constraint_4 = View(in.quotient_high_limbs_range_constraint_4); + + // Q₃ = (Q₃[3] || Q₃[2] || Q₃[1] || Q₃[0]) + auto quotient_binary_limbs_3 = View(in.quotient_high_binary_limbs_shift); + auto quotient_limb_3_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0_shift); + auto quotient_limb_3_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1_shift); + auto quotient_limb_3_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2_shift); + auto quotient_limb_3_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3_shift); + + // Carry limbs: relation_wide_limbs_lo (84 bits) + // cβ‚—β‚’ = (cβ‚—β‚’[5] || cβ‚—β‚’[4] || cβ‚—β‚’[3] || cβ‚—β‚’[2] || cβ‚—β‚’[1] || cβ‚—β‚’[0]) + auto relation_wide_limbs_lo = View(in.relation_wide_limbs); + auto relation_wide_limbs_lo_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0); + auto relation_wide_limbs_lo_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1); + auto relation_wide_limbs_lo_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2); + auto relation_wide_limbs_lo_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3); + + // The final two limbs of cβ‚—β‚’ are stored in the unused tail columns of pβ‚“ and accumulator. + auto relation_wide_limbs_lo_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_tail_shift); + auto relation_wide_limbs_lo_range_constraint_5 = View(in.accumulator_high_limbs_range_constraint_tail_shift); + + // Carry limbs: relation_wide_limbs_hi (84 bits) + // cβ‚•α΅’ = (cβ‚•α΅’[5] || cβ‚•α΅’[4] || cβ‚•α΅’[3] || cβ‚•α΅’[2] || cβ‚•α΅’[1] || cβ‚•α΅’[0]) + auto relation_wide_limbs_hi = View(in.relation_wide_limbs_shift); + auto relation_wide_limbs_hi_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0_shift); + auto relation_wide_limbs_hi_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1_shift); + auto relation_wide_limbs_hi_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2_shift); + auto relation_wide_limbs_hi_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3_shift); + + // The final two limbs of cβ‚•α΅’ are stored in the unused tail columns of pα΅§ and quotient. + auto relation_wide_limbs_hi_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_tail_shift); + auto relation_wide_limbs_hi_range_constraint_5 = View(in.quotient_high_limbs_range_constraint_tail_shift); + + // Additional tail microlimbs for tighter range constraints + // ==> [Pβ‚“,β‚€[tail], Pβ‚“,₁[tail], Pβ‚“,β‚‚[tail], Pβ‚“,₃[tail]] + auto p_x_limb_0_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail); + auto p_x_limb_1_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail_shift); + auto p_x_limb_2_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_tail); + + // Pβ‚“,₃[tail] is stored in the unused (odd) column of Pβ‚“,₃[4]. + auto p_x_limb_3_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_4_shift); + + // ==> [Pα΅§,β‚€[tail], Pα΅§,₁[tail], Pα΅§,β‚‚[tail], Pα΅§,₃[tail]] + auto p_y_limb_0_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail); + auto p_y_limb_1_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail_shift); + auto p_y_limb_2_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_tail); + + // Pα΅§,₃[tail] is stored in the unused (odd) column of Pα΅§,₃[4]. + auto p_y_limb_3_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_4_shift); + + // ==> [z₁,β‚€[tail], zβ‚‚,β‚€[tail], z₁,₁[tail], zβ‚‚,₁[tail]] + auto z_1_limb_0_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail); + auto z_2_limb_0_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail_shift); + auto z_1_limb_1_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail); + auto z_2_limb_1_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail_shift); + + // Accumulator and quotient tail microlimbs for tighter range constraints + // ==> [Aβ‚€[tail], A₁[tail], Aβ‚‚[tail], A₃[tail]] + auto accumulator_limb_0_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail); + auto accumulator_limb_1_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail_shift); + auto accumulator_limb_2_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_tail); + + // Fetch the highest microlimb of A₃ for range constraint + // To get A₃[tail]], we fetch the unused (odd) column of A₃[3]. + auto accumulator_limb_3_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3_shift); + auto accumulator_limb_3_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_4_shift); + + // ==> [Qβ‚€[tail], Q₁[tail], Qβ‚‚[tail], Q₃[tail]] + // To get Q₃[tail], we fetch the unused (odd) column of Q₃[3]. + auto quotient_limb_0_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail); + auto quotient_limb_1_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail_shift); + auto quotient_limb_2_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_tail); + auto quotient_limb_3_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_4_shift); + + // Coordinate decompositions + // first column: [x_lo, y_hi] + // second column: [x_hi, z_1] + // third column: [y_lo, z_2] + auto x_lo = View(in.x_lo_y_hi); + auto y_hi = View(in.x_lo_y_hi_shift); + auto x_hi = View(in.x_hi_z_1); + auto z_one = View(in.x_hi_z_1_shift); + auto y_lo = View(in.y_lo_z_2); + auto z_two = View(in.y_lo_z_2_shift); auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - // Contribution 5 , P_y lowest limb decomposition - auto tmp_5 = ((p_y_low_limbs_range_constraint_0 + p_y_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_y_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_y_low_limbs); + // clang-format off + // Contribution 5 , Pα΅§,β‚€ limb decomposition + auto tmp_5 = + ((p_y_limb_0_range_constraint_0 + + p_y_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_y_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_y_limb_0); tmp_5 *= lagrange_even_in_minicircuit; tmp_5 *= scaling_factor; std::get<4>(accumulators) += tmp_5; - // Contribution 6 , P_y second lowest limb decomposition + // Contribution 6 , Pα΅§,₁ limb decomposition auto tmp_6 = - ((p_y_low_limbs_range_constraint_0_shift + p_y_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_y_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_y_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - p_y_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - p_y_low_limbs_shift); + ((p_y_limb_1_range_constraint_0 + + p_y_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_y_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_y_limb_1); tmp_6 *= lagrange_even_in_minicircuit; tmp_6 *= scaling_factor; std::get<5>(accumulators) += tmp_6; - // Contribution 7 , P_y third limb decomposition - auto tmp_7 = ((p_y_high_limbs_range_constraint_0 + p_y_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_y_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_y_high_limbs); + // Contribution 7 , Pα΅§,β‚‚ limb decomposition + auto tmp_7 = + ((p_y_limb_2_range_constraint_0 + + p_y_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_y_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_y_limb_2); tmp_7 *= lagrange_even_in_minicircuit; tmp_7 *= scaling_factor; std::get<6>(accumulators) += tmp_7; - // Contribution 8 , P_y highest limb decomposition + // Contribution 8 , Pα΅§,₃ limb decomposition auto tmp_8 = - ((p_y_high_limbs_range_constraint_0_shift + p_y_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_y_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_y_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - p_y_high_limbs_shift); + ((p_y_limb_3_range_constraint_0 + + p_y_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - + p_y_limb_3); tmp_8 *= lagrange_even_in_minicircuit; tmp_8 *= scaling_factor; std::get<7>(accumulators) += tmp_8; - // Contribution 9 , z_1 low limb decomposition - auto tmp_9 = ((z_low_limbs_range_constraint_0 + z_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - z_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - z_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_low_limbs); + // Contribution 9 , z₁,β‚€ limb decomposition + auto tmp_9 = + ((z_1_limb_0_range_constraint_0 + + z_1_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + + z_1_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_1_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_1_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_1_limb_0); tmp_9 *= lagrange_even_in_minicircuit; tmp_9 *= scaling_factor; std::get<8>(accumulators) += tmp_9; - // Contribution 10 , z_2 low limb decomposition - auto tmp_10 = ((z_low_limbs_range_constraint_0_shift + z_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - z_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - z_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - z_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - z_low_limbs_shift); + // Contribution 10 , zβ‚‚,β‚€ limb decomposition + auto tmp_10 = + ((z_2_limb_0_range_constraint_0 + + z_2_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + + z_2_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_2_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_2_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_2_limb_0); tmp_10 *= lagrange_even_in_minicircuit; tmp_10 *= scaling_factor; std::get<9>(accumulators) += tmp_10; - // Contribution 11 , z_1 high limb decomposition - auto tmp_11 = ((z_high_limbs_range_constraint_0 + z_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - z_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - z_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_high_limbs); + // Contribution 11 , z₁,₁ limb decomposition + auto tmp_11 = + ((z_1_limb_1_range_constraint_0 + + z_1_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + + z_1_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_1_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_1_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_1_limb_1); tmp_11 *= lagrange_even_in_minicircuit; tmp_11 *= scaling_factor; std::get<10>(accumulators) += tmp_11; - // Contribution 12 , z_2 high limb decomposition + // Contribution 12 , zβ‚‚,₁ limb decomposition auto tmp_12 = - ((z_high_limbs_range_constraint_0_shift + z_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - z_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - z_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - z_high_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - z_high_limbs_shift); + ((z_2_limb_1_range_constraint_0 + + z_2_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + + z_2_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_2_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_2_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_2_limb_1); tmp_12 *= lagrange_even_in_minicircuit; tmp_12 *= scaling_factor; std::get<11>(accumulators) += tmp_12; // Contributions that decompose 50, 52, 68 or 84 bit limbs used for computation into range-constrained chunks - // Contribution 13, P_x lowest limb decomposition - auto tmp_13 = ((p_x_low_limbs_range_constraint_0 + p_x_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_x_low_limbs); + // Contribution 13, Pβ‚“,β‚€ limb decomposition + auto tmp_13 = + ((p_x_limb_0_range_constraint_0 + + p_x_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_x_limb_0); tmp_13 *= lagrange_even_in_minicircuit; tmp_13 *= scaling_factor; std::get<12>(accumulators) += tmp_13; - // Contribution 14 , P_x second lowest limb decomposition + // Contribution 14 , Pβ‚“,₁ limb decomposition auto tmp_14 = - ((p_x_low_limbs_range_constraint_0_shift + p_x_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_x_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_x_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - p_x_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - p_x_low_limbs_shift); + ((p_x_limb_1_range_constraint_0 + + p_x_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_x_limb_1); tmp_14 *= lagrange_even_in_minicircuit; tmp_14 *= scaling_factor; std::get<13>(accumulators) += tmp_14; - // Contribution 15 , P_x third limb decomposition - auto tmp_15 = ((p_x_high_limbs_range_constraint_0 + p_x_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_x_high_limbs); + // Contribution 15 , Pβ‚“,β‚‚ limb decomposition + auto tmp_15 = + ((p_x_limb_2_range_constraint_0 + + p_x_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_x_limb_2); tmp_15 *= lagrange_even_in_minicircuit; tmp_15 *= scaling_factor; std::get<14>(accumulators) += tmp_15; - // Contribution 16 , P_x highest limb decomposition + // Contribution 16 , Pβ‚“,₃ limb decomposition auto tmp_16 = - ((p_x_high_limbs_range_constraint_0_shift + p_x_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - p_x_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - p_x_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - p_x_high_limbs_shift); + ((p_x_limb_3_range_constraint_0 + + p_x_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - + p_x_limb_3); tmp_16 *= lagrange_even_in_minicircuit; tmp_16 *= scaling_factor; std::get<15>(accumulators) += tmp_16; - // Contribution 17 , quotient lowest limb decomposition + // Contribution 17 , Qβ‚€ limb decomposition auto tmp_17 = - ((quotient_low_limbs_range_constraint_0 + quotient_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - quotient_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - quotient_low_binary_limbs); + ((quotient_limb_0_range_constraint_0 + + quotient_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + quotient_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + quotient_binary_limbs_0); tmp_17 *= lagrange_even_in_minicircuit; tmp_17 *= scaling_factor; std::get<16>(accumulators) += tmp_17; - // Contribution 18 , quotient second lowest limb decomposition - auto tmp_18 = ((quotient_low_limbs_range_constraint_0_shift + - quotient_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - quotient_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - quotient_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - quotient_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - - quotient_low_binary_limbs_shift); + + // Contribution 18 , Q₁ limb decomposition + auto tmp_18 = + ((quotient_limb_1_range_constraint_0 + + quotient_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + quotient_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + quotient_binary_limbs_1); tmp_18 *= lagrange_even_in_minicircuit; tmp_18 *= scaling_factor; std::get<17>(accumulators) += tmp_18; - // Contribution 19 , quotient second highest limb decomposition + // Contribution 19 , Qβ‚‚ limb decomposition auto tmp_19 = - ((quotient_high_limbs_range_constraint_0 + quotient_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - quotient_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - quotient_high_binary_limbs); + ((quotient_limb_2_range_constraint_0 + + quotient_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + quotient_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + quotient_binary_limbs_2); tmp_19 *= lagrange_even_in_minicircuit; tmp_19 *= scaling_factor; std::get<18>(accumulators) += tmp_19; - // Contribution 20 , quotient highest limb decomposition - auto tmp_20 = ((quotient_high_limbs_range_constraint_0_shift + - quotient_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - quotient_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - quotient_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - - quotient_high_binary_limbs_shift); + + // Contribution 20 , Q₃ limb decomposition + auto tmp_20 = + ((quotient_limb_3_range_constraint_0 + + quotient_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - + quotient_binary_limbs_3); tmp_20 *= lagrange_even_in_minicircuit; tmp_20 *= scaling_factor; std::get<19>(accumulators) += tmp_20; @@ -452,24 +570,26 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // accumulator and quotient. This is to save space and because these microlimbs are not used by their namesakes, // since top limbs in 254/6-bit values use one less microlimb for the top 50/52-bit limb auto tmp_21 = - ((relation_wide_limbs_range_constraint_0 + relation_wide_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + - relation_wide_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - relation_wide_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + - accumulator_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - - relation_wide_limbs); + ((relation_wide_limbs_lo_range_constraint_0 + + relation_wide_limbs_lo_range_constraint_1 * MICRO_LIMB_SHIFT + + relation_wide_limbs_lo_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + relation_wide_limbs_lo_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + relation_wide_limbs_lo_range_constraint_4 * MICRO_LIMB_SHIFTx4 + + relation_wide_limbs_lo_range_constraint_5 * MICRO_LIMB_SHIFTx5) - + relation_wide_limbs_lo); tmp_21 *= lagrange_even_in_minicircuit; tmp_21 *= scaling_factor; std::get<20>(accumulators) += tmp_21; // Contribution 22 , decomposition of high relation limb - auto tmp_22 = ((relation_wide_limbs_range_constraint_0_shift + - relation_wide_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + - relation_wide_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + - relation_wide_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + - p_y_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + - quotient_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - - relation_wide_limbs_shift); + auto tmp_22 = + ((relation_wide_limbs_hi_range_constraint_0 + + relation_wide_limbs_hi_range_constraint_1 * MICRO_LIMB_SHIFT + + relation_wide_limbs_hi_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + relation_wide_limbs_hi_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + relation_wide_limbs_hi_range_constraint_4 * MICRO_LIMB_SHIFTx4 + + relation_wide_limbs_hi_range_constraint_5 * MICRO_LIMB_SHIFTx5) - + relation_wide_limbs_hi); tmp_22 *= lagrange_even_in_minicircuit; tmp_22 *= scaling_factor; std::get<21>(accumulators) += tmp_22; @@ -478,89 +598,84 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // each limb to be more severely range constrained) // Contribution 23, range constrain the highest microlimb of lowest P.x limb to be 12 bits (68 % 14 = 12) - auto tmp_23 = p_x_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail; + auto tmp_23 = p_x_limb_0_range_constraint_4 * SHIFT_12_TO_14 - p_x_limb_0_range_constraint_tail; tmp_23 *= lagrange_even_in_minicircuit; tmp_23 *= scaling_factor; std::get<22>(accumulators) += tmp_23; // Contribution 24, range constrain the highest microlimb of second lowest P.x limb to be 12 bits - auto tmp_24 = - p_x_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail_shift; + auto tmp_24 = p_x_limb_1_range_constraint_4 * SHIFT_12_TO_14 - p_x_limb_1_range_constraint_tail; tmp_24 *= lagrange_even_in_minicircuit; tmp_24 *= scaling_factor; std::get<23>(accumulators) += tmp_24; // Contribution 25, range constrain the highest microlimb of second highest P.x limb to be 12 bits - auto tmp_25 = p_x_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_high_limbs_range_constraint_tail; + auto tmp_25 = p_x_limb_2_range_constraint_4 * SHIFT_12_TO_14 - p_x_limb_2_range_constraint_tail; tmp_25 *= lagrange_even_in_minicircuit; tmp_25 *= scaling_factor; std::get<24>(accumulators) += tmp_25; // Contribution 26, range constrain the highest microilmb of highest P.x limb to be 8 bits (50 % 14 = 8) - auto tmp_26 = - (p_x_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_x_high_limbs_range_constraint_4_shift); + auto tmp_26 = p_x_limb_3_range_constraint_3 * SHIFT_8_TO_14 - p_x_limb_3_range_constraint_tail; tmp_26 *= lagrange_even_in_minicircuit; tmp_26 *= scaling_factor; std::get<25>(accumulators) += tmp_26; // Contribution 27, range constrain the highest microlimb of lowest P.y limb to be 12 bits (68 % 14 = 12) - auto tmp_27 = p_y_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail; + auto tmp_27 = p_y_limb_0_range_constraint_4 * SHIFT_12_TO_14 - p_y_limb_0_range_constraint_tail; tmp_27 *= lagrange_even_in_minicircuit; tmp_27 *= scaling_factor; std::get<26>(accumulators) += tmp_27; // Contribution 28, range constrain the highest microlimb of second lowest P.y limb to be 12 bits (68 % 14 = 12) auto tmp_28 = - p_y_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail_shift; + p_y_limb_1_range_constraint_4 * SHIFT_12_TO_14 - p_y_limb_1_range_constraint_tail; tmp_28 *= lagrange_even_in_minicircuit; tmp_28 *= scaling_factor; std::get<27>(accumulators) += tmp_28; // Contribution 29, range constrain the highest microlimb of second highest P.y limb to be 12 bits (68 % 14 = // 12) - auto tmp_29 = p_y_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_high_limbs_range_constraint_tail; + auto tmp_29 = p_y_limb_2_range_constraint_4 * SHIFT_12_TO_14 - p_y_limb_2_range_constraint_tail; tmp_29 *= lagrange_even_in_minicircuit; tmp_29 *= scaling_factor; std::get<28>(accumulators) += tmp_29; // Contribution 30, range constrain the highest microlimb of highest P.y limb to be 8 bits (50 % 14 = 8) - auto tmp_30 = - (p_y_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_y_high_limbs_range_constraint_4_shift); + auto tmp_30 = p_y_limb_3_range_constraint_3 * SHIFT_8_TO_14 - p_y_limb_3_range_constraint_tail; tmp_30 *= lagrange_even_in_minicircuit; tmp_30 *= scaling_factor; std::get<29>(accumulators) += tmp_30; // Contribution 31, range constrain the highest microlimb of low z1 limb to be 12 bits (68 % 14 = 12) - auto tmp_31 = (z_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail); + auto tmp_31 = (z_1_limb_0_range_constraint_4 * SHIFT_12_TO_14 - z_1_limb_0_range_constraint_tail); tmp_31 *= lagrange_even_in_minicircuit; tmp_31 *= scaling_factor; std::get<30>(accumulators) += tmp_31; // Contribution 32, range constrain the highest microlimb of low z2 limb to be 12 bits (68 % 14 = 12) - auto tmp_32 = (z_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail_shift); + auto tmp_32 = (z_2_limb_0_range_constraint_4 * SHIFT_12_TO_14 - z_2_limb_0_range_constraint_tail); tmp_32 *= lagrange_even_in_minicircuit; tmp_32 *= scaling_factor; std::get<31>(accumulators) += tmp_32; // Contribution 33, range constrain the highest microlimb of high z1 limb to be 4 bits (60 % 14 = 12) - auto tmp_33 = (z_high_limbs_range_constraint_4 * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail); + auto tmp_33 = (z_1_limb_1_range_constraint_4 * SHIFT_4_TO_14 - z_1_limb_1_range_constraint_tail); tmp_33 *= lagrange_even_in_minicircuit; tmp_33 *= scaling_factor; std::get<32>(accumulators) += tmp_33; // Contribution 34, range constrain the highest microlimb of high z2 limb to be 4 bits (60 % 14 = 12) - auto tmp_34 = - (z_high_limbs_range_constraint_4_shift * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail_shift); + auto tmp_34 = z_2_limb_1_range_constraint_4 * SHIFT_4_TO_14 - z_2_limb_1_range_constraint_tail; tmp_34 *= lagrange_even_in_minicircuit; tmp_34 *= scaling_factor; std::get<33>(accumulators) += tmp_34; // Contribution 35, range constrain the highest microlimb of lowest current accumulator limb to be 12 bits (68 % // 14 = 12) - auto tmp_35 = - (accumulator_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_low_limbs_range_constraint_tail); + auto tmp_35 = accumulator_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_limb_0_range_constraint_tail; tmp_35 *= lagrange_even_in_minicircuit; tmp_35 *= scaling_factor; std::get<34>(accumulators) += tmp_35; @@ -568,7 +683,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contribution 36, range constrain the highest microlimb of second lowest current accumulator limb to be 12 // bits (68 % 14 = 12) auto tmp_36 = (accumulator_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - - accumulator_low_limbs_range_constraint_tail_shift); + accumulator_limb_1_range_constraint_tail); tmp_36 *= lagrange_even_in_minicircuit; tmp_36 *= scaling_factor; std::get<35>(accumulators) += tmp_36; @@ -576,30 +691,28 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contribution 37, range constrain the highest microlimb of second highest current accumulator limb to be 12 // bits (68 % 14 = 12) auto tmp_37 = - (accumulator_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_high_limbs_range_constraint_tail); + (accumulator_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_limb_2_range_constraint_tail); tmp_37 *= lagrange_even_in_minicircuit; tmp_37 *= scaling_factor; std::get<36>(accumulators) += tmp_37; // Contribution 38, range constrain the highest microlimb of highest current accumulator limb to be 8 bits (50 % // 14 = 12) - auto tmp_38 = (accumulator_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - - accumulator_high_limbs_range_constraint_4_shift); + auto tmp_38 = (accumulator_limb_3_range_constraint_3 * SHIFT_8_TO_14 - accumulator_limb_3_range_constraint_tail); tmp_38 *= lagrange_even_in_minicircuit; tmp_38 *= scaling_factor; std::get<37>(accumulators) += tmp_38; // Contribution 39, range constrain the highest microlimb of lowest quotient limb to be 12 bits (68 % 14 = 12) auto tmp_39 = - (quotient_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_low_limbs_range_constraint_tail); + (quotient_limb_0_range_constraint_4 * SHIFT_12_TO_14 - quotient_limb_0_range_constraint_tail); tmp_39 *= lagrange_even_in_minicircuit; tmp_39 *= scaling_factor; std::get<38>(accumulators) += tmp_39; // Contribution 40, range constrain the highest microlimb of second lowest quotient limb to be 12 bits (68 % 14 // = 12) - auto tmp_40 = (quotient_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - - quotient_low_limbs_range_constraint_tail_shift); + auto tmp_40 = (quotient_limb_1_range_constraint_4 * SHIFT_12_TO_14 - quotient_limb_1_range_constraint_tail); tmp_40 *= lagrange_even_in_minicircuit; tmp_40 *= scaling_factor; std::get<39>(accumulators) += tmp_40; @@ -607,14 +720,13 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contribution 41, range constrain the highest microlimb of second highest quotient limb to be 12 bits (68 % 14 // = 12) auto tmp_41 = - (quotient_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_high_limbs_range_constraint_tail); + (quotient_limb_2_range_constraint_4 * SHIFT_12_TO_14 - quotient_limb_2_range_constraint_tail); tmp_41 *= lagrange_even_in_minicircuit; tmp_41 *= scaling_factor; std::get<40>(accumulators) += tmp_41; // Contribution 42, range constrain the highest microlimb of highest quotient limb to be 10 bits (52 % 14 = 12) - auto tmp_42 = (quotient_high_limbs_range_constraint_3_shift * SHIFT_10_TO_14 - - quotient_high_limbs_range_constraint_4_shift); + auto tmp_42 = (quotient_limb_3_range_constraint_3 * SHIFT_10_TO_14 - quotient_limb_3_range_constraint_tail); tmp_42 *= lagrange_even_in_minicircuit; tmp_42 *= scaling_factor; std::get<41>(accumulators) += tmp_42; @@ -622,36 +734,36 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contributions where we decompose initial EccOpQueue values into 68-bit limbs // Contribution 43, decompose x_lo - auto tmp_43 = (p_x_low_limbs + p_x_low_limbs_shift * LIMB_SHIFT) - x_lo_y_hi; + auto tmp_43 = (p_x_limb_0 + p_x_limb_1 * LIMB_SHIFT) - x_lo; tmp_43 *= lagrange_even_in_minicircuit; tmp_43 *= scaling_factor; std::get<42>(accumulators) += tmp_43; // Contribution 44, decompose x_hi - auto tmp_44 = (p_x_high_limbs + p_x_high_limbs_shift * LIMB_SHIFT) - x_hi_z_1; + auto tmp_44 = (p_x_limb_2 + p_x_limb_3 * LIMB_SHIFT) - x_hi; tmp_44 *= lagrange_even_in_minicircuit; tmp_44 *= scaling_factor; std::get<43>(accumulators) += tmp_44; // Contribution 45, decompose y_lo - auto tmp_45 = (p_y_low_limbs + p_y_low_limbs_shift * LIMB_SHIFT) - y_lo_z_2; + auto tmp_45 = (p_y_limb_0 + p_y_limb_1 * LIMB_SHIFT) - y_lo; tmp_45 *= lagrange_even_in_minicircuit; tmp_45 *= scaling_factor; std::get<44>(accumulators) += tmp_45; // Contribution 46, decompose y_hi - auto tmp_46 = (p_y_high_limbs + p_y_high_limbs_shift * LIMB_SHIFT) - x_lo_y_hi_shift; + auto tmp_46 = (p_y_limb_2 + p_y_limb_3 * LIMB_SHIFT) - y_hi; tmp_46 *= lagrange_even_in_minicircuit; tmp_46 *= scaling_factor; std::get<45>(accumulators) += tmp_46; // Contribution 47, decompose z1 - auto tmp_47 = (z_low_limbs + z_high_limbs * LIMB_SHIFT) - x_hi_z_1_shift; + auto tmp_47 = (z_1_limb_0 + z_1_limb_1 * LIMB_SHIFT) - z_one; tmp_47 *= lagrange_even_in_minicircuit; tmp_47 *= scaling_factor; std::get<46>(accumulators) += tmp_47; // Contribution 48, decompose z2 - auto tmp_48 = (z_low_limbs_shift + z_high_limbs_shift * LIMB_SHIFT) - y_lo_z_2_shift; + auto tmp_48 = (z_2_limb_0 + z_2_limb_1 * LIMB_SHIFT) - z_two; tmp_48 *= lagrange_even_in_minicircuit; tmp_48 *= scaling_factor; std::get<47>(accumulators) += tmp_48; From 61e1650c997a8946562724ec9f95a9c73577e910 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Thu, 11 Dec 2025 09:21:24 +0000 Subject: [PATCH 08/29] chore. --- .../cpp/src/barretenberg/translator_vm/README.md | 2 +- .../cpp/src/barretenberg/translator_vm/RELATIONS.md | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename TRANSLATOR_CIRCUIT_EXPLAINED.md => barretenberg/cpp/src/barretenberg/translator_vm/README.md (99%) rename TRANSLATOR_NON_NATIVE_FIELD_MATH.md => barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md (100%) diff --git a/TRANSLATOR_CIRCUIT_EXPLAINED.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md similarity index 99% rename from TRANSLATOR_CIRCUIT_EXPLAINED.md rename to barretenberg/cpp/src/barretenberg/translator_vm/README.md index 649b3f9e915e..82c757ac6948 100644 --- a/TRANSLATOR_CIRCUIT_EXPLAINED.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -16,7 +16,7 @@ ## Overview -The **Translator Circuit** is a critical component of the Goblin Plonk proving system in Aztec. It serves as a **bridge between two elliptic curves**: +The **Translator Circuit** is a critical component of the Goblin Plonk proving system in Aztec. It serves as a bridge between two elliptic curves: - **BN254** (used in Mega circuits and Ethereum) - **Grumpkin** (used in ECCVM for efficient EC operations) diff --git a/TRANSLATOR_NON_NATIVE_FIELD_MATH.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md similarity index 100% rename from TRANSLATOR_NON_NATIVE_FIELD_MATH.md rename to barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md From d03cc251ca2f14b1223fe3d88ccada5a7cb683a3 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Thu, 11 Dec 2025 10:39:49 +0000 Subject: [PATCH 09/29] cleanup readme. --- .../src/barretenberg/translator_vm/README.md | 296 ++++++++++++------ 1 file changed, 197 insertions(+), 99 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 82c757ac6948..4a9a8173950a 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -3,7 +3,7 @@ ## Table of Contents 1. [Overview](#overview) -2. [The Statement Being Proven](#the-statement-being-proven) +2. [High-Level Statement](#high-level-statement) 3. [Architecture and Constants](#architecture-and-constants) 4. [Witness Polynomials (81 Total)](#witness-polynomials-81-total) 5. [Selector Polynomials](#selector-polynomials) @@ -16,65 +16,82 @@ ## Overview -The **Translator Circuit** is a critical component of the Goblin Plonk proving system in Aztec. It serves as a bridge between two elliptic curves: -- **BN254** (used in Mega circuits and Ethereum) -- **Grumpkin** (used in ECCVM for efficient EC operations) +The **Translator Circuit** is a critical component of the Goblin Plonk proving system in Aztec. It serves as a bridge between the Mega and ECCVM circuits. -### The Problem +| Curve | Base Field | Scalar Field | Usage | +| -------- | -------------- | -------------- | ----------------------------------------- | +| BN254 | $\mathbb{F}_q$ | $\mathbb{F}_r$ | Used in Mega circuits | +| Grumpkin | $\mathbb{F}_r$ | $\mathbb{F}_q$ | Used in ECCVM for efficient EC operations | -When proving recursive circuits, we accumulate elliptic curve operations in an `EccOpQueue`. These operations are performed over **BN254's base field (𝔽q)**. However, the circuit itself operates in **BN254's scalar field (𝔽r)**. +When proving recursive circuits with Mega circuit builder, we accumulate elliptic curve operations in an `EccOpQueue`. Proving these ECC operations is delegated to the ECCVM circuit, which operates over the Grumpkin curve. However, the representation of the `EccOpQueue` is different in the Mega circuit (BN254) and ECCVM (Grumpkin) circuit because: -**Key challenge:** We need to prove that polynomial evaluations computed in **𝔽r** (the circuit's native field) match the evaluations that should be computed in **𝔽q** (the curve's base field). +- Mega circuit operates over the BN254 scalar field $\mathbb{F}_r$ so elements in $\mathbb{F}_q$ are non-native (i.e., they need to decomposed into limbs in $\mathbb{F}_r$) +- ECCVM operates over the Grumpkin scalar field $\mathbb{F}_q$ so elements in $\mathbb{F}_q$ are circuit native -### The Solution +For example, consider the operation $(z \cdot P)$ where $P$ is a point on the curve and $z$ is a scalar: -The Translator circuit: -1. **Receives** a batched polynomial evaluation problem from ECCVM (operating over Grumpkin/𝔽q) -2. **Proves** that the evaluation is correct using non-native field arithmetic in 𝔽r -3. **Outputs** the result for verification in the main proving system +The ECCVM arithmetisation represents this operation (in 1 row) as: -**Analogy:** Think of Translator as an interpreter between two languages (𝔽r and 𝔽q) that proves it translated correctly. +| Opcode | $x$-coordinate | $y$-coordinate | Scalar $z_1$ | Scalar $z_2$ | Full scalar $z$ | +| ------ | -------------- | -------------- | ------------ | ------------ | --------------- | +| `MUL` | $P_x$ | $P_y$ | $z_1$ | $z_2$ | $z$ | +| | | | | | | ---- +The Mega circuit arithmetisation represents the same operation (in 2 rows) as: + +| Column 1 | Column 2 | Column 3 | Column 4 | +| -------- | -------------------- | -------------------- | -------------------- | +| `MUL` | $P_{x, \textsf{lo}}$ | $P_{x, \textsf{hi}}$ | $P_{y, \textsf{lo}}$ | +| $0$ | $P_{y, \textsf{hi}}$ | $z_1$ | $z_2$ | +| | | | | + +where $P_x = (P_{x, \textsf{lo}} + 2^{136} \cdot P_{x, \textsf{hi}}), \ P_y = (P_{y, \textsf{lo}} + 2^{136} \cdot P_{y, \textsf{hi}})$ and the scalar $z = (z_1 + 2^{128} \cdot z_2)$. + +We need to prove that these two representations are consistent, i.e., that the polynomial evaluations computed in the ECCVM circuit (over $\mathbb{F}_q$) match those computed in the Mega circuit (over $\mathbb{F}_r$). -## The Statement Being Proven +The Translator circuit is a custom circuit designed to solve this problem. It: + +1. **Receives** the ECC op queue in Mega arithmetisation and the batched polynomial evaluation problem from ECCVM (operating over $\mathbb{F}_q$), +2. **Computes** the batched polynomial evaluation using non-native field arithmetic in $\mathbb{F}_r$ and, +3. **Verifies** that the result matches the evaluation provided by ECCVM. + +--- -### High-Level Statement +## High-Level Statement Given: + - A sequence of `UltraOp` operations from the `EccOpQueue` -- An evaluation challenge `x ∈ 𝔽q` -- A batching challenge `v ∈ 𝔽q` +- An evaluation challenge $x \in \mathbb{F}_q$ +- A batching challenge $v \in \mathbb{F}_q$ **Prove:** $$\boxed{\text{accumulator}_{\text{final}} = \sum_{i=0}^{n-1} x^{n-1-i} \cdot \left( \text{op}_i + v \cdot P_x^{(i)} + v^2 \cdot P_y^{(i)} + v^3 \cdot z_1^{(i)} + v^4 \cdot z_2^{(i)} \right) \pmod{q}}$$ -Where: -- `q = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` (BN254 base field modulus) -- Each `UltraOp` contains: `(op, P.x, P.y, z₁, zβ‚‚)` -- The computation is performed **in integers** then reduced modulo `q` +where: -### Detailed Statement +- each `UltraOp` contains: $(\text{op}, \ P_x, \ P_y, \ z_1, \ z_2)$, +- the computation is performed modulo $q$. -For each accumulation step (every 2 rows), prove: +Specifically, for each accumulation step (every 2 rows), prove: $$\text{acc}_{\text{curr}} = \text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ -**Method:** Prove in integers using: +**Method:** Similar to the technique used in [bigfield](../stdlib/primitives/bigfield/README.md), we prove in integers that: + $$\text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \text{quotient} \cdot q - \text{acc}_{\text{curr}} = 0$$ This equation must hold: -1. **Modulo 2²⁷²** (proven via limb arithmetic) -2. **Modulo r** (proven in native field) -3. With proper **range constraints** (prevents overflow/underflow) -**Soundness:** Since `2²⁷² Β· r > 2⁡¹⁴` (larger than maximum possible value), correctness in both moduli implies correctness in integers. +1. modulo $2^{272}$ (proven via limb arithmetic) +2. modulo $r$ (proven in native field) +3. with appropriate range constraints (to prevent overflows/underflows) ---- +Then the Chinese Remainder Theorem guarantees that the equation holds modulo $q$. ## Architecture and Constants -### Circuit Size Parameters +#### Circuit Size Parameters ```cpp CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE = 13 // Mini-circuit: 2^13 = 8,192 rows @@ -84,7 +101,7 @@ CONST_TRANSLATOR_LOG_N = 13 + 4 = 17 // Full circuit: 2^17 = 131,072 **Why interleaving?** To reduce the degree of the permutation argument polynomial for range constraints. -### Field Moduli +#### Field Moduli ``` BN254 Base Field (Fq): @@ -96,9 +113,9 @@ r = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 β‰ˆ 2^254 ``` -**Key observation:** `q β‰  r` (they differ by ~2⁴⁷), so we cannot directly compute in 𝔽q using 𝔽r arithmetic. +**Key observation:** $q \neq r$ (they differ by $\approx 2^{47}$), so we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic. -### Limb Decomposition Constants +#### Limb Decomposition Constants ```cpp NUM_LIMB_BITS = 68 // Each limb is 68 bits @@ -112,24 +129,17 @@ NUM_QUOTIENT_BITS = 256 // Quotient needs 256 bits NUM_LAST_QUOTIENT_LIMB_BITS = 52 // 256 - 3*68 = 52 bits MICRO_LIMB_BITS = 14 // Range constraint granularity -NUM_MICRO_LIMBS = 6 // 68 / 14 β‰ˆ 5, plus 1 for shift -``` - -**Limb structure for P.x, P.y, accumulator:** -``` -Element = limb[0] + 2^68 Β· limb[1] + 2^136 Β· limb[2] + 2^204 Β· limb[3] -where: - limb[0], limb[1], limb[2] ∈ [0, 2^68) - limb[3] ∈ [0, 2^50) +NUM_MICRO_LIMBS = 6 // 68 / 14 β‰ˆ 5, plus 1 for tail ``` -### Opcode Values +#### Opcode Values ```cpp Valid opcodes: {0, 1, 2, 3, 4, 8} ``` Encoding EC operations: + - `0`: No-op / NULL - `1`: Add - `2`: Mul (scalar multiplication) @@ -137,7 +147,7 @@ Encoding EC operations: - `4`: Reset accumulator - `8`: [Special operation] -### Range Constraint Constants +#### Range Constraint Constants ```cpp SORT_STEP = 3 // Max delta between sorted values @@ -146,7 +156,7 @@ SORTED_STEPS_COUNT = 2^14 / 3 + 1 // Number of "step" values inserted = 5462 steps ``` -Each microlimb must be ≀ 2¹⁴ - 1 = 16383. +Each microlimb must be $≀ 2^{14} - 1 = 16383$. --- @@ -154,7 +164,7 @@ Each microlimb must be ≀ 2¹⁴ - 1 = 16383. ### Why Interleaving is Necessary -The Translator needs to perform **range constraints on ~64 different microlimb sets** using a **permutation argument**. Without optimization, this creates a major problem with the **relation degree**. +The Translator needs to perform range constraints on ~64 different microlimb sets using a permutation argument. Without optimization, this creates a major problem with the relation degree. **The Core Issue: Permutation Argument Degree** @@ -168,6 +178,11 @@ z_perm[i] Γ— ∏_{j=1}^{NUM_COLS} (interleaved[j] + Ξ² + Ξ³) Degree = 1 + NUM_COLS (polynomial z_perm Γ— product of NUM_COLS columns) ``` +$$ +z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \beta + \gamma) = +z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \beta + \gamma) +$$ + **The Translator's Challenge:** - We have **~64 different logical microlimb columns** that need range constraints: @@ -181,6 +196,7 @@ Degree = 1 + NUM_COLS (polynomial z_perm Γ— product of NUM_COLS columns) **Naive approach:** If we tried to permute all ~64 active columns at once: + - Degree = 1 + 64 = **65** - This is **prohibitively expensive** for sumcheck! - The relation would dominate proof generation time @@ -189,12 +205,14 @@ If we tried to permute all ~64 active columns at once: **The Solution: Interleaving to Reduce Column Count** Instead of checking 64 columns in one permutation, we: + 1. **Group 16 logical columns together** and pack them into the circuit at different row segments 2. **Use only 5 physical wires** for each permutation check (4 interleaved + 1 extra numerator) 3. **Reuse these 5 wires across 16 different segments** of the circuit 4. Each segment checks a different subset of ~4 logical columns from the original 64 **Result:** + - Relation degree: 1 + 5 = **6** (plus Lagrange = 7 total) - This is manageable for the proof system! - We perform 16 separate permutation checks (one per segment), each with low degree @@ -204,6 +222,7 @@ Instead of checking 64 columns in one permutation, we: #### The Basic Concept **Mini-circuit vs. Full Circuit:** + ``` Mini-circuit size: 2^13 = 8,192 rows (where actual computation happens) Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) @@ -219,10 +238,12 @@ Relationship: FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE For each **set of range constraint wires** (e.g., all P.x microlimbs), we create two types of polynomials: **1. Interleaved Polynomials** (in full circuit) + - Size: 131,072 (full circuit size) - Contains microlimbs from **multiple mini-circuit rows** packed together **2. Ordered Polynomials** (in full circuit) + - Size: 131,072 (full circuit size) - Contains the **sorted version** of the interleaved values @@ -233,6 +254,7 @@ Let's trace exactly how microlimbs from the mini-circuit map to the full circuit #### Example: P.x Low Limbs Range Constraint 0 (First Microlimb) **In the mini-circuit:** Each even row i ∈ {0, 2, 4, ..., 8190} generates a microlimb value: + ``` mini_row 0 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[0] = micro_0_0 mini_row 2 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[2] = micro_0_2 @@ -256,6 +278,7 @@ Group 15: mini_rows {30, 62, 94, 126, ...} β†’ full_circuit rows {122880, 1228 ``` **Formula:** + ``` For mini_row = 2k (even rows only): group_id = k mod 16 @@ -265,6 +288,7 @@ For mini_row = 2k (even rows only): ``` **Example calculation:** + ``` mini_row = 64 (32nd even row, so k = 32) group_id = 32 mod 16 = 0 @@ -319,11 +343,13 @@ Here's the exact layout of the full circuit with interleaving: ``` **Important observation:** We only have **5 physical wires** for range constraints: + - `ordered_range_constraints_0` through `ordered_range_constraints_4` - `interleaved_range_constraints_0` through `interleaved_range_constraints_3` - Plus one extra numerator wire But we need to check **many more** microlimb sets. The solution: + - Each wire is **reused across different interleaving groups** - Within each 8,192-row segment, the wire represents a different logical microlimb set - The permutation argument operates **within each segment independently** @@ -333,6 +359,7 @@ But we need to check **many more** microlimb sets. The solution: **The Critical Insight: Degree = Number of Columns in Product** The permutation relation has the form: + ``` z_perm[i+1] Γ— ∏_{j=0}^{NUM_COLS-1} (ordered[j][i] + Ξ² + Ξ³) = z_perm[i] Γ— ∏_{j=0}^{NUM_COLS-1} (interleaved[j][i] + Ξ² + Ξ³) @@ -341,6 +368,7 @@ z_perm[i] Γ— ∏_{j=0}^{NUM_COLS-1} (interleaved[j][i] + Ξ² + Ξ³) **Degree = 1 (from z_perm) + NUM_COLS (from the products)** **Without interleaving (naive approach):** + ``` Check all ~64 logical microlimb columns in one relation: @@ -358,6 +386,7 @@ This creates a degree-65 relation! ``` **With interleaving (only 5 physical columns per check):** + ``` Group 16 logical columns together, use 5 physical wires per segment: @@ -381,6 +410,7 @@ Much more manageable! **Degree reduction: 65 β†’ 7 (more than 9Γ— reduction!)** **How it works:** + - **Segment 0** (rows 0-8,191): Wires represent logical columns {0, 1, 2, 3, 4} - **Segment 1** (rows 8,192-16,383): Same wires represent logical columns {5, 6, 7, 8, 9} - **Segment 2** (rows 16,384-24,575): Same wires represent logical columns {10, 11, 12, 13, 14} @@ -423,11 +453,13 @@ For row i within segment [0, 8191]: Let's trace one specific microlimb through the entire system: **Setup:** + - We're checking P.x_low_limbs[0] (first 68-bit limb of P.x's lower 136 bits) - At mini_row = 100 (even row, 50th accumulation) - The value of the first 14-bit microlimb is: `micro = 0x2A5F = 10847` **Step 1: Mini-circuit computation (row 100)** + ``` P_X_LOW_LIMBS[0] = limb_value = 0x1234567890ABCDEF Decompose into microlimbs: @@ -437,6 +469,7 @@ Decompose into microlimbs: ``` **Step 2: Determine interleaving group** + ``` k = 100 / 2 = 50 (since mini_row 100 is the 50th even row) group_id = 50 mod 16 = 2 @@ -444,6 +477,7 @@ position = 50 Γ· 16 = 3 ``` **Step 3: Map to full circuit** + ``` full_circuit_row = 2 Γ— 8192 + 3 = 16384 + 3 = 16387 @@ -453,6 +487,7 @@ interleaved_range_constraints_2[16387] = 52719 **Step 4: Sorting** All microlimbs in group 2 are collected and sorted: + ``` interleaved_2 = [52719, 36882, ..., 4096 more values from group 2 mini-rows] ordered_2 = sorted(interleaved_2) = [0, 0, 0, ..., 1, 1, 2, ..., 16383] @@ -462,6 +497,7 @@ ordered_2 = sorted(interleaved_2) = [0, 0, 0, ..., 1, 1, 2, ..., 16383] **Step 5: Permutation check** The permutation relation verifies: + ``` For full_circuit_row ∈ [16384, 24575] (group 2 segment): @@ -496,37 +532,44 @@ Row 5463: 16383 ← Last value must be exactly 16383 ``` With periodic "step" values inserted every few rows to ensure coverage of [0, 16383]. The delta range constraint relation enforces: + 1. Each step ∈ {0, 1, 2, 3} 2. Final value = 16383 ### Benefits of Interleaving **1. Relation Degree Reduction (Most Important):** + - **From degree 65 to degree 7** (9Γ— reduction) - This is the primary benefit - keeps relations efficient - Sumcheck complexity is dominated by max relation degree **2. Proof Size Stays Constant:** + - Only need one z_perm polynomial - Reuse it across all 16 segments - Proof doesn't grow with number of groups **3. Verification Efficiency:** + - Verifier checks same polynomial across segments - No additional cost for more interleaving groups **4. Flexibility:** + - Can adjust INTERLEAVING_GROUP_SIZE based on circuit size - Balances polynomial degree vs. circuit size blowup ### Trade-offs **Cost of interleaving:** + - Circuit size increases by 16Γ— (from 8,192 to 131,072 rows) - More zero padding needed (Relation 7 ensures unused rows are zero) - More complex witness generation (need to correctly map mini-circuit to full circuit) **Why it's worth it:** + - **Relation degree reduction** >>> circuit size increase - Sumcheck is dominated by max relation degree - Without interleaving, degree-65 relation would make the circuit impractical @@ -537,6 +580,7 @@ With periodic "step" values inserted every few rows to ensure coverage of [0, 16 **Interleaving is the technique that makes the Translator practical:** Without interleaving: + - Permutation checks ~64 columns at once - **Relation degree: 65** - Sumcheck with degree-65 polynomials: impractical @@ -544,6 +588,7 @@ Without interleaving: - Unusable in production With interleaving: + - Permutation checks only 5 columns at once - **Relation degree: 7** - Circuit size: 131,072 rows (16Γ— increase, acceptable trade-off) @@ -562,14 +607,15 @@ The Translator circuit uses **81 witness polynomials** (no selector polynomials) These contain the raw data from the EC operation queue: -| Wire | Description | Range | -|------|-------------|-------| -| `OP` | Operation code | {0, 1, 2, 3, 4, 8} | -| `X_LOW_Y_HI` | P.x_lo (136-bit) at even rows, P.y_hi (118-bit) at odd rows | < 2¹³⁢ or < 2¹¹⁸ | -| `X_HIGH_Z_1` | P.x_hi (118-bit) at even rows, z₁ (128-bit) at odd rows | < 2¹¹⁸ or < 2¹²⁸ | -| `Y_LOW_Z_2` | P.y_lo (136-bit) at even rows, zβ‚‚ (128-bit) at odd rows | < 2¹³⁢ or < 2¹²⁸ | +| Wire | Description | Range | +| ------------ | ----------------------------------------------------------- | ------------------ | +| `OP` | Operation code | {0, 1, 2, 3, 4, 8} | +| `X_LOW_Y_HI` | P.x_lo (136-bit) at even rows, P.y_hi (118-bit) at odd rows | < 2¹³⁢ or < 2¹¹⁸ | +| `X_HIGH_Z_1` | P.x_hi (118-bit) at even rows, z₁ (128-bit) at odd rows | < 2¹¹⁸ or < 2¹²⁸ | +| `Y_LOW_Z_2` | P.y_lo (136-bit) at even rows, zβ‚‚ (128-bit) at odd rows | < 2¹³⁢ or < 2¹²⁸ | **Note:** The circuit operates in a 2-row cycle: + - **Even rows (accumulation):** Compute new accumulator value - **Odd rows (copy):** Transfer accumulator to next cycle @@ -578,14 +624,17 @@ These contain the raw data from the EC operation queue: These decompose coordinates and z-values into 68-bit limbs: **P.x limbs (4 wires):** + - `P_X_LOW_LIMBS`: Two 68-bit limbs from P.x_lo - `P_X_HIGH_LIMBS`: One 68-bit + one 50-bit limb from P.x_hi **P.y limbs (4 wires):** + - `P_Y_LOW_LIMBS`: Two 68-bit limbs from P.y_lo - `P_Y_HIGH_LIMBS`: One 68-bit + one 50-bit limb from P.y_hi **z limbs (4 wires):** + - `Z_LOW_LIMBS`: 68-bit limbs of z₁ and zβ‚‚ (low parts) - `Z_HIGH_LIMBS`: 60-bit limbs of z₁ and zβ‚‚ (high parts) @@ -593,12 +642,12 @@ These decompose coordinates and z-values into 68-bit limbs: Store current and previous accumulator values: -| Wire | Description | Bits per limb | -|------|-------------|---------------| -| `ACCUMULATORS_BINARY_LIMBS_0` | Limb 0 (current & previous) | 68 bits | -| `ACCUMULATORS_BINARY_LIMBS_1` | Limb 1 (current & previous) | 68 bits | -| `ACCUMULATORS_BINARY_LIMBS_2` | Limb 2 (current & previous) | 68 bits | -| `ACCUMULATORS_BINARY_LIMBS_3` | Limb 3 (current & previous) | 50 bits | +| Wire | Description | Bits per limb | +| ----------------------------- | --------------------------- | ------------- | +| `ACCUMULATORS_BINARY_LIMBS_0` | Limb 0 (current & previous) | 68 bits | +| `ACCUMULATORS_BINARY_LIMBS_1` | Limb 1 (current & previous) | 68 bits | +| `ACCUMULATORS_BINARY_LIMBS_2` | Limb 2 (current & previous) | 68 bits | +| `ACCUMULATORS_BINARY_LIMBS_3` | Limb 3 (current & previous) | 50 bits | **Layout:** Previous accumulator is at higher indices (row i+1) due to KZG commitment structure. @@ -606,20 +655,21 @@ Store current and previous accumulator values: The quotient from dividing by q: -| Wire | Description | -|------|-------------| -| `QUOTIENT_LOW_BINARY_LIMBS` | Lower two 68-bit limbs | +| Wire | Description | +| ---------------------------- | ---------------------------- | +| `QUOTIENT_LOW_BINARY_LIMBS` | Lower two 68-bit limbs | | `QUOTIENT_HIGH_BINARY_LIMBS` | One 68-bit + one 52-bit limb | ### Category 5: Relation Wide Limbs (1 wire) Used for modulo 2²⁷² computation: -| Wire | Description | Bits | -|------|-------------|------| +| Wire | Description | Bits | +| --------------------- | ------------------------------------- | ------------ | | `RELATION_WIDE_LIMBS` | Carries for 136-bit computation steps | 84 bits each | Contains two values: + - **relation_wide_lower_limb:** Carry from lower 136-bit computation - **relation_wide_higher_limb:** Carry from higher 136-bit computation @@ -628,10 +678,12 @@ Contains two values: Each limb is further decomposed into 14-bit microlimbs for tight range constraints: **Pattern for each element (P.x_lo, P.x_hi, P.y_lo, P.y_hi, z₁_lo, z₁_hi, zβ‚‚_lo, zβ‚‚_hi, acc_lo, acc_hi, quot_lo, quot_hi):** + - `*_RANGE_CONSTRAINT_0` through `*_RANGE_CONSTRAINT_4`: Five 14-bit microlimbs - `*_RANGE_CONSTRAINT_TAIL`: Shifted highest microlimb (for stricter constraint) Examples: + ``` P_X_LOW_LIMBS_RANGE_CONSTRAINT_0 // Microlimb 0 (bits 0-13) P_X_LOW_LIMBS_RANGE_CONSTRAINT_1 // Microlimb 1 (bits 14-27) @@ -641,9 +693,11 @@ P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL // Microlimb 4 << 4 (for exact 68-bit constr ``` **Relation wide limb microlimbs (4 wires):** + - `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0` through `_3`: Four 14-bit chunks Total range constraint wires: + - 10 elements Γ— 6 microlimbs = 60 wires - But relation_wide_limbs only needs 4 microlimbs - **Total: 56 microlimb wires** @@ -652,8 +706,8 @@ Total range constraint wires: Used for the permutation argument to prove all microlimbs are ≀ 2¹⁴ - 1: -| Wire | Description | -|------|-------------| +| Wire | Description | +| ----------------------------- | ---------------------------------- | | `ordered_range_constraints_0` | Sorted values for constraint set 0 | | `ordered_range_constraints_1` | Sorted values for constraint set 1 | | `ordered_range_constraints_2` | Sorted values for constraint set 2 | @@ -674,15 +728,15 @@ Instead, the circuit uses **Lagrange polynomials** to control which constraints ### Lagrange Polynomials (Precomputed) -| Polynomial | Description | Active Rows | -|------------|-------------|-------------| -| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | i ∈ {0, 2, 4, ..., 8190} (mini) | -| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | i ∈ {1, 3, 5, ..., 8191} (mini) | -| `lagrange_first` | First row | i = 0 | -| `lagrange_last_in_minicircuit` | Last row in mini-circuit | i = 8191 (mini) | -| `lagrange_result_row` | Row containing final result | Specific row in trace | -| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | -| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | +| Polynomial | Description | Active Rows | +| ------------------------------ | ------------------------------- | ------------------------------- | +| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | i ∈ {0, 2, 4, ..., 8190} (mini) | +| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | i ∈ {1, 3, 5, ..., 8191} (mini) | +| `lagrange_first` | First row | i = 0 | +| `lagrange_last_in_minicircuit` | Last row in mini-circuit | i = 8191 (mini) | +| `lagrange_result_row` | Row containing final result | Specific row in trace | +| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | +| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | **Why no selectors?** The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange polynomials, which are more efficient than custom selectors. @@ -703,6 +757,7 @@ The Translator circuit enforces correctness through **7 distinct relations** tot $$\boxed{(z_{\text{perm}} + L_0) \cdot \prod_{j=0}^{4} (\text{interleaved}_j + \beta \cdot L_{\text{mask}} + \gamma) = (z_{\text{perm,shift}} + L_{\text{last}}) \cdot \prod_{j=0}^{4} (\text{ordered}_j + \beta \cdot L_{\text{mask}} + \gamma)}$$ Where: + - **Numerator:** Product over 4 interleaved range constraint wires + 1 extra numerator - **Denominator:** Product over 5 ordered range constraint wires - **Masking:** `lagrange_masking` marks ZK rows to exclude from permutation @@ -774,6 +829,7 @@ For standard 68-bit limbs: $$\boxed{L_{\text{even}} \cdot \left( \text{limb} - \sum_{k=0}^{4} 2^{14k} \cdot \text{micro}_k - 2^{68} \cdot \text{micro}_{tail} \right) = 0}$$ Example for P.x limb 0: + ``` P_X_LOW_LIMBS[0] = P_X_LOW_LIMBS_RANGE_CONSTRAINT_0 + @@ -820,6 +876,7 @@ Compute the formula using only limbs [0] and parts of limbs [1], check that resu $$\boxed{L_{\text{even}} \cdot \left( \text{LOWER\_COMPUTATION} - 2^{136} \cdot \text{relation\_wide\_lower\_limb} \right) = 0}$$ Where `LOWER_COMPUTATION` includes: + ``` acc_prev[0]Β·x[0] + op + P_x[0]Β·v[0] + P_y[0]Β·vΒ²[0] + z₁[0]Β·vΒ³[0] + zβ‚‚[0]Β·v⁴[0] + quot[0]Β·(-q)[0] - acc_curr[0] @@ -840,6 +897,7 @@ Use `relation_wide_lower_limb` as carry and compute for limbs [2], [3]: $$\boxed{L_{\text{even}} \cdot \left( \text{HIGHER\_COMPUTATION} - 2^{136} \cdot \text{relation\_wide\_higher\_limb} \right) = 0}$$ Where `HIGHER_COMPUTATION` includes: + ``` relation_wide_lower_limb + combinations of limbs: (0,2), (1,1), (2,0), (0,3), (1,2), (2,1), (3,0), ... @@ -855,6 +913,7 @@ Reconstruct full elements in 𝔽r and check directly: $$\boxed{L_{\text{even}} \cdot \text{NATIVE\_CHECK} = 0}$$ Where: + ``` NATIVE_CHECK = acc_prev_native Β· x_native + op + P_x_native Β· v_native + P_y_native Β· vΒ²_native @@ -863,6 +922,7 @@ NATIVE_CHECK = ``` And: + ``` acc_prev_native = acc_prev[0] + 2^68Β·acc_prev[1] + 2^136Β·acc_prev[2] + 2^204Β·acc_prev[3] (mod r) ``` @@ -870,6 +930,7 @@ acc_prev_native = acc_prev[0] + 2^68Β·acc_prev[1] + 2^136Β·acc_prev[2] + 2^204Β· **Degree:** 4 (lagrange Γ— triple products like accΒ·x) **Soundness argument:** + - If the relation holds mod 2²⁷² AND mod r - AND all values are properly range-constrained - THEN 2²⁷² Β· r > 2⁡¹⁴ > max_possible_value @@ -950,6 +1011,7 @@ $$\boxed{\neg(L_{\text{in\_mini}} \lor L_{\text{mask}}) \implies \text{wire}_i = ### Proof System Type **TranslatorFlavor** uses: + - **HyperNova-style sumcheck** with ZK (zero-knowledge) - **KZG polynomial commitment scheme** over BN254 - **Libra** for ZK masking @@ -977,6 +1039,7 @@ struct TranslatorProverInput { ``` **Construction:** + 1. For each `UltraOp` in the queue, generate witness values: - Decompose P.x, P.y, z₁, zβ‚‚ into limbs and microlimbs - Compute quotient and new accumulator @@ -1029,6 +1092,7 @@ struct TranslatorProof { ``` The proof contains: + 1. Witness commitments (88 Γ— 2 = 176 Fr elements) 2. Libra commitments and sum (2 + 1 = 3 Fr) 3. Sumcheck univariates (17 rounds Γ— 8 coefficients = 136 Fr) @@ -1085,37 +1149,38 @@ As computed in CHONK_MATH_EXPLAINED.md, the Translator proof size is: ### Detailed Breakdown -| Component | Formula | Field Elements | -|-----------|---------|----------------| -| 1. Accumulated result (BN254 Fq) | `1 Γ— 1` | **1** | -| 2. Witness commitments | `88 Γ— 2` | **176** | -| 3. Libra concatenation commitment | `1 Γ— 2` | **2** | -| 4. Libra sum | `1 Γ— 1` | **1** | -| 5. Sumcheck univariates | `17 Γ— 8 Γ— 1` | **136** | -| 6. Sumcheck evaluations | `188 Γ— 1` | **188** | -| 7. Libra claimed evaluation | `1 Γ— 1` | **1** | -| 8. Libra grand sum commitment | `1 Γ— 2` | **2** | -| 9. Libra quotient commitment | `1 Γ— 2` | **2** | -| 10. Gemini fold commitments | `16 Γ— 2` | **32** | -| 11. Gemini evaluations | `17 Γ— 1` | **17** | -| 12. Gemini P positive evaluation | `1 Γ— 1` | **1** | -| 13. Gemini P negative evaluation | `1 Γ— 1` | **1** | -| 14. SmallSubgroupIPA evals | `4 Γ— 1` | **4** | -| 15. Shplonk Q commitment | `1 Γ— 2` | **2** | -| 16. KZG opening commitment | `1 Γ— 2` | **2** | +| Component | Formula | Field Elements | +| --------------------------------- | ------------ | -------------- | +| 1. Accumulated result (BN254 Fq) | `1 Γ— 1` | **1** | +| 2. Witness commitments | `88 Γ— 2` | **176** | +| 3. Libra concatenation commitment | `1 Γ— 2` | **2** | +| 4. Libra sum | `1 Γ— 1` | **1** | +| 5. Sumcheck univariates | `17 Γ— 8 Γ— 1` | **136** | +| 6. Sumcheck evaluations | `188 Γ— 1` | **188** | +| 7. Libra claimed evaluation | `1 Γ— 1` | **1** | +| 8. Libra grand sum commitment | `1 Γ— 2` | **2** | +| 9. Libra quotient commitment | `1 Γ— 2` | **2** | +| 10. Gemini fold commitments | `16 Γ— 2` | **32** | +| 11. Gemini evaluations | `17 Γ— 1` | **17** | +| 12. Gemini P positive evaluation | `1 Γ— 1` | **1** | +| 13. Gemini P negative evaluation | `1 Γ— 1` | **1** | +| 14. SmallSubgroupIPA evals | `4 Γ— 1` | **4** | +| 15. Shplonk Q commitment | `1 Γ— 2` | **2** | +| 16. KZG opening commitment | `1 Γ— 2` | **2** | **Total: 568 field elements = 568 Γ— 32 bytes = 18,176 bytes β‰ˆ 17.8 KB** ### Comparison with Other Components -| Component | Size (field elements) | Size (KB) | Percentage of Chonk | -|-----------|----------------------|-----------|---------------------| -| **Translator** | **568** | **17.8** | **37.6%** | -| Mega ZK | 356 | 11.1 | 23.6% | -| ECCVM | 488 | 15.2 | 32.3% | -| Merge | 42 | 1.3 | 2.8% | +| Component | Size (field elements) | Size (KB) | Percentage of Chonk | +| -------------- | --------------------- | --------- | ------------------- | +| **Translator** | **568** | **17.8** | **37.6%** | +| Mega ZK | 356 | 11.1 | 23.6% | +| ECCVM | 488 | 15.2 | 32.3% | +| Merge | 42 | 1.3 | 2.8% | **Insight:** Translator is the **largest single component** in the Chonk proof, primarily due to: + 1. 188 sumcheck evaluations (all 91 witness + 86 derived + shifts) 2. 136 sumcheck univariates (17 rounds Γ— 8 coefficients) 3. 176 witness commitments (88 polynomials) @@ -1131,14 +1196,17 @@ Ranked from most to least critical for security: ### πŸ”΄ **CRITICAL (Audit First)** #### 1. Non-Native Field Relation (Relation 4) + **File:** `translator_non_native_field_relation.hpp` **Why critical:** + - **Core soundness:** This is the heart of the circuit. If this relation is wrong, the entire translation is invalid. - **Complex arithmetic:** Involves intricate modular arithmetic across two moduli with limb-based computation. - **Overflow risks:** If the mod 2²⁷² check is wrong, overflow could allow false proofs. **What to audit:** + - Verify the limb combination formulas match the mathematical specification exactly - Check all powers of 2 (2⁢⁸, 2¹³⁢, etc.) are correct - Ensure the "wide" relation limbs correctly capture carries @@ -1148,14 +1216,17 @@ Ranked from most to least critical for security: **Attack vector:** Incorrect arithmetic could allow proving wrong evaluations, breaking Goblin soundness. #### 2. Permutation Relation (Relation 1) + **File:** `translator_permutation_relation.hpp` **Why critical:** + - **Foundation for range constraints:** If permutation is broken, attacker can use out-of-range values. - **Grand product soundness:** The z_perm computation must be absolutely correct. - **Masking handling:** ZK rows must be properly excluded. **What to audit:** + - Verify grand product formula matches the specification - Check initialization (z_perm[0] = 1 accounting for L_0) - Verify finalization (z_perm[last] = 0 accounting for L_last and masking) @@ -1165,14 +1236,17 @@ Ranked from most to least critical for security: **Attack vector:** Broken permutation β†’ use 2⁢⁸ instead of 2¹⁴ limbs β†’ completely break non-native arithmetic. #### 3. Delta Range Constraint Relation (Relation 2) + **File:** `translator_delta_range_constraint_relation.hpp` **Why critical:** + - **Enforces sorted property:** Without this, permutation check is meaningless. - **Maximum value check:** Must ensure final value is exactly 2¹⁴ - 1. - **Step constraint:** Max step of 3 is necessary for coverage. **What to audit:** + - Verify Ξ” ∈ {0,1,2,3} check is correctly implemented - Confirm final value check at lagrange_last is exact - Check masking rows are properly excluded @@ -1183,14 +1257,17 @@ Ranked from most to least critical for security: ### 🟠 **HIGH PRIORITY** #### 4. Decomposition Relation (Relation 3) + **File:** `translator_decomposition_relation.hpp` **Why high priority:** + - **Ensures consistency:** Limbs must match original values. - **Many subrelations (48):** More code = more potential bugs. - **Tail microlimb logic:** The shift factors must be exact. **What to audit:** + - Verify all 48 decomposition formulas match specification - Check powers of 2 are correct (2⁢⁸, 2¹⁴, etc.) - Confirm tail shift calculations (especially the Γ—4, Γ—16 multipliers) @@ -1199,13 +1276,16 @@ Ranked from most to least critical for security: **Attack vector:** Wrong decomposition β†’ mismatch between transcript and limbs β†’ arbitrary values. #### 5. Opcode Constraint Relation (Relation 5) + **File:** `translator_extra_relations.hpp` **Why high priority:** + - **Input validation:** Invalid opcodes could inject malicious data. - **Relatively simple:** But critical to get right. **What to audit:** + - Verify opcode set {0, 1, 2, 3, 4, 8} is complete and correct - Check polynomial roots match opcodes exactly - Ensure masking rows are handled @@ -1215,13 +1295,16 @@ Ranked from most to least critical for security: ### 🟑 **MEDIUM PRIORITY** #### 6. Accumulator Transfer Relation (Relation 6) + **File:** `translator_extra_relations.hpp` **Why medium priority:** + - **Ensures state consistency:** But doesn't directly affect arithmetic soundness. - **Edge cases:** Initialization and finalization must be correct. **What to audit:** + - Verify odd row copy constraint is active at all odd rows - Check initialization to zero at start - Confirm final result comparison uses correct expected value @@ -1230,13 +1313,16 @@ Ranked from most to least critical for security: **Attack vector:** Wrong initialization β†’ start with non-zero acc β†’ offset all computations. #### 7. Zero Constraints Relation (Relation 7) + **File:** `translator_extra_relations.hpp` **Why medium priority:** + - **Cleanup relation:** Ensures unused rows don't pollute permutation. - **Many subrelations (68):** But mostly repetitive. **What to audit:** + - Verify all 68 wires are covered - Check lagrange polynomial logic for "outside minicircuit" - Ensure no-op case (op = 0) is handled correctly @@ -1246,25 +1332,31 @@ Ranked from most to least critical for security: ### 🟒 **LOW PRIORITY (But Still Check)** #### 8. Circuit Builder Logic + **File:** `translator_circuit_builder.cpp` **Why low priority for audit:** + - Prover-side only (doesn't affect verification soundness directly) - But bugs here could cause proof generation failures **What to check:** + - Witness generation formulas match relation formulas - Quotient calculation is correct - Microlimb splitting logic matches decomposition relation #### 9. Flavor Configuration + **File:** `translator_flavor.hpp` **Why low priority:** + - Configuration and constants - But errors here (wrong NUM_LIMB_BITS) would be catastrophic **What to check:** + - All constants match specification - Proof length formula is correct - Polynomial commitment configuration is sound @@ -1276,6 +1368,7 @@ Ranked from most to least critical for security: Use this checklist when auditing the Translator: ### Mathematical Specification + - [ ] Verify q (Fq modulus) is correct BN254 base field - [ ] Verify r (Fr modulus) is correct BN254 scalar field - [ ] Confirm 2²⁷² Β· r > 2⁡¹⁴ (soundness bound) @@ -1284,6 +1377,7 @@ Use this checklist when auditing the Translator: - [ ] Confirm SORT_STEP = 3 is sufficient for coverage ### Non-Native Field Arithmetic + - [ ] Audit all limb combination formulas in subrelation 4.1 - [ ] Audit all limb combination formulas in subrelation 4.2 - [ ] Verify native field reconstruction in subrelation 4.3 @@ -1292,6 +1386,7 @@ Use this checklist when auditing the Translator: - [ ] Test with adversarial quotients ### Range Constraints + - [ ] Verify permutation grand product formula - [ ] Check delta constraint polynomial (degree 5 product) - [ ] Confirm final value = 2¹⁴ - 1 exactly @@ -1299,12 +1394,14 @@ Use this checklist when auditing the Translator: - [ ] Test with values > 2¹⁴ ### Decomposition + - [ ] Verify all 6 binary limb decompositions - [ ] Verify all 44 microlimb decompositions - [ ] Check all 42 tail microlimb stricter constraints - [ ] Test with wrong decompositions ### Edge Cases + - [ ] First row (initialization) - [ ] Last row (finalization) - [ ] No-op case (op = 0) @@ -1312,6 +1409,7 @@ Use this checklist when auditing the Translator: - [ ] Interleaving boundary ### Implementation + - [ ] Code review all relation implementations - [ ] Verify relation degrees match specification - [ ] Check lagrange polynomial usage is correct From 3a1a162d0c48d126bab50cc452b775f37bf018e8 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Thu, 11 Dec 2025 13:11:17 +0000 Subject: [PATCH 10/29] fixes. --- .../src/barretenberg/translator_vm/README.md | 478 +++--------------- .../barretenberg/translator_vm/RELATIONS.md | 2 +- 2 files changed, 62 insertions(+), 418 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 4a9a8173950a..3d3727f40169 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -1,4 +1,6 @@ -# The Translator Circuit: Complete Technical Specification +# The Translator Circuit + +> $\textcolor{orange}{\textsf{Warning}}$: This document provides a technical overview of the Translator Circuit used in the Goblin Plonk proving system. It is intended for understanding the design and optimizations. The code is the source of truth for implementation specifics. ## Table of Contents @@ -162,440 +164,82 @@ Each microlimb must be $≀ 2^{14} - 1 = 16383$. ## Interleaving: The Key Optimization -### Why Interleaving is Necessary - -The Translator needs to perform range constraints on ~64 different microlimb sets using a permutation argument. Without optimization, this creates a major problem with the relation degree. - -**The Core Issue: Permutation Argument Degree** - -In a permutation argument, the degree of the relation is determined by **how many columns** are being permuted simultaneously: - -``` -Grand product relation: -z_perm[i+1] Γ— ∏_{j=1}^{NUM_COLS} (ordered[j] + Ξ² + Ξ³) = -z_perm[i] Γ— ∏_{j=1}^{NUM_COLS} (interleaved[j] + Ξ² + Ξ³) - -Degree = 1 + NUM_COLS (polynomial z_perm Γ— product of NUM_COLS columns) -``` +The Translator must range-constrain approximately 64 different microlimb sets using permutation argument. The permutation argument's degree equals $1 + \text{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: $$ z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \beta + \gamma) = z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \beta + \gamma) $$ -**The Translator's Challenge:** - -- We have **~64 different logical microlimb columns** that need range constraints: - - P.x: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns - - P.y: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns - - z₁, zβ‚‚: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns - - Accumulator: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns - - Quotient: 4 limbs Γ— 6 microlimbs each = 24 microlimb columns - - Relation wide limbs: 2 Γ— 6 microlimbs = 12 microlimb columns - - **Total: ~130 logical microlimb columns** (many reuse physical wires) +**The Problem:** Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. -**Naive approach:** -If we tried to permute all ~64 active columns at once: +**The Solution:** Interleave 16 logical column groups into the same 5 physical wires across 16 circuit segments. Each segment performs an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree by 9Γ—. -- Degree = 1 + 64 = **65** -- This is **prohibitively expensive** for sumcheck! -- The relation would dominate proof generation time -- Higher degree = more FFT operations, more commitment cost - -**The Solution: Interleaving to Reduce Column Count** - -Instead of checking 64 columns in one permutation, we: - -1. **Group 16 logical columns together** and pack them into the circuit at different row segments -2. **Use only 5 physical wires** for each permutation check (4 interleaved + 1 extra numerator) -3. **Reuse these 5 wires across 16 different segments** of the circuit -4. Each segment checks a different subset of ~4 logical columns from the original 64 - -**Result:** - -- Relation degree: 1 + 5 = **6** (plus Lagrange = 7 total) -- This is manageable for the proof system! -- We perform 16 separate permutation checks (one per segment), each with low degree - -### How Interleaving Works - -#### The Basic Concept - -**Mini-circuit vs. Full Circuit:** +### Circuit Structure ``` -Mini-circuit size: 2^13 = 8,192 rows (where actual computation happens) +Mini-circuit size: 2^13 = 8,192 rows (actual computation) Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) - -Relationship: FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE - 131,072 = 8,192 Γ— 16 -``` - -**Key idea:** Instead of 64+ columns in one permutation check (degree 65+), we group logical columns together and reuse 5 physical columns across 16 circuit segments (degree 7). - -#### The Interleaving Structure - -For each **set of range constraint wires** (e.g., all P.x microlimbs), we create two types of polynomials: - -**1. Interleaved Polynomials** (in full circuit) - -- Size: 131,072 (full circuit size) -- Contains microlimbs from **multiple mini-circuit rows** packed together - -**2. Ordered Polynomials** (in full circuit) - -- Size: 131,072 (full circuit size) -- Contains the **sorted version** of the interleaved values - -### Detailed Interleaving Mapping - -Let's trace exactly how microlimbs from the mini-circuit map to the full circuit: - -#### Example: P.x Low Limbs Range Constraint 0 (First Microlimb) - -**In the mini-circuit:** Each even row i ∈ {0, 2, 4, ..., 8190} generates a microlimb value: - -``` -mini_row 0 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[0] = micro_0_0 -mini_row 2 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[2] = micro_0_2 -mini_row 4 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[4] = micro_0_4 -... -mini_row 8190 β†’ P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[8190] = micro_0_8190 -``` - -Total: ~4,096 microlimbs (half of 8,192 rows, since only even rows are active). - -**Interleaving into full circuit:** - -These 4,096 values are **interleaved** into 16 groups: - -``` -Group 0: mini_rows {0, 32, 64, 96, ...} β†’ full_circuit rows {0, 1, 2, 3, ...} -Group 1: mini_rows {2, 34, 66, 98, ...} β†’ full_circuit rows {8192, 8193, 8194, ...} -Group 2: mini_rows {4, 36, 68, 100, ...} β†’ full_circuit rows {16384, 16385, 16386, ...} -... -Group 15: mini_rows {30, 62, 94, 126, ...} β†’ full_circuit rows {122880, 122881, 122882, ...} -``` - -**Formula:** - -``` -For mini_row = 2k (even rows only): - group_id = k mod 16 - position_in_group = k Γ· 16 - - full_circuit_row = group_id Γ— 8192 + position_in_group -``` - -**Example calculation:** - -``` -mini_row = 64 (32nd even row, so k = 32) - group_id = 32 mod 16 = 0 - position = 32 Γ· 16 = 2 - full_circuit_row = 0 Γ— 8192 + 2 = 2 - -mini_row = 66 (33rd even row, so k = 33) - group_id = 33 mod 16 = 1 - position = 33 Γ· 16 = 2 - full_circuit_row = 1 Γ— 8192 + 2 = 8194 -``` - -### The Complete Circuit Trace Structure - -Here's the exact layout of the full circuit with interleaving: - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ FULL CIRCUIT (2^17 = 131,072 rows) β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ β”‚ -β”‚ INTERLEAVED GROUP 0 Rows 0-8191 β”‚ -β”‚ β”œβ”€ Contains values from mini_rows: 0, 32, 64, 96, ... β”‚ -β”‚ β”œβ”€ interleaved_range_constraints_0[i] for i ∈ [0, 8191] β”‚ -β”‚ └─ ordered_range_constraints_0[i] = sorted version β”‚ -β”‚ β”‚ -β”‚ INTERLEAVED GROUP 1 Rows 8192-16383 β”‚ -β”‚ β”œβ”€ Contains values from mini_rows: 2, 34, 66, 98, ... β”‚ -β”‚ β”œβ”€ interleaved_range_constraints_1[i] β”‚ -β”‚ └─ ordered_range_constraints_1[i] = sorted version β”‚ -β”‚ β”‚ -β”‚ INTERLEAVED GROUP 2 Rows 16384-24575 β”‚ -β”‚ β”œβ”€ Contains values from mini_rows: 4, 36, 68, 100, ... β”‚ -β”‚ β”œβ”€ interleaved_range_constraints_2[i] β”‚ -β”‚ └─ ordered_range_constraints_2[i] = sorted version β”‚ -β”‚ β”‚ -β”‚ INTERLEAVED GROUP 3 Rows 24576-32767 β”‚ -β”‚ β”œβ”€ Contains values from mini_rows: 6, 38, 70, 102, ... β”‚ -β”‚ β”œβ”€ interleaved_range_constraints_3[i] β”‚ -β”‚ └─ ordered_range_constraints_3[i] = sorted version β”‚ -β”‚ β”‚ -β”‚ ... β”‚ -β”‚ (Groups 4-14 follow same pattern) β”‚ -β”‚ ... β”‚ -β”‚ β”‚ -β”‚ INTERLEAVED GROUP 15 Rows 122880-131071β”‚ -β”‚ β”œβ”€ Contains values from mini_rows: 30, 62, 94, 126, ... β”‚ -β”‚ β”œβ”€ interleaved_range_constraints_4[i] (reuses wire 4) β”‚ -β”‚ └─ ordered_range_constraints_4[i] = sorted version β”‚ -β”‚ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -**Important observation:** We only have **5 physical wires** for range constraints: - -- `ordered_range_constraints_0` through `ordered_range_constraints_4` -- `interleaved_range_constraints_0` through `interleaved_range_constraints_3` -- Plus one extra numerator wire - -But we need to check **many more** microlimb sets. The solution: - -- Each wire is **reused across different interleaving groups** -- Within each 8,192-row segment, the wire represents a different logical microlimb set -- The permutation argument operates **within each segment independently** - -### Why Interleaving Reduces Relation Degree - -**The Critical Insight: Degree = Number of Columns in Product** - -The permutation relation has the form: - -``` -z_perm[i+1] Γ— ∏_{j=0}^{NUM_COLS-1} (ordered[j][i] + Ξ² + Ξ³) = -z_perm[i] Γ— ∏_{j=0}^{NUM_COLS-1} (interleaved[j][i] + Ξ² + Ξ³) -``` - -**Degree = 1 (from z_perm) + NUM_COLS (from the products)** - -**Without interleaving (naive approach):** - -``` -Check all ~64 logical microlimb columns in one relation: - -Relation: - z_perm[i+1] Γ— ∏_{j=0}^{63} (ordered[j][i] + Ξ² + Ξ³) = - z_perm[i] Γ— ∏_{j=0}^{63} (interleaved[j][i] + Ξ² + Ξ³) - -DEGREE = 1 + 64 = 65 - -This creates a degree-65 relation! -- Sumcheck round complexity: 65 univariate polynomials per round -- FFT operations: O(n Β· 65) -- Prover time: dominated by high-degree relation -- **Completely impractical!** +FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE = 8,192 Γ— 16 ``` -**With interleaving (only 5 physical columns per check):** +To compute the interleaved polynomials, we group 16 polynomials together and interleave their coefficients. Consider the following 16 polynomials each of size $n=2^{13}$ in the mini-circuit: -``` -Group 16 logical columns together, use 5 physical wires per segment: - -Relation (same for all 16 segments): - z_perm[i+1] Γ— (ordered_0[i] + Ξ² + Ξ³) - Γ— (ordered_1[i] + Ξ² + Ξ³) - Γ— (ordered_2[i] + Ξ² + Ξ³) - Γ— (ordered_3[i] + Ξ² + Ξ³) - Γ— (ordered_4[i] + Ξ² + Ξ³) - = z_perm[i] Γ— (interleaved_0[i] + Ξ² + Ξ³) - Γ— (interleaved_1[i] + Ξ² + Ξ³) - Γ— (interleaved_2[i] + Ξ² + Ξ³) - Γ— (interleaved_3[i] + Ξ² + Ξ³) - Γ— (extra_numerator[i] + Ξ² + Ξ³) - -DEGREE = 1 + 5 = 6 (or 7 with Lagrange selector) - -Much more manageable! -``` - -**Degree reduction: 65 β†’ 7 (more than 9Γ— reduction!)** - -**How it works:** - -- **Segment 0** (rows 0-8,191): Wires represent logical columns {0, 1, 2, 3, 4} -- **Segment 1** (rows 8,192-16,383): Same wires represent logical columns {5, 6, 7, 8, 9} -- **Segment 2** (rows 16,384-24,575): Same wires represent logical columns {10, 11, 12, 13, 14} -- ... and so on for 16 segments - -Each segment checks a different subset of logical columns, but all use the **same low-degree relation**! - -### The Permutation Check with Interleaving - -The permutation relation operates **within each 8,192-row segment**: - -**For segment s ∈ {0, 1, ..., 15}:** - -``` -Base row index: base = s Γ— 8,192 - -For row i within segment [0, 8191]: - full_row = base + i - - z_perm[full_row + 1] Γ— DENOMINATOR = z_perm[full_row] Γ— NUMERATOR - - Where: - NUMERATOR = (interleaved_0[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (interleaved_1[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (interleaved_2[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (interleaved_3[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (extra_numerator[full_row] + Ξ²Β·L_mask + Ξ³) - - DENOMINATOR = (ordered_0[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (ordered_1[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (ordered_2[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (ordered_3[full_row] + Ξ²Β·L_mask + Ξ³) - Γ— (ordered_4[full_row] + Ξ²Β·L_mask + Ξ³) -``` - -**Key insight:** The permutation argument doesn't know or care that these values came from different mini-circuit rows. It just checks that within each 8,192-row segment, the interleaved values are a permutation of the ordered values. - -### Concrete Example: Tracing One Microlimb - -Let's trace one specific microlimb through the entire system: - -**Setup:** - -- We're checking P.x_low_limbs[0] (first 68-bit limb of P.x's lower 136 bits) -- At mini_row = 100 (even row, 50th accumulation) -- The value of the first 14-bit microlimb is: `micro = 0x2A5F = 10847` - -**Step 1: Mini-circuit computation (row 100)** - -``` -P_X_LOW_LIMBS[0] = limb_value = 0x1234567890ABCDEF -Decompose into microlimbs: - P_X_LOW_LIMBS_RANGE_CONSTRAINT_0[100] = 0xCDEF = 52719 - P_X_LOW_LIMBS_RANGE_CONSTRAINT_1[100] = 0x9012 = 36882 - ... -``` - -**Step 2: Determine interleaving group** - -``` -k = 100 / 2 = 50 (since mini_row 100 is the 50th even row) -group_id = 50 mod 16 = 2 -position = 50 Γ· 16 = 3 -``` - -**Step 3: Map to full circuit** - -``` -full_circuit_row = 2 Γ— 8192 + 3 = 16384 + 3 = 16387 - -interleaved_range_constraints_2[16387] = 52719 -``` - -**Step 4: Sorting** - -All microlimbs in group 2 are collected and sorted: - -``` -interleaved_2 = [52719, 36882, ..., 4096 more values from group 2 mini-rows] -ordered_2 = sorted(interleaved_2) = [0, 0, 0, ..., 1, 1, 2, ..., 16383] - ↑ with step values inserted -``` - -**Step 5: Permutation check** - -The permutation relation verifies: - -``` -For full_circuit_row ∈ [16384, 24575] (group 2 segment): - - Accumulate in z_perm: - z_perm[16384] = 1 - z_perm[16385] = z_perm[16384] Γ— (interleaved_2[16384] + ...) / (ordered_2[16384] + ...) - ... - z_perm[16387] = ... includes our value 52719 ... - ... - z_perm[24575] should equal 1 (modulo public input delta) -``` - -If the permutation is valid, our microlimb `52719` is proven to be ≀ 16383. βœ“ - -### The Sorted Array Structure - -Each `ordered_range_constraints_j` polynomial contains: - -``` -Row 0: 0 -Row 1: 0 (possible duplicate) -Row 2: 0 (possible duplicate) -Row 3: 1 (step by 0 or 1 or 2 or 3) -Row 4: 3 (step by 2) -Row 5: 4 (step by 1) -Row 6: 7 (step by 3) -Row 7: 7 (possible duplicate, step by 0) -... -Row 5461: 16380 (step by 3) -Row 5462: 16383 (step by 3) -Row 5463: 16383 ← Last value must be exactly 16383 -``` - -With periodic "step" values inserted every few rows to ensure coverage of [0, 16383]. The delta range constraint relation enforces: - -1. Each step ∈ {0, 1, 2, 3} -2. Final value = 16383 - -### Benefits of Interleaving - -**1. Relation Degree Reduction (Most Important):** - -- **From degree 65 to degree 7** (9Γ— reduction) -- This is the primary benefit - keeps relations efficient -- Sumcheck complexity is dominated by max relation degree - -**2. Proof Size Stays Constant:** - -- Only need one z_perm polynomial -- Reuse it across all 16 segments -- Proof doesn't grow with number of groups - -**3. Verification Efficiency:** - -- Verifier checks same polynomial across segments -- No additional cost for more interleaving groups - -**4. Flexibility:** - -- Can adjust INTERLEAVING_GROUP_SIZE based on circuit size -- Balances polynomial degree vs. circuit size blowup - -### Trade-offs - -**Cost of interleaving:** - -- Circuit size increases by 16Γ— (from 8,192 to 131,072 rows) -- More zero padding needed (Relation 7 ensures unused rows are zero) -- More complex witness generation (need to correctly map mini-circuit to full circuit) - -**Why it's worth it:** - -- **Relation degree reduction** >>> circuit size increase -- Sumcheck is dominated by max relation degree -- Without interleaving, degree-65 relation would make the circuit impractical -- With interleaving, degree-7 is manageable for production use - -### Summary - -**Interleaving is the technique that makes the Translator practical:** - -Without interleaving: +$$ +\newcommand{\arraystretch}{1.2} +\begin{array}{|c|c|c|c|c|c|} +\hline +\textsf{index} & \textsf{poly 1} & \textsf{poly 2} & \textsf{poly 3} & \ldots & \textsf{poly 16} \\ +\hline +0 & \textcolor{skyblue}{a_0} & \textcolor{orange}{b_0} & \textcolor{lightgreen}{c_0} & \quad \ldots \quad & \textcolor{firebrick}{p_0} \\ +1 & \textcolor{skyblue}{a_1} & \textcolor{orange}{b_1} & \textcolor{lightgreen}{c_1} & \quad \ldots \quad & \textcolor{firebrick}{p_1} \\ +2 & \textcolor{skyblue}{a_2} & \textcolor{orange}{b_2} & \textcolor{lightgreen}{c_2} & \quad \ldots \quad & \textcolor{firebrick}{p_2} \\ +3 & \textcolor{skyblue}{a_3} & \textcolor{orange}{b_3} & \textcolor{lightgreen}{c_3} & \quad \ldots \quad & \textcolor{firebrick}{p_3} \\[5pt] +\vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\[5pt] +n-1 & \textcolor{skyblue}{a_{n-1}} & \textcolor{orange}{b_{n-1}} & \textcolor{lightgreen}{c_{n-1}} & \quad \ldots \quad & \textcolor{firebrick}{p_{n-1}} \\ +\hline +\end{array} +\quad \longrightarrow \quad +\begin{array}{|c|c|c|} +\hline +\textsf{group} & \textsf{index} & \textsf{interleaved} \\ +\hline +0 & 0 & \textcolor{skyblue}{a_0} \\ +0 & 1 & \textcolor{orange}{b_0} \\ +0 & 2 & \textcolor{lightgreen}{c_0} \\ +\vdots & \vdots & \vdots \\[3pt] +1 & 15 & \textcolor{firebrick}{p_0} \\ \hline +1 & 4 & \textcolor{skyblue}{a_1} \\ +1 & 5 & \textcolor{orange}{b_1} \\ +1 & 6 & \textcolor{lightgreen}{c_1} \\ +\vdots & \vdots & \vdots \\[3pt] +1 & 7 & \textcolor{firebrick}{p_1} \\ \hline +\vdots & \vdots & \vdots \\[5pt] +\vdots & \vdots & \vdots \\ \hline +n-1 & 4n-4 & \textcolor{skyblue}{a_{n-1}} \\ +n-1 & 4n-3 & \textcolor{orange}{b_{n-1}} \\ +n-1 & 4n-2 & \textcolor{lightgreen}{c_{n-1}} \\ +\vdots & \vdots & \vdots \\[3pt] +n-1 & 4n-1 & \textcolor{firebrick}{p_{n-1}} \\ +\hline +\end{array} +$$ -- Permutation checks ~64 columns at once -- **Relation degree: 65** -- Sumcheck with degree-65 polynomials: impractical -- Prover time: hours (if even feasible) -- Unusable in production +The resulting interleaved polynomial has size $16n = 2^{17}$. +For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: -With interleaving: +- **Numerator:** 4 interleaved wires + 1 extra = 5 terms +- **Denominator:** 5 ordered wires = 5 terms +- **Degree:** $1 + 5 = 6$ (or 7 with Lagrange) -- Permutation checks only 5 columns at once -- **Relation degree: 7** -- Circuit size: 131,072 rows (16Γ— increase, acceptable trade-off) -- Prover time: minutes -- **Production-ready! βœ“** +The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. -**The key insight:** Interleaving trades circuit size (cheap to increase) for relation degree (expensive if high). By grouping 16 logical columns together and reusing 5 physical wires across 16 circuit segments, we keep the relation degree low while still checking all necessary columns. +> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: The interleaved polynomials do not require separate commitments. During proving key construction, the prover computes them for use in sumcheck. In the Gemini PCS phase, the prover sends only **two additional field element evaluations** $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: +> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ +> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. The PCS proof grows by only **2 field elements**. +> +> For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: +> $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ --- diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index cba9d1e23ebe..4ea0c280db23 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -1,4 +1,4 @@ -# Translator Non-Native Field Relation: Complete Mathematical Derivation +# Translator Relations ## Document Purpose From 4249930b9c6c3dfb67fa9ec947491d8f220ace61 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Thu, 11 Dec 2025 13:19:25 +0000 Subject: [PATCH 11/29] move witness struct in main doc. --- .../src/barretenberg/translator_vm/README.md | 310 ++++++++++-------- .../barretenberg/translator_vm/RELATIONS.md | 140 -------- 2 files changed, 167 insertions(+), 283 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 3d3727f40169..869147431137 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -162,6 +162,173 @@ Each microlimb must be $≀ 2^{14} - 1 = 16383$. --- +## Witness Trace Structure + +The Translator circuit operates on a **2-row cycle structure**. Each EccOpQueue entry occupies exactly 2 rows: + +- **Row $2i$ (Even rows)**: **Computation rows** where the non-native field relation is actively checked +- **Row $2i+1$ (Odd rows)**: **Data storage rows** that hold values accessed by the next even row via shifts + +This architecture exists because of how polynomial commitments work in the KZG scheme: the "shifted" polynomial at index $i$ evaluates to the polynomial at index $i+1$. Thus: + +- Even row $2i$ performs computation using "current" values from its own row +- Even row $2i$ accesses "previous" values from odd row $2i+1$ via shift columns +- Odd row $2i+1$ stores the data that will become "previous" for the next computation at row $2i+2$ + +The Translator circuit has **81 witness columns** organized into several categories: + +#### 1. EccOpQueue Transcript Columns (4 columns) + +These columns directly represent the EccOpQueue transcript: + +| Column | Even Row (2i) | Odd Row (2i+1) | Description | +| ----------- | --------------------------------- | ---------------------------- | --------------------------------------------- | +| `OP` | $\texttt{op} \in \{0,1,2,3,4,8\}$ | 0 (no-op) | Opcode (the type of elliptic curve operation) | +| `X_LO_Y_HI` | $P_{x,\text{lo}}$ (136 bits) | $P_{y,\text{hi}}$ (118 bits) | Low 136 bits of P.x and High 118 bits of P.y | +| `X_HI_Z_1` | $P_{x,\text{hi}}$ (118 bits) | $z_1$ (128 bits) | High 118 bits of P.x and first scalar | +| `Y_LO_Z_2` | $P_{y,\text{lo}}$ (136 bits) | $z_2$ (128 bits) | Low 136 bits of P.y and second scalar | +| | | | | + +**Encoding scheme**: Point coordinates $P_x$ and $P_y$ are each 254 bits, split as: + +- $P_x = (P_{x,\text{hi}}$ (118 bits) $\|$ $P_{x,\text{lo}}$ (136 bits) $)$ +- $P_y = (P_{y,\text{hi}}$ (118 bits) $\|$ $P_{y,\text{lo}}$ (136 bits) $)$ + +#### 2. Limb Decomposition Columns (13 columns) + +These columns store finer-grained limb decompositions for non-native arithmetic: + +| Column Group | Even Row (2i) | Odd Row (2i+1) | Bits | Purpose | +| ----------------------------- | --------------------- | --------------------- | ------ | ---------------------------------------- | +| `P_X_LOW_LIMBS` | $P_{x,0}^{\text{lo}}$ | $P_{x,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{x,\text{lo}}$ | +| `P_X_HIGH_LIMBS` | $P_{x,0}^{\text{hi}}$ | $P_{x,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{x,\text{hi}}$ | +| `P_Y_LOW_LIMBS` | $P_{y,0}^{\text{lo}}$ | $P_{y,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{y,\text{lo}}$ | +| `P_Y_HIGH_LIMBS` | $P_{y,0}^{\text{hi}}$ | $P_{y,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{y,\text{hi}}$ | +| `Z_LOW_LIMBS` | $z_{1,0}$ | $z_{2,0}$ | 68 | Low limbs of $z_1$ and $z_2$ | +| `Z_HIGH_LIMBS` | $z_{1,1}$ | $z_{2,1}$ | 60 | High limbs of $z_1$ and $z_2$ | +| `ACCUMULATORS_BINARY_LIMBS_0` | $a_0^{\text{curr}}$ | $a_0^{\text{prev}}$ | 68 | Limb 0 of current/previous accumulator | +| `ACCUMULATORS_BINARY_LIMBS_1` | $a_1^{\text{curr}}$ | $a_1^{\text{prev}}$ | 68 | Limb 1 of current/previous accumulator | +| `ACCUMULATORS_BINARY_LIMBS_2` | $a_2^{\text{curr}}$ | $a_2^{\text{prev}}$ | 68 | Limb 2 of current/previous accumulator | +| `ACCUMULATORS_BINARY_LIMBS_3` | $a_3^{\text{curr}}$ | $a_3^{\text{prev}}$ | 50 | Limb 3 of current/previous accumulator | +| `QUOTIENT_LOW_BINARY_LIMBS` | $q_0$ | $q_1$ | 68 | Limbs 0 & 1 of quotient $\mathcal{Q}$ | +| `QUOTIENT_HIGH_BINARY_LIMBS` | $q_2$ | $q_3$ | 68, 52 | Limbs 2 & 3 of quotient $\mathcal{Q}$ | +| `RELATION_WIDE_LIMBS` | $c^{\text{lo}}$ | $c^{\text{hi}}$ | 84 | Carry/overflow from mod $2^{136}$ checks | + +**Key insight**: The accumulator columns demonstrate the shift mechanism: + +- Even row stores $a^{\text{curr}}$ (result of current computation) +- Odd row stores what will become $a^{\text{prev}}$ (input to next computation) +- Via shifts, even row $2i$ reads odd row $2i+1$ to get "previous" values + +#### 3. Range Constraint Microlimb Columns (64 columns) + +Each limb is further decomposed into **14-bit microlimbs** for range checking. Each 68-bit limb has 5 microlimbs (14 bits each) plus a "tail" microlimb that enforces tight range constraints. The columns are organized as follows: + +| Column Group | Even Row (2i) | Odd Row (2i+1) | +| ---------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------- | +| Coordinate $P_x$ microlimbs | | | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_0` | $P_{x,0}[0]$ | $P_{x,1}[0]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_1` | $P_{x,0}[1]$ | $P_{x,1}[1]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_2` | $P_{x,0}[2]$ | $P_{x,1}[2]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_3` | $P_{x,0}[3]$ | $P_{x,1}[3]$ | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_4` | $P_{x,0}[4]$ | $P_{x,1}[4]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $P_{x,2}[0]$ | $P_{x,3}[0]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $P_{x,2}[1]$ | $P_{x,3}[1]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $P_{x,2}[2]$ | $P_{x,3}[2]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $P_{x,2}[3]$ | $P_{x,3}[3]$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $P_{x,2}[4]$ | $\textcolor{yellow}{P_{x,3}[\textsf{tail}]}$ (reassigned) | +| Coordinate $P_y$ microlimbs | | | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0` | $P_{y,0}[0]$ | $P_{y,1}[0]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_1` | $P_{y,0}[1]$ | $P_{y,1}[1]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_2` | $P_{y,0}[2]$ | $P_{y,1}[2]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_3` | $P_{y,0}[3]$ | $P_{y,1}[3]$ | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_4` | $P_{y,0}[4]$ | $P_{y,1}[4]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $P_{y,2}[0]$ | $P_{y,3}[0]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $P_{y,2}[1]$ | $P_{y,3}[1]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $P_{y,2}[2]$ | $P_{y,3}[2]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $P_{y,2}[3]$ | $P_{y,3}[3]$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $P_{y,2}[4]$ | $\textcolor{yellow}{P_{y,3}[\textsf{tail}]}$ (reassigned) | +| Coordinate $z_1$ microlimbs | | | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_0` | $z_{1,0}[0]$ | $z_{2,0}[0]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_1` | $z_{1,0}[1]$ | $z_{2,0}[1]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,0}[2]$ | $z_{2,0}[2]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_3` | $z_{1,0}[3]$ | $z_{2,0}[3]$ | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_4` | $z_{1,0}[4]$ | $z_{2,0}[4]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $z_{1,1}[0]$ | $z_{2,1}[0]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $z_{1,1}[1]$ | $z_{2,1}[1]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,1}[2]$ | $z_{2,1}[2]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $z_{1,1}[3]$ | $z_{2,1}[3]$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $z_{1,1}[4]$ | $z_{2,1}[4]$ | +| Accumulator microlimbs | | | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0` | $a_{0}^{\text{curr}}[0]$ | $a_{1}^{\text{curr}}[0]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_1` | $a_{0}^{\text{curr}}[1]$ | $a_{1}^{\text{curr}}[1]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_2` | $a_{0}^{\text{curr}}[2]$ | $a_{1}^{\text{curr}}[2]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_3` | $a_{0}^{\text{curr}}[3]$ | $a_{1}^{\text{curr}}[3]$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_4` | $a_{0}^{\text{curr}}[4]$ | $a_{1}^{\text{curr}}[4]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $a_{2}^{\text{curr}}[0]$ | $a_{3}^{\text{curr}}[0]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $a_{2}^{\text{curr}}[1]$ | $a_{3}^{\text{curr}}[1]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $a_{2}^{\text{curr}}[2]$ | $a_{3}^{\text{curr}}[2]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $a_{2}^{\text{curr}}[3]$ | $a_{3}^{\text{curr}}[3]$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $a_{2}^{\text{curr}}[4]$ | $\textcolor{yellow}{a_{3}[\textsf{tail}]}$ (reassigned) | +| Quotient microlimbs | | | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_0` | $q_{0}[0]$ | $q_{1}[0]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_1` | $q_{0}[1]$ | $q_{1}[1]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_2` | $q_{0}[2]$ | $q_{1}[2]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_3` | $q_{0}[3]$ | $q_{1}[3]$ | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_4` | $q_{0}[4]$ | $q_{1}[4]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $q_{2}[0]$ | $q_{3}[0]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $q_{2}[1]$ | $q_{3}[1]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $q_{2}[2]$ | $q_{3}[2]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $q_{2}[3]$ | $q_{3}[3]$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $q_{2}[4]$ | $\textcolor{yellow}{q_{3}[\textsf{tail}]}$ (reassigned) | +| Carry microlimbs | | | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0` | $c^{\text{lo}}[0]$ | $c^{\text{hi}}[0]$ | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_1` | $c^{\text{lo}}[1]$ | $c^{\text{hi}}[1]$ | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_2` | $c^{\text{lo}}[2]$ | $c^{\text{hi}}[2]$ | +| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_3` | $c^{\text{lo}}[3]$ | $c^{\text{hi}}[3]$ | +| Tail microlimbs | | | +| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{x,0}[\textsf{tail}]}$ | $\textcolor{yellow}{P_{x,1}[\textsf{tail}]}$ | +| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{x,2}[\textsf{tail}]}$ | $c^{\text{lo}}[4]$ (reassigned) | +| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{y,0}[\textsf{tail}]}$ | $\textcolor{yellow}{P_{y,1}[\textsf{tail}]}$ | +| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{y,2}[\textsf{tail}]}$ | $c^{\text{hi}}[4]$ (reassigned) | +| `Z_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{z_{1,0}[\textsf{tail}]}$ | $\textcolor{yellow}{z_{2,0}[\textsf{tail}]}$ | +| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{z_{1,1}[\textsf{tail}]}$ | $\textcolor{yellow}{z_{2,1}[\textsf{tail}]}$ | +| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{a_{0}^{\text{curr}}[\textsf{tail}]}$ | $\textcolor{yellow}{a_{1}^{\text{curr}}[\textsf{tail}]}$ | +| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{a_{2}^{\text{curr}}[\textsf{tail}]}$ | $c^{\text{lo}}[5]$ (reassigned) | +| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{0}[\textsf{tail}]}$ | $\textcolor{yellow}{q_{1}[\textsf{tail}]}$ | +| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{2}[\textsf{tail}]}$ | $c^{\text{hi}}[5]$ (reassigned) | +| | | | + +The tail microlimbs are shown in yellow and we will explain their role in enforcing tight range constraints in the following sections. +We reuse columns in some cases (to save space) by reassigning them to hold tail microlimbs. For example since limb $P_{x, 3}$ is only 50 bits, it only needs 4 full 14-bit microlimbs. So the odd row in the 5th microlimb column `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` is reassigned to hold the tail microlimb for $P_{x,3}$. + +### Virtual Columns + +Some columns are "virtual" and not explicitly stored in the witness trace. Instead, they are computed on-the-fly during relation evaluation using existing columns. These include: + +- Interleaved columns for range constraint microlimbs (computed from the physical microlimb columns) +- Sorted (ordered) columns for range constraint microlimbs (computed by sorting the physical microlimb columns) + +### Lagrange Polynomials (Precomputed) + +The Translator circuit uses **ZERO selector polynomials** (`NUM_SELECTORS = 0`). + +Instead, the circuit uses **Lagrange polynomials** to control which constraints are active: + +| Polynomial | Description | Active Rows | +| ------------------------------ | ------------------------------- | ----------------------------------- | +| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in {0, 2, 4, ..., 8190}$ (mini) | +| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in {1, 3, 5, ..., 8191}$ (mini) | +| `lagrange_first` | First row | $i = 0$ | +| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | +| `lagrange_result_row` | Row containing final result | Specific row in trace | +| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | +| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | + +The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange polynomials, which are more efficient than custom selectors. + +--- + ## Interleaving: The Key Optimization The Translator must range-constrain approximately 64 different microlimb sets using permutation argument. The permutation argument's degree equals $1 + \text{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: @@ -243,149 +410,6 @@ The permutation argument verifies that within each group, the interleaved values --- -## Witness Polynomials (81 Total) - -The Translator circuit uses **81 witness polynomials** (no selector polynomials). These can be categorized as follows: - -### Category 1: EccOpQueue Transcript (4 wires) - -These contain the raw data from the EC operation queue: - -| Wire | Description | Range | -| ------------ | ----------------------------------------------------------- | ------------------ | -| `OP` | Operation code | {0, 1, 2, 3, 4, 8} | -| `X_LOW_Y_HI` | P.x_lo (136-bit) at even rows, P.y_hi (118-bit) at odd rows | < 2¹³⁢ or < 2¹¹⁸ | -| `X_HIGH_Z_1` | P.x_hi (118-bit) at even rows, z₁ (128-bit) at odd rows | < 2¹¹⁸ or < 2¹²⁸ | -| `Y_LOW_Z_2` | P.y_lo (136-bit) at even rows, zβ‚‚ (128-bit) at odd rows | < 2¹³⁢ or < 2¹²⁸ | - -**Note:** The circuit operates in a 2-row cycle: - -- **Even rows (accumulation):** Compute new accumulator value -- **Odd rows (copy):** Transfer accumulator to next cycle - -### Category 2: Binary Limb Decompositions (12 wires) - -These decompose coordinates and z-values into 68-bit limbs: - -**P.x limbs (4 wires):** - -- `P_X_LOW_LIMBS`: Two 68-bit limbs from P.x_lo -- `P_X_HIGH_LIMBS`: One 68-bit + one 50-bit limb from P.x_hi - -**P.y limbs (4 wires):** - -- `P_Y_LOW_LIMBS`: Two 68-bit limbs from P.y_lo -- `P_Y_HIGH_LIMBS`: One 68-bit + one 50-bit limb from P.y_hi - -**z limbs (4 wires):** - -- `Z_LOW_LIMBS`: 68-bit limbs of z₁ and zβ‚‚ (low parts) -- `Z_HIGH_LIMBS`: 60-bit limbs of z₁ and zβ‚‚ (high parts) - -### Category 3: Accumulator Limbs (4 wires) - -Store current and previous accumulator values: - -| Wire | Description | Bits per limb | -| ----------------------------- | --------------------------- | ------------- | -| `ACCUMULATORS_BINARY_LIMBS_0` | Limb 0 (current & previous) | 68 bits | -| `ACCUMULATORS_BINARY_LIMBS_1` | Limb 1 (current & previous) | 68 bits | -| `ACCUMULATORS_BINARY_LIMBS_2` | Limb 2 (current & previous) | 68 bits | -| `ACCUMULATORS_BINARY_LIMBS_3` | Limb 3 (current & previous) | 50 bits | - -**Layout:** Previous accumulator is at higher indices (row i+1) due to KZG commitment structure. - -### Category 4: Quotient Limbs (2 wires) - -The quotient from dividing by q: - -| Wire | Description | -| ---------------------------- | ---------------------------- | -| `QUOTIENT_LOW_BINARY_LIMBS` | Lower two 68-bit limbs | -| `QUOTIENT_HIGH_BINARY_LIMBS` | One 68-bit + one 52-bit limb | - -### Category 5: Relation Wide Limbs (1 wire) - -Used for modulo 2²⁷² computation: - -| Wire | Description | Bits | -| --------------------- | ------------------------------------- | ------------ | -| `RELATION_WIDE_LIMBS` | Carries for 136-bit computation steps | 84 bits each | - -Contains two values: - -- **relation_wide_lower_limb:** Carry from lower 136-bit computation -- **relation_wide_higher_limb:** Carry from higher 136-bit computation - -### Category 6: Range Constraint Microlimbs (52 wires) - -Each limb is further decomposed into 14-bit microlimbs for tight range constraints: - -**Pattern for each element (P.x_lo, P.x_hi, P.y_lo, P.y_hi, z₁_lo, z₁_hi, zβ‚‚_lo, zβ‚‚_hi, acc_lo, acc_hi, quot_lo, quot_hi):** - -- `*_RANGE_CONSTRAINT_0` through `*_RANGE_CONSTRAINT_4`: Five 14-bit microlimbs -- `*_RANGE_CONSTRAINT_TAIL`: Shifted highest microlimb (for stricter constraint) - -Examples: - -``` -P_X_LOW_LIMBS_RANGE_CONSTRAINT_0 // Microlimb 0 (bits 0-13) -P_X_LOW_LIMBS_RANGE_CONSTRAINT_1 // Microlimb 1 (bits 14-27) -... -P_X_LOW_LIMBS_RANGE_CONSTRAINT_4 // Microlimb 4 (bits 56-69, actually 56-67) -P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL // Microlimb 4 << 4 (for exact 68-bit constraint) -``` - -**Relation wide limb microlimbs (4 wires):** - -- `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0` through `_3`: Four 14-bit chunks - -Total range constraint wires: - -- 10 elements Γ— 6 microlimbs = 60 wires -- But relation_wide_limbs only needs 4 microlimbs -- **Total: 56 microlimb wires** - -### Category 7: Ordered Range Constraint Wires (5 wires) - -Used for the permutation argument to prove all microlimbs are ≀ 2¹⁴ - 1: - -| Wire | Description | -| ----------------------------- | ---------------------------------- | -| `ordered_range_constraints_0` | Sorted values for constraint set 0 | -| `ordered_range_constraints_1` | Sorted values for constraint set 1 | -| `ordered_range_constraints_2` | Sorted values for constraint set 2 | -| `ordered_range_constraints_3` | Sorted values for constraint set 3 | -| `ordered_range_constraints_4` | Sorted values for constraint set 4 | - -These are not explicit wires but are part of the interleaving structure. - -**Interleaving:** To handle 131,072 rows with efficient permutation, microlimbs from 16 consecutive mini-circuit rows are interleaved into single full-circuit rows. - ---- - -## Selector Polynomials - -**Critical fact:** The Translator circuit uses **ZERO selector polynomials** (`NUM_SELECTORS = 0`). - -Instead, the circuit uses **Lagrange polynomials** to control which constraints are active: - -### Lagrange Polynomials (Precomputed) - -| Polynomial | Description | Active Rows | -| ------------------------------ | ------------------------------- | ------------------------------- | -| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | i ∈ {0, 2, 4, ..., 8190} (mini) | -| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | i ∈ {1, 3, 5, ..., 8191} (mini) | -| `lagrange_first` | First row | i = 0 | -| `lagrange_last_in_minicircuit` | Last row in mini-circuit | i = 8191 (mini) | -| `lagrange_result_row` | Row containing final result | Specific row in trace | -| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | -| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | - -**Why no selectors?** The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange polynomials, which are more efficient than custom selectors. - ---- - ## The Seven Relations The Translator circuit enforces correctness through **7 distinct relations** totaling **151 subrelations**. diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index 4ea0c280db23..8bd56c7ca248 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -6,146 +6,6 @@ This document provides a rigorous mathematical treatment of the **Non-Native Fie --- -## Witness Trace Structure - -The Translator circuit operates on a **2-row cycle structure**. Each EccOpQueue entry occupies exactly 2 rows: - -- **Row 2i (Even rows)**: **Computation rows** where the non-native field relation is actively checked -- **Row 2i+1 (Odd rows)**: **Data storage rows** that hold values accessed by the next even row via shifts - -This architecture exists because of how polynomial commitments work in the KZG scheme: the "shifted" polynomial at index $i$ evaluates to the polynomial at index $i+1$. Thus: - -- Even row $2i$ performs computation using "current" values from its own row -- Even row $2i$ accesses "previous" values from odd row $2i+1$ via shift columns -- Odd row $2i+1$ stores the data that will become "previous" for the next computation at row $2i+2$ - -The Translator circuit has **81 witness columns** organized into several categories: - -#### 1. EccOpQueue Transcript Columns (4 columns) - -These columns directly represent the EccOpQueue transcript: - -| Column | Even Row (2i) | Odd Row (2i+1) | Description | -| ----------- | --------------------------------- | ---------------------------- | --------------------------------------------- | -| `OP` | $\texttt{op} \in \{0,1,2,3,4,8\}$ | 0 (no-op) | Opcode (the type of elliptic curve operation) | -| `X_LO_Y_HI` | $P_{x,\text{lo}}$ (136 bits) | $P_{y,\text{hi}}$ (118 bits) | Low 136 bits of P.x and High 118 bits of P.y | -| `X_HI_Z_1` | $P_{x,\text{hi}}$ (118 bits) | $z_1$ (128 bits) | High 118 bits of P.x and first scalar | -| `Y_LO_Z_2` | $P_{y,\text{lo}}$ (136 bits) | $z_2$ (128 bits) | Low 136 bits of P.y and second scalar | -| | | | | - -**Encoding scheme**: Point coordinates $P_x$ and $P_y$ are each 254 bits, split as: - -- $P_x = (P_{x,\text{hi}}$ (118 bits) $\|$ $P_{x,\text{lo}}$ (136 bits) $)$ -- $P_y = (P_{y,\text{hi}}$ (118 bits) $\|$ $P_{y,\text{lo}}$ (136 bits) $)$ - -#### 2. Limb Decomposition Columns (13 columns) - -These columns store finer-grained limb decompositions for non-native arithmetic: - -| Column Group | Even Row (2i) | Odd Row (2i+1) | Bits | Purpose | -| ----------------------------- | --------------------- | --------------------- | ------ | ---------------------------------------- | -| `P_X_LOW_LIMBS` | $P_{x,0}^{\text{lo}}$ | $P_{x,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{x,\text{lo}}$ | -| `P_X_HIGH_LIMBS` | $P_{x,0}^{\text{hi}}$ | $P_{x,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{x,\text{hi}}$ | -| `P_Y_LOW_LIMBS` | $P_{y,0}^{\text{lo}}$ | $P_{y,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{y,\text{lo}}$ | -| `P_Y_HIGH_LIMBS` | $P_{y,0}^{\text{hi}}$ | $P_{y,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{y,\text{hi}}$ | -| `Z_LOW_LIMBS` | $z_{1,0}$ | $z_{2,0}$ | 68 | Low limbs of $z_1$ and $z_2$ | -| `Z_HIGH_LIMBS` | $z_{1,1}$ | $z_{2,1}$ | 60 | High limbs of $z_1$ and $z_2$ | -| `ACCUMULATORS_BINARY_LIMBS_0` | $a_0^{\text{curr}}$ | $a_0^{\text{prev}}$ | 68 | Limb 0 of current/previous accumulator | -| `ACCUMULATORS_BINARY_LIMBS_1` | $a_1^{\text{curr}}$ | $a_1^{\text{prev}}$ | 68 | Limb 1 of current/previous accumulator | -| `ACCUMULATORS_BINARY_LIMBS_2` | $a_2^{\text{curr}}$ | $a_2^{\text{prev}}$ | 68 | Limb 2 of current/previous accumulator | -| `ACCUMULATORS_BINARY_LIMBS_3` | $a_3^{\text{curr}}$ | $a_3^{\text{prev}}$ | 50 | Limb 3 of current/previous accumulator | -| `QUOTIENT_LOW_BINARY_LIMBS` | $q_0$ | $q_1$ | 68 | Limbs 0 & 1 of quotient $\mathcal{Q}$ | -| `QUOTIENT_HIGH_BINARY_LIMBS` | $q_2$ | $q_3$ | 68, 52 | Limbs 2 & 3 of quotient $\mathcal{Q}$ | -| `RELATION_WIDE_LIMBS` | $c^{\text{lo}}$ | $c^{\text{hi}}$ | 84 | Carry/overflow from mod $2^{136}$ checks | - -**Key insight**: The accumulator columns demonstrate the shift mechanism: - -- Even row stores $a^{\text{curr}}$ (result of current computation) -- Odd row stores what will become $a^{\text{prev}}$ (input to next computation) -- Via shifts, even row $2i$ reads odd row $2i+1$ to get "previous" values - -#### 3. Range Constraint Microlimb Columns (64 columns) - -Each limb is further decomposed into **14-bit microlimbs** for range checking. Each 68-bit limb has 5 microlimbs (14 bits each) plus a "tail" microlimb that enforces tight range constraints. The columns are organized as follows: - -| Column Group | Even Row (2i) | Odd Row (2i+1) | -| ---------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------- | -| Coordinate $P_x$ microlimbs | | | -| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_0` | $P_{x,0}[0]$ | $P_{x,1}[0]$ | -| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_1` | $P_{x,0}[1]$ | $P_{x,1}[1]$ | -| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_2` | $P_{x,0}[2]$ | $P_{x,1}[2]$ | -| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_3` | $P_{x,0}[3]$ | $P_{x,1}[3]$ | -| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_4` | $P_{x,0}[4]$ | $P_{x,1}[4]$ | -| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $P_{x,2}[0]$ | $P_{x,3}[0]$ | -| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $P_{x,2}[1]$ | $P_{x,3}[1]$ | -| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $P_{x,2}[2]$ | $P_{x,3}[2]$ | -| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $P_{x,2}[3]$ | $P_{x,3}[3]$ | -| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $P_{x,2}[4]$ | $\textcolor{yellow}{P_{x,3}[\textsf{tail}]}$ (reassigned) | -| Coordinate $P_y$ microlimbs | | | -| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0` | $P_{y,0}[0]$ | $P_{y,1}[0]$ | -| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_1` | $P_{y,0}[1]$ | $P_{y,1}[1]$ | -| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_2` | $P_{y,0}[2]$ | $P_{y,1}[2]$ | -| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_3` | $P_{y,0}[3]$ | $P_{y,1}[3]$ | -| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_4` | $P_{y,0}[4]$ | $P_{y,1}[4]$ | -| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $P_{y,2}[0]$ | $P_{y,3}[0]$ | -| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $P_{y,2}[1]$ | $P_{y,3}[1]$ | -| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $P_{y,2}[2]$ | $P_{y,3}[2]$ | -| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $P_{y,2}[3]$ | $P_{y,3}[3]$ | -| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $P_{y,2}[4]$ | $\textcolor{yellow}{P_{y,3}[\textsf{tail}]}$ (reassigned) | -| Coordinate $z_1$ microlimbs | | | -| `Z_LOW_LIMBS_RANGE_CONSTRAINT_0` | $z_{1,0}[0]$ | $z_{2,0}[0]$ | -| `Z_LOW_LIMBS_RANGE_CONSTRAINT_1` | $z_{1,0}[1]$ | $z_{2,0}[1]$ | -| `Z_LOW_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,0}[2]$ | $z_{2,0}[2]$ | -| `Z_LOW_LIMBS_RANGE_CONSTRAINT_3` | $z_{1,0}[3]$ | $z_{2,0}[3]$ | -| `Z_LOW_LIMBS_RANGE_CONSTRAINT_4` | $z_{1,0}[4]$ | $z_{2,0}[4]$ | -| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $z_{1,1}[0]$ | $z_{2,1}[0]$ | -| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $z_{1,1}[1]$ | $z_{2,1}[1]$ | -| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,1}[2]$ | $z_{2,1}[2]$ | -| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $z_{1,1}[3]$ | $z_{2,1}[3]$ | -| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $z_{1,1}[4]$ | $z_{2,1}[4]$ | -| Accumulator microlimbs | | | -| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0` | $a_{0}^{\text{curr}}[0]$ | $a_{1}^{\text{curr}}[0]$ | -| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_1` | $a_{0}^{\text{curr}}[1]$ | $a_{1}^{\text{curr}}[1]$ | -| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_2` | $a_{0}^{\text{curr}}[2]$ | $a_{1}^{\text{curr}}[2]$ | -| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_3` | $a_{0}^{\text{curr}}[3]$ | $a_{1}^{\text{curr}}[3]$ | -| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_4` | $a_{0}^{\text{curr}}[4]$ | $a_{1}^{\text{curr}}[4]$ | -| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $a_{2}^{\text{curr}}[0]$ | $a_{3}^{\text{curr}}[0]$ | -| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $a_{2}^{\text{curr}}[1]$ | $a_{3}^{\text{curr}}[1]$ | -| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $a_{2}^{\text{curr}}[2]$ | $a_{3}^{\text{curr}}[2]$ | -| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $a_{2}^{\text{curr}}[3]$ | $a_{3}^{\text{curr}}[3]$ | -| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $a_{2}^{\text{curr}}[4]$ | $\textcolor{yellow}{a_{3}[\textsf{tail}]}$ (reassigned) | -| Quotient microlimbs | | | -| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_0` | $q_{0}[0]$ | $q_{1}[0]$ | -| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_1` | $q_{0}[1]$ | $q_{1}[1]$ | -| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_2` | $q_{0}[2]$ | $q_{1}[2]$ | -| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_3` | $q_{0}[3]$ | $q_{1}[3]$ | -| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_4` | $q_{0}[4]$ | $q_{1}[4]$ | -| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_0` | $q_{2}[0]$ | $q_{3}[0]$ | -| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_1` | $q_{2}[1]$ | $q_{3}[1]$ | -| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $q_{2}[2]$ | $q_{3}[2]$ | -| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $q_{2}[3]$ | $q_{3}[3]$ | -| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $q_{2}[4]$ | $\textcolor{yellow}{q_{3}[\textsf{tail}]}$ (reassigned) | -| Carry microlimbs | | | -| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0` | $c^{\text{lo}}[0]$ | $c^{\text{hi}}[0]$ | -| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_1` | $c^{\text{lo}}[1]$ | $c^{\text{hi}}[1]$ | -| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_2` | $c^{\text{lo}}[2]$ | $c^{\text{hi}}[2]$ | -| `RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_3` | $c^{\text{lo}}[3]$ | $c^{\text{hi}}[3]$ | -| Tail microlimbs | | | -| `P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{x,0}[\textsf{tail}]}$ | $\textcolor{yellow}{P_{x,1}[\textsf{tail}]}$ | -| `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{x,2}[\textsf{tail}]}$ | $c^{\text{lo}}[4]$ (reassigned) | -| `P_Y_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{y,0}[\textsf{tail}]}$ | $\textcolor{yellow}{P_{y,1}[\textsf{tail}]}$ | -| `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{P_{y,2}[\textsf{tail}]}$ | $c^{\text{hi}}[4]$ (reassigned) | -| `Z_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{z_{1,0}[\textsf{tail}]}$ | $\textcolor{yellow}{z_{2,0}[\textsf{tail}]}$ | -| `Z_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{z_{1,1}[\textsf{tail}]}$ | $\textcolor{yellow}{z_{2,1}[\textsf{tail}]}$ | -| `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{a_{0}^{\text{curr}}[\textsf{tail}]}$ | $\textcolor{yellow}{a_{1}^{\text{curr}}[\textsf{tail}]}$ | -| `ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{a_{2}^{\text{curr}}[\textsf{tail}]}$ | $c^{\text{lo}}[5]$ (reassigned) | -| `QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{0}[\textsf{tail}]}$ | $\textcolor{yellow}{q_{1}[\textsf{tail}]}$ | -| `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{2}[\textsf{tail}]}$ | $c^{\text{hi}}[5]$ (reassigned) | -| | | | - -The tail microlimbs are shown in yellow and we will explain their role in enforcing tight range constraints in the following sections. -We reuse columns in some cases (to save space) by reassigning them to hold tail microlimbs. For example since limb $P_{x, 3}$ is only 50 bits, it only needs 4 full 14-bit microlimbs. So the odd row in the 5th microlimb column `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` is reassigned to hold the tail microlimb for $P_{x,3}$. - ### Active Constraints by Row Type | Constraint | Active on Even Rows | Active on Odd Rows | From 23b1568043b1a996818e8851337a8ab8740faec6 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 16 Dec 2025 10:00:18 +0000 Subject: [PATCH 12/29] update with witgen section. --- .../src/barretenberg/translator_vm/README.md | 1158 +++++++++++++---- .../barretenberg/translator_vm/RELATIONS.md | 612 +++++++++ .../translator_vm/translator_proving_key.cpp | 7 +- 3 files changed, 1524 insertions(+), 253 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 869147431137..bfcd1f7d07af 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -7,12 +7,13 @@ 1. [Overview](#overview) 2. [High-Level Statement](#high-level-statement) 3. [Architecture and Constants](#architecture-and-constants) -4. [Witness Polynomials (81 Total)](#witness-polynomials-81-total) -5. [Selector Polynomials](#selector-polynomials) -6. [The Seven Relations](#the-seven-relations) -7. [Proof System Details](#proof-system-details) -8. [Proof Size Analysis](#proof-size-analysis) -9. [Critical Components for Auditing](#critical-components-for-auditing) +4. [Witness Trace Structure](#witness-trace-structure) +5. [Witness Generation and Proving Key Construction](#witness-generation-and-proving-key-construction) +6. [Interleaving: The Key Optimization](#interleaving-the-key-optimization) +7. [The Seven Relations](#the-seven-relations) +8. [Proof System Details](#proof-system-details) +9. [Proof Size Analysis](#proof-size-analysis) +10. [Critical Components for Auditing](#critical-components-for-auditing) --- @@ -25,7 +26,7 @@ The **Translator Circuit** is a critical component of the Goblin Plonk proving s | BN254 | $\mathbb{F}_q$ | $\mathbb{F}_r$ | Used in Mega circuits | | Grumpkin | $\mathbb{F}_r$ | $\mathbb{F}_q$ | Used in ECCVM for efficient EC operations | -When proving recursive circuits with Mega circuit builder, we accumulate elliptic curve operations in an `EccOpQueue`. Proving these ECC operations is delegated to the ECCVM circuit, which operates over the Grumpkin curve. However, the representation of the `EccOpQueue` is different in the Mega circuit (BN254) and ECCVM (Grumpkin) circuit because: +When proving recursive circuits with Mega circuit builder, we accumulate elliptic curve operations in an `EccOpQueue`. Proving these ECC operations is delegated to the ECCVM circuit, which operates over the Grumpkin curve. However, the **same operations have different representations** in the two circuits because: - Mega circuit operates over the BN254 scalar field $\mathbb{F}_r$ so elements in $\mathbb{F}_q$ are non-native (i.e., they need to decomposed into limbs in $\mathbb{F}_r$) - ECCVM operates over the Grumpkin scalar field $\mathbb{F}_q$ so elements in $\mathbb{F}_q$ are circuit native @@ -61,47 +62,46 @@ The Translator circuit is a custom circuit designed to solve this problem. It: ## High-Level Statement -Given: +The Translator proves that the ECCVM's batched polynomial evaluation of the ECC operations is computed correctly. -- A sequence of `UltraOp` operations from the `EccOpQueue` +**Given:** + +- A sequence of `UltraOp` operations from the `EccOpQueue` (each containing: $\text{op}, P_x, P_y, z_1, z_2$) - An evaluation challenge $x \in \mathbb{F}_q$ - A batching challenge $v \in \mathbb{F}_q$ **Prove:** $$\boxed{\text{accumulator}_{\text{final}} = \sum_{i=0}^{n-1} x^{n-1-i} \cdot \left( \text{op}_i + v \cdot P_x^{(i)} + v^2 \cdot P_y^{(i)} + v^3 \cdot z_1^{(i)} + v^4 \cdot z_2^{(i)} \right) \pmod{q}}$$ -where: - -- each `UltraOp` contains: $(\text{op}, \ P_x, \ P_y, \ z_1, \ z_2)$, -- the computation is performed modulo $q$. +The batching via powers of $v$ combines the 5 values per operation into a single field element, and the powers of $x$ combine all operations into a single accumulator. Specifically, for each accumulation step (every 2 rows), prove: $$\text{acc}_{\text{curr}} = \text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ -**Method:** Similar to the technique used in [bigfield](../stdlib/primitives/bigfield/README.md), we prove in integers that: +**Method:** Since we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic (as $q \neq r$), we use non-native field arithmetic. Similar to the technique in [bigfield](../stdlib/primitives/bigfield/README.md), we prove the equation holds in integers: $$\text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \text{quotient} \cdot q - \text{acc}_{\text{curr}} = 0$$ -This equation must hold: +We verify this by proving the equation holds: -1. modulo $2^{272}$ (proven via limb arithmetic) -2. modulo $r$ (proven in native field) -3. with appropriate range constraints (to prevent overflows/underflows) +1. **modulo $2^{272}$** (via 68-bit limb arithmetic split into two 136-bit checks) +2. **modulo $r$** (natively in $\mathbb{F}_r$) +3. with **range constraints** on all limbs (prevents overflow/underflow) -Then the Chinese Remainder Theorem guarantees that the equation holds modulo $q$. +By the Chinese Remainder Theorem, since $2^{272} \cdot r > 2^{514}$ exceeds the maximum possible value, the equation must hold in integers, and thus modulo $q$. ## Architecture and Constants #### Circuit Size Parameters ```cpp -CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE = 13 // Mini-circuit: 2^13 = 8,192 rows +CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE = 13 // Mini-circuit: 2^13 = 8,192 rows (logβ‚‚ of size) INTERLEAVING_GROUP_SIZE = 16 // Interleaving factor -CONST_TRANSLATOR_LOG_N = 13 + 4 = 17 // Full circuit: 2^17 = 131,072 rows +CONST_TRANSLATOR_LOG_N = 13 + 4 = 17 // Full circuit: 2^17 = 131,072 rows (logβ‚‚ of size) ``` -**Why interleaving?** To reduce the degree of the permutation argument polynomial for range constraints. +**Why interleaving?** Without interleaving, checking ~64 microlimb columns simultaneously would create a degree-65 polynomial in the permutation argument, making sumcheck impractical. Interleaving reduces this to degree 6-7 by spreading the checks across 16 segments (see [Interleaving section](#interleaving-the-key-optimization)). #### Field Moduli @@ -164,7 +164,13 @@ Each microlimb must be $≀ 2^{14} - 1 = 16383$. ## Witness Trace Structure -The Translator circuit operates on a **2-row cycle structure**. Each EccOpQueue entry occupies exactly 2 rows: +The Translator circuit has **81 witness columns**, organized into: + +- **4 columns**: EccOpQueue transcript (op, P.x, P.y, z₁, zβ‚‚ encoded across 2 rows) +- **13 columns**: Limb decompositions (68-bit limbs for non-native arithmetic) +- **64 columns**: Microlimb decompositions (14-bit microlimbs for range constraints) + +The circuit operates on a **2-row cycle structure**. Each EccOpQueue entry occupies exactly 2 rows: - **Row $2i$ (Even rows)**: **Computation rows** where the non-native field relation is actively checked - **Row $2i+1$ (Odd rows)**: **Data storage rows** that hold values accessed by the next even row via shifts @@ -299,8 +305,9 @@ Each limb is further decomposed into **14-bit microlimbs** for range checking. E | `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{2}[\textsf{tail}]}$ | $c^{\text{hi}}[5]$ (reassigned) | | | | | -The tail microlimbs are shown in yellow and we will explain their role in enforcing tight range constraints in the following sections. -We reuse columns in some cases (to save space) by reassigning them to hold tail microlimbs. For example since limb $P_{x, 3}$ is only 50 bits, it only needs 4 full 14-bit microlimbs. So the odd row in the 5th microlimb column `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` is reassigned to hold the tail microlimb for $P_{x,3}$. +The tail microlimbs (shown in yellow) enforce tight range constraints by ensuring top limbs use exactly the required number of bits (explained in [Relation 3](#relation-3-decomposition-relation-48-subrelations)). + +**Column reuse optimization:** Some columns are reassigned in odd rows to hold tail microlimbs for limbs that don't need all 5 microlimbs. For example, limb $P_{x, 3}$ is only 50 bits (= 3Γ—14 + 8), requiring only 4 microlimbs. The 5th microlimb column `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` at odd rows is therefore reassigned to hold the tail microlimb for $P_{x,3}$ (and carry values $c^{\text{lo}}[4]$, $c^{\text{hi}}[4]$, etc.). ### Virtual Columns @@ -315,362 +322,1015 @@ The Translator circuit uses **ZERO selector polynomials** (`NUM_SELECTORS = 0`). Instead, the circuit uses **Lagrange polynomials** to control which constraints are active: -| Polynomial | Description | Active Rows | -| ------------------------------ | ------------------------------- | ----------------------------------- | -| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in {0, 2, 4, ..., 8190}$ (mini) | -| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in {1, 3, 5, ..., 8191}$ (mini) | -| `lagrange_first` | First row | $i = 0$ | -| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | -| `lagrange_result_row` | Row containing final result | Specific row in trace | -| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | -| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | +| Polynomial | Description | Active Rows | +| ------------------------------ | ------------------------------- | ------------------------------------- | +| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in \{0, 2, 4, ..., 8190\}$ (mini) | +| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in \{1, 3, 5, ..., 8191\}$ (mini) | +| `lagrange_first` | First row | $i = 0$ | +| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | +| `lagrange_result_row` | Row containing final result | Specific row in trace | +| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | +| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange polynomials, which are more efficient than custom selectors. --- -## Interleaving: The Key Optimization +## Witness Generation and Proving Key Construction -The Translator must range-constrain approximately 64 different microlimb sets using permutation argument. The permutation argument's degree equals $1 + \text{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: +This section details how the Translator circuit's witness polynomials are populated and how zero-knowledge is achieved through masking. + +### Overview + +Witness generation transforms the `EccOpQueue` from the Mega circuit into the 91 polynomials required by the Translator circuit: + +``` +Input: EccOpQueue (n operations) + Evaluation challenge x ∈ Fq + Batching challenge v ∈ Fq + +Output: 91 polynomials of size 2^17 + - 81 witness polynomials + - 5 ordered range constraint polynomials + - 4 interleaved range constraint polynomials (virtual) + - 1 precomputed extra numerator +``` + +**Note:** Witness generation happens in the **mini-circuit size** (2ΒΉΒ³ = 8,192 rows), then is expanded to **full circuit size** (2¹⁷ = 131,072 rows) through interleaving and zero-padding. + +### Step 1: Populate Transcript Polynomials + +The prover receives the `EccOpQueue` from the Mega circuit. Each entry contains: + +$$\texttt{UltraOp} = \{\texttt{op}, P_x, P_y, z_1, z_2\}$$ + +For operation $i$ at rows $2i$ (even) and $2i+1$ (odd), populate: + +**Even row ($2i$):** $$ -z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \beta + \gamma) = -z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \beta + \gamma) +\begin{aligned} +\texttt{OP}[2i] &= \texttt{op}_i \\ +\texttt{X\_LO\_Y\_HI}[2i] &= P_{x,\text{lo}} = P_x \bmod 2^{136} \\ +\texttt{X\_HI\_Z\_1}[2i] &= P_{x,\text{hi}} = \lfloor P_x / 2^{136} \rfloor \\ +\texttt{Y\_LO\_Z\_2}[2i] &= P_{y,\text{lo}} = P_y \bmod 2^{136} +\end{aligned} $$ -**The Problem:** Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. +**Odd row ($2i+1$):** -**The Solution:** Interleave 16 logical column groups into the same 5 physical wires across 16 circuit segments. Each segment performs an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree by 9Γ—. +$$ +\begin{aligned} +\texttt{OP}[2i+1] &= 0 \\ +\texttt{X\_LO\_Y\_HI}[2i+1] &= P_{y,\text{hi}} = \lfloor P_y / 2^{136} \rfloor \\ +\texttt{X\_HI\_Z\_1}[2i+1] &= z_1 \\ +\texttt{Y\_LO\_Z\_2}[2i+1] &= z_2 +\end{aligned} +$$ -### Circuit Structure +### Step 2: Compute Binary Limb Decompositions -``` -Mini-circuit size: 2^13 = 8,192 rows (actual computation) -Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) -FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE = 8,192 Γ— 16 -``` +Each 136-bit transcript value is further decomposed into two 68-bit limbs. For $P_{x,\text{lo}}$: -To compute the interleaved polynomials, we group 16 polynomials together and interleave their coefficients. Consider the following 16 polynomials each of size $n=2^{13}$ in the mini-circuit: +$$P_{x,\text{lo}} = P_{x,0}^{\text{lo}} + 2^{68} \cdot P_{x,1}^{\text{lo}}$$ + +where: + +- $P_{x,0}^{\text{lo}} = P_{x,\text{lo}} \bmod 2^{68}$ + +- $P_{x,1}^{\text{lo}} = \lfloor P_{x,\text{lo}} / 2^{68} \rfloor$ + +Even row ($2i$) limb assignments: $$ -\newcommand{\arraystretch}{1.2} -\begin{array}{|c|c|c|c|c|c|} -\hline -\textsf{index} & \textsf{poly 1} & \textsf{poly 2} & \textsf{poly 3} & \ldots & \textsf{poly 16} \\ -\hline -0 & \textcolor{skyblue}{a_0} & \textcolor{orange}{b_0} & \textcolor{lightgreen}{c_0} & \quad \ldots \quad & \textcolor{firebrick}{p_0} \\ -1 & \textcolor{skyblue}{a_1} & \textcolor{orange}{b_1} & \textcolor{lightgreen}{c_1} & \quad \ldots \quad & \textcolor{firebrick}{p_1} \\ -2 & \textcolor{skyblue}{a_2} & \textcolor{orange}{b_2} & \textcolor{lightgreen}{c_2} & \quad \ldots \quad & \textcolor{firebrick}{p_2} \\ -3 & \textcolor{skyblue}{a_3} & \textcolor{orange}{b_3} & \textcolor{lightgreen}{c_3} & \quad \ldots \quad & \textcolor{firebrick}{p_3} \\[5pt] -\vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\[5pt] -n-1 & \textcolor{skyblue}{a_{n-1}} & \textcolor{orange}{b_{n-1}} & \textcolor{lightgreen}{c_{n-1}} & \quad \ldots \quad & \textcolor{firebrick}{p_{n-1}} \\ -\hline -\end{array} -\quad \longrightarrow \quad -\begin{array}{|c|c|c|} -\hline -\textsf{group} & \textsf{index} & \textsf{interleaved} \\ -\hline -0 & 0 & \textcolor{skyblue}{a_0} \\ -0 & 1 & \textcolor{orange}{b_0} \\ -0 & 2 & \textcolor{lightgreen}{c_0} \\ -\vdots & \vdots & \vdots \\[3pt] -1 & 15 & \textcolor{firebrick}{p_0} \\ \hline -1 & 4 & \textcolor{skyblue}{a_1} \\ -1 & 5 & \textcolor{orange}{b_1} \\ -1 & 6 & \textcolor{lightgreen}{c_1} \\ -\vdots & \vdots & \vdots \\[3pt] -1 & 7 & \textcolor{firebrick}{p_1} \\ \hline -\vdots & \vdots & \vdots \\[5pt] -\vdots & \vdots & \vdots \\ \hline -n-1 & 4n-4 & \textcolor{skyblue}{a_{n-1}} \\ -n-1 & 4n-3 & \textcolor{orange}{b_{n-1}} \\ -n-1 & 4n-2 & \textcolor{lightgreen}{c_{n-1}} \\ -\vdots & \vdots & \vdots \\[3pt] -n-1 & 4n-1 & \textcolor{firebrick}{p_{n-1}} \\ -\hline -\end{array} +\begin{aligned} +\texttt{P\_X\_LOW\_LIMBS}[2i] &= P_{x,0}^{\text{lo}} \\ +\texttt{P\_X\_HIGH\_LIMBS}[2i] &= P_{x,0}^{\text{hi}} \\ +\texttt{P\_Y\_LOW\_LIMBS}[2i] &= P_{y,0}^{\text{lo}} \\ +\texttt{P\_Y\_HIGH\_LIMBS}[2i] &= P_{y,0}^{\text{hi}} \\ +\texttt{Z\_LOW\_LIMBS}[2i] &= z_{1,0} \\ +\texttt{Z\_HIGH\_LIMBS}[2i] &= z_{1,1} +\end{aligned} $$ -The resulting interleaved polynomial has size $16n = 2^{17}$. -For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: +Odd row ($2i+1$) limb assignments: -- **Numerator:** 4 interleaved wires + 1 extra = 5 terms -- **Denominator:** 5 ordered wires = 5 terms -- **Degree:** $1 + 5 = 6$ (or 7 with Lagrange) +$$ +\begin{aligned} +\texttt{P\_X\_LOW\_LIMBS}[2i+1] &= P_{x,1}^{\text{lo}} \\ +\texttt{P\_X\_HIGH\_LIMBS}[2i+1] &= P_{x,1}^{\text{hi}} \\ +\texttt{P\_Y\_LOW\_LIMBS}[2i+1] &= P_{y,1}^{\text{lo}} \\ +\texttt{P\_Y\_HIGH\_LIMBS}[2i+1] &= P_{y,1}^{\text{hi}} \\ +\texttt{Z\_LOW\_LIMBS}[2i+1] &= z_{2,0} \\ +\texttt{Z\_HIGH\_LIMBS}[2i+1] &= z_{2,1} +\end{aligned} +$$ -The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. +### Step 3: Compute Accumulator and Quotient -> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: The interleaved polynomials do not require separate commitments. During proving key construction, the prover computes them for use in sumcheck. In the Gemini PCS phase, the prover sends only **two additional field element evaluations** $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: -> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ -> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. The PCS proof grows by only **2 field elements**. -> -> For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: -> $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ +For each even row $2i$, compute the accumulator update and quotient. The accumulator evolves as: ---- +$$a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ -## The Seven Relations +The current and the previous accumulators are decomposed into 4 limbs each: -The Translator circuit enforces correctness through **7 distinct relations** totaling **151 subrelations**. +$$ +\begin{aligned} +a^{\text{curr}} &= +a_0^{\text{curr}} ++ +2^{68} \cdot a_1^{\text{curr}} ++ +2^{136} \cdot a_2^{\text{curr}} ++ +2^{204} \cdot a_3^{\text{curr}} +\\[5pt] +a^{\text{prev}} &= +a_0^{\text{prev}} ++ +2^{68} \cdot a_1^{\text{prev}} ++ +2^{136} \cdot a_2^{\text{prev}} ++ +2^{204} \cdot a_3^{\text{prev}} +\end{aligned} +$$ -### Relation 1: Permutation Relation (2 subrelations) +Since we're working in $\mathbb{F}_r$ (not $\mathbb{F}_q$), we must compute the quotient $\mathcal{Q}$ such that: -**Purpose:** Prove that all microlimbs are properly range-constrained to 14 bits. +$$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 = \mathcal{Q} \cdot q + a^{\text{curr}}$$ -**Method:** Grand product argument over sorted vs. interleaved values. +$$ +\implies \mathcal{Q} = \left\lfloor \frac{a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4}{q} \right\rfloor +$$ -#### Subrelation 1.1: Grand Product Identity +The quotient is then decomposed into 4 limbs (68 + 68 + 68 + 52 bits): -$$\boxed{(z_{\text{perm}} + L_0) \cdot \prod_{j=0}^{4} (\text{interleaved}_j + \beta \cdot L_{\text{mask}} + \gamma) = (z_{\text{perm,shift}} + L_{\text{last}}) \cdot \prod_{j=0}^{4} (\text{ordered}_j + \beta \cdot L_{\text{mask}} + \gamma)}$$ +$$\mathcal{Q} = q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3$$ -Where: +**Carry computation:** The relation-wide limbs $c^{\text{lo}}$ and $c^{\text{hi}}$ (84 bits each) capture overflow from the mod $2^{136}$ checks: -- **Numerator:** Product over 4 interleaved range constraint wires + 1 extra numerator -- **Denominator:** Product over 5 ordered range constraint wires -- **Masking:** `lagrange_masking` marks ZK rows to exclude from permutation +$$c^{\text{lo}} = \left\lfloor \frac{T_0 + 2^{68} \cdot T_1}{2^{136}} \right\rfloor, \quad c^{\text{hi}} = \left\lfloor \frac{c^{\text{lo}} + T_2 + 2^{68} \cdot T_3}{2^{136}} \right\rfloor$$ -**Intuition:** If the multisets match (interleaved = permutation of ordered), the grand product telescopes to 1. +where $T_0, T_1, T_2, T_3$ are the limb contributions defined in [RELATIONS.md](RELATIONS.md). -#### Subrelation 1.2: Final Value Check +### Step 4: Microlimb Decomposition -$$\boxed{L_{\text{last}} \cdot z_{\text{perm,shift}} = 0}$$ +Each 68-bit limb is decomposed into five 14-bit microlimbs plus a tail microlimb for range tightening. For a general 68-bit limb $\ell$: -Ensures the grand product returns to 1 at the end (accounting for masking). +$$\ell = \sum_{k=0}^{4} 2^{14k} \cdot m_k$$ -**Degree:** 7 (highest in Translator) +where each $m_k \in [0, 2^{14})$ and $m_4 \in [0, 2^{12})$ (since $68 = 14 \times 4 + 12$). -**Critical for security:** If this fails, an attacker could use out-of-range values, breaking the non-native field arithmetic soundness. +**Tail microlimb:** To enforce $m_4 < 2^{12}$, compute: -### Relation 2: Delta Range Constraint Relation (10 subrelations) +$$m_{\text{tail}} = m_4 \cdot 2^{14-12} = m_4 \cdot 4$$ -**Purpose:** Ensure ordered polynomials are actually sorted and bounded. +The decomposition relation enforces $m_{\text{tail}} \in [0, 2^{14})$, which implies $m_4 \in [0, 2^{12})$. For limbs with fewer bits, the tail microlimb is adjusted accordingly. -**Method:** Check consecutive differences and final value. +- 50-bit limbs (top limb): $m_3 \in [0, 2^8) \implies$ tail shift is $2^{14-8} = 64$ +- 60-bit limbs (z high): $m_4 \in [0, 2^4)\implies$ tail shift is $2^{14-4} = 1024$ -#### Subrelations 2.1-2.5: Difference Constraints +### Step 5: Construct Interleaved Polynomials -For each `j ∈ {0, 1, 2, 3, 4}`: +The 64 microlimb columns are organized into 4 groups of 16 columns each. Each group is **interleaved** into a single polynomial at full circuit size. -$$\boxed{(L_{\text{real\_last}} - 1) \cdot (L_{\text{mask}} - 1) \cdot \Delta_j \cdot (\Delta_j - 1) \cdot (\Delta_j - 2) \cdot (\Delta_j - 3) = 0}$$ +**Interleaving formula:** For group polynomials $\{p_0, p_1, \ldots, p_{15}\}$ each of mini-size $n = 2^{13}$: -Where: -$$\Delta_j = \text{ordered}_j^{(\text{shift})} - \text{ordered}_j$$ +$$p_{\text{interleaved}}(x) = \sum_{j=0}^{15} x^j \cdot p_j(x^{16})$$ -**Meaning:** The difference between consecutive values must be in {0, 1, 2, 3} (non-descending, max step = 3). +**In coefficient form:** Element at position $i \cdot 16 + j$ in the interleaved polynomial comes from row $i$ of polynomial $p_j$: -**Why max step 3?** This allows the sorted array to contain "step" values every 3 increments, ensuring coverage of [0, 2¹⁴-1] without making the polynomial too dense. +$$p_{\text{interleaved}}[i \cdot 16 + j] = p_j[i] \quad \text{for } i \in [0, n), \ j \in [0, 16)$$ -#### Subrelations 2.6-2.10: Maximum Value Constraints +This expands the circuit from mini-size $2^{13}$ to full size $2^{17} = 2^{13} \times 16$. -For each `j ∈ {0, 1, 2, 3, 4}`: +**Illustration:** We have a total of 64 microlimb columns, each with $n = 2^{13}$ rows (mini-circuit size). We illustrate the microlimb distribution and interleaving process below: -$$\boxed{L_{\text{real\_last}} \cdot (\text{ordered}_j - (2^{14} - 1)) = 0}$$ +1. Let $I_{\textsf{size}} = 16$ be the number of microlimb columns in one group. Since we have 64 microlimb columns, we will have 4 groups. -**Meaning:** The last value in each sorted array must be exactly 2¹⁴ - 1 = 16383. +2. Each group separates the microlimbs into circuit witnesses ($n-m$ rows in orange) and masking values ($m$ rows in gray). -**Together:** These constraints ensure every microlimb ∈ [0, 2¹⁴ - 1], which is the foundation for all range constraints. +3. For each group, we interleave the microlimbs to create one interleaved polynomial of size $(n - m) \cdot I_{\textsf{size}}$ for circuit witnesses and $m \cdot I_{\textsf{size}}$ for masking values. -**Degree:** 7 (due to 5-way product for difference check) +$$ +\begin{array}{rllll} +n - m +& +\overbrace{ +\textcolor{orange}{ + \boxed{ + \begin{array}{ccccc} + \\ + \\ + \\ + & & W & & \\ + \\ + \\ + \\ + \end{array} + } +} +}^{I_{\textsf{size}}} +\ +\overbrace{ +\textcolor{orange}{ + \boxed{ + \begin{array}{ccccc} + \\ + \\ + \\ + & & W & & \\ + \\ + \\ + \\ + \end{array} + } +} +}^{I_{\textsf{size}}} +\ +\overbrace{ +\textcolor{orange}{ + \boxed{ + \begin{array}{ccccc} + \\ + \\ + \\ + & & W & & \\ + \\ + \\ + \\ + \end{array} + } +} +}^{I_{\textsf{size}}} +\ +\overbrace{ +\textcolor{orange}{ + \boxed{ + \begin{array}{ccccc} + \\ + \\ + \\ + & & W & & \\ + \\ + \\ + \\ + \end{array} + } +} +}^{I_{\textsf{size}}} +\\[2pt] +m +& +\textcolor{grey}{ + \boxed{ + \begin{array}{ccccc} + & & M & & \\ + \end{array} + } +} +\ +\textcolor{grey}{ + \boxed{ + \begin{array}{ccccc} + & & M & & \\ + \end{array} + } +} +\ +\textcolor{grey}{ + \boxed{ + \begin{array}{ccccc} + & & M & & \\ + \end{array} + } +} +\ +\textcolor{grey}{ + \boxed{ + \begin{array}{ccccc} + & & M & & \\ + \end{array} + } +} +\end{array} -### Relation 3: Decomposition Relation (48 subrelations) +\xrightarrow[]{\textsf{interleaved polys}} -**Purpose:** Prove that limbs are correctly decomposed into microlimbs and wide limbs into narrow limbs. +\begin{array}{lllll} +I_1 \quad I_2 \quad I_3 \quad I_4 \\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +& +N - m \cdot I_{\textsf{size}} +\\ +\\[-10pt] +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +& +m \cdot I_{\textsf{size}} +\end{array} +$$ -**Method:** Polynomial identities checking decomposition formulas. +### Step 6: Construct Ordered (Sorted) Polynomials -#### Subrelation Types +The permutation argument requires proving that the interleaved microlimbs equal the **sorted** microlimbs. The prover constructs 5 ordered polynomials by collecting microlimbs from all 64 columns, sorting them, and distributing across ordered polynomials with inserted step values. We first describe the mathematical setup and then illustrate the construction steps. -**Type A: Binary Limb Decomposition (6 subrelations)** +**Constants:** -For each transcript value (x_lo, x_hi, y_lo, y_hi, z₁, zβ‚‚): +- Mini-circuit size: $n = 2^{13} = 8{,}192$ +- Number of masked rows in mini-circuit: $m = 4$ +- Mini-circuit size without masking: $(n - m) = 8{,}188$ +- Number of interleaving groups: $G = 4$ +- Group size: $I_{\text{size}} = 16$ (polynomials per group) +- Full circuit size: $N := n \cdot I_{\text{size}} = 2^{17} = 131{,}072$ +- Circuit size without masking: $N_{\text{no-mask}} = N - m \cdot I_{\textsf{size}}$ +- Step sequence size: $N_{\text{steps}} = 5{,}462$ -$$\boxed{L_{\text{even}} \cdot \left( \text{wide\_limb} - \text{limb}_{\text{low}} - 2^{68} \cdot \text{limb}_{\text{high}} \right) = 0}$$ +**Step sequence:** The sorted steps $\mathcal{S} = \{s_0, s_1, \ldots, s_{5461}\}$ where: +$$s_i = 3i \quad \text{for } i \in [0, 5461], \quad s_{5461} = 16{,}383 = 2^{14} - 1$$ -Example for x_lo: -$$X\_LOW\_Y\_HI = P\_X\_LOW\_LIMBS[0] + 2^{68} \cdot P\_X\_LOW\_LIMBS[1]$$ +This ensures coverage of all values in $[0, 2^{14})$ with max gap of 3. -**Type B: Limb to Microlimb Decomposition (44 subrelations)** +#### Step 6.1: Collect Microlimbs from Each Group -For standard 68-bit limbs: +For each group $g \in \{0, 1, 2, 3\}$, collect all microlimbs from its 16 polynomials: -$$\boxed{L_{\text{even}} \cdot \left( \text{limb} - \sum_{k=0}^{4} 2^{14k} \cdot \text{micro}_k - 2^{68} \cdot \text{micro}_{tail} \right) = 0}$$ +$$\mathcal{M}_g = \bigcup_{j=0}^{15} \Big\{ p_{g,j}[i] : i \in [0, (n-m)) \Big\}$$ -Example for P.x limb 0: +where $p_{g,j}$ is the $j$-th polynomial in group $g$. Size of each group microlimb set: -``` -P_X_LOW_LIMBS[0] = - P_X_LOW_LIMBS_RANGE_CONSTRAINT_0 + - 2^14 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_1 + - 2^28 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_2 + - 2^42 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_3 + - 2^56 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_4 + - 2^68 Β· P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL -``` +$$|\mathcal{M}_g| = 16 \times (n - m)$$ -For top limbs (50-bit, 60-bit, 52-bit), the formula adjusts accordingly. +and total microlimbs across all groups: +$$|\mathcal{M}_0 \cup \mathcal{M}_1 \cup \mathcal{M}_2 \cup \mathcal{M}_3| = 64 \times (n - m).$$ -For relation wide limbs (84-bit): -$$\text{relation\_wide\_limb} = \sum_{k=0}^{5} 2^{14k} \cdot \text{micro}_k$$ +#### Step 6.2: Determine Capacity for Each Ordered Polynomial -**Type C: Tail Microlimb Stricter Constraints (42 subrelations)** +Each ordered polynomial has size $N$ but must accommodate: -For elements that need exact bit constraints (not just ≀ 68): +1. Microlimbs from the circuit (actual witness values) +2. Step values $\mathcal{S}$ (for delta range constraint) -$$\boxed{L_{\text{even}} \cdot \left( \text{micro}_4 \cdot 2^{shift} - \text{micro}_{tail} \right) = 0}$$ +**Capacity per ordered polynomial (for circuit microlimbs):** +$$C_{\text{capacity}} = N_{\text{no-mask}} - N_{\text{steps}} = N_{\text{no-mask}} - 5{,}462$$ -Example: For 68-bit limb, shift = 4 (since 68 = 14Γ—4 + 12, so top microlimb must be ≀ 2ΒΉΒ² - 1): -$$\text{micro}_4 \cdot 16 = \text{micro}_{tail}$$ +This is the maximum number of witnesses each ordered polynomial can hold before adding step values. -Since both `micro_4` and `micro_tail` are constrained to 14 bits by the permutation, this forces `micro_4 ≀ 2ΒΉΒ² - 1`. +#### Step 6.3: Distribute Microlimbs to Ordered Polynomials -**Degree:** 4 (lagrange Γ— decomposition identity) +For groups 0-3, construct `ordered_range_constraints_i` by: -**Why important:** Without correct decomposition, the non-native arithmetic breaks down completely. +1. Collect microlimbs from group $g$: $\mathcal{M}_g$ +2. Take first $C_{\text{capacity}}$ elements (arbitrarily ordered at this point) +3. Add step values $\mathcal{S}$ +4. Sort the combined set -### Relation 4: Non-Native Field Relation (3 subrelations) +Mathematically, for $g \in \{0, 1, 2, 3\}$: -**Purpose:** Prove the core accumulation identity in non-native field arithmetic. +$$ +\text{ordered}[g]_{\text{unsorted}} = \begin{cases} +\mathcal{M}_g[k] & \text{if } k < C_{\text{capacity}} \\ +\mathcal{S}[k - C_{\text{capacity}}] & \text{if } C_{\text{capacity}} \leq k < N_{\text{no-mask}} \\ +0 & \text{if } k \geq N_{\text{no-mask}} \text{ (masking region)} +\end{cases} +$$ -**The Formula:** -$$\text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \text{quot} \cdot q - \text{acc}_{\text{curr}} = 0$$ +Then sort: +$$\text{ordered}[g] = \text{sort}(\text{ordered}[g]_{\text{unsorted}})$$ -This must hold in two moduli for soundness. +Overflow microlimbs: If $|\mathcal{M}_g| > C_{\text{capacity}}$, the excess microlimbs go to group 4: -#### Subrelation 4.1: Lower Mod 2¹³⁢ Check +$$\mathcal{M}_{g,\text{overflow}} = \left\{ \mathcal{M}_g[k] : k \geq C_{\text{capacity}} \right\}$$ -Compute the formula using only limbs [0] and parts of limbs [1], check that result Γ· 2¹³⁢ equals `relation_wide_lower_limb`: +$$|\mathcal{M}_{g,\text{overflow}}| = |\mathcal{M}_g| - C_{\text{capacity}}$$ -$$\boxed{L_{\text{even}} \cdot \left( \text{LOWER\_COMPUTATION} - 2^{136} \cdot \text{relation\_wide\_lower\_limb} \right) = 0}$$ +#### Step 6.4: Construct the 5th Ordered Polynomial -Where `LOWER_COMPUTATION` includes: +The 5th ordered polynomial (`ordered_range_constraints_4`) collects all overflow: -``` - acc_prev[0]Β·x[0] + op + P_x[0]Β·v[0] + P_y[0]Β·vΒ²[0] + z₁[0]Β·vΒ³[0] + zβ‚‚[0]Β·v⁴[0] -+ quot[0]Β·(-q)[0] - acc_curr[0] -+ 2^68Β·( - acc_prev[1]Β·x[0] + P_x[1]Β·v[0] + P_y[1]Β·vΒ²[0] + z₁[1]Β·vΒ³[0] + zβ‚‚[1]Β·v⁴[0] - + quot[1]Β·(-q)[0] - + acc_prev[0]Β·x[1] + P_x[0]Β·v[1] + P_y[0]Β·vΒ²[1] + z₁[0]Β·vΒ³[1] + zβ‚‚[0]Β·v⁴[1] - + quot[0]Β·(-q)[1] - acc_curr[1] -) -``` +$$\mathcal{M}_{\text{overflow}} = \bigcup_{g=0}^{3} \mathcal{M}_{g,\text{overflow}}$$ -All arithmetic is in 𝔽r, but the structure mimics integer arithmetic mod 2¹³⁢. +Size of overflow: +$$|\mathcal{M}_{\text{overflow}}| = 4 \times |\mathcal{M}_{g,\text{overflow}}| = 4 \times (16 \times (n - m) - C_{\text{capacity}})$$ -#### Subrelation 4.2: Higher Mod 2¹³⁢ Check +Then construct: -Use `relation_wide_lower_limb` as carry and compute for limbs [2], [3]: +$$ +\text{ordered}[4]_{\text{unsorted}} = \begin{cases} +\mathcal{M}_{\text{overflow}}[k] & \text{if } k < |\mathcal{M}_{\text{overflow}}| \\ +\mathcal{S}[k - |\mathcal{M}_{\text{overflow}}|] & \text{if } |\mathcal{M}_{\text{overflow}}| \leq k < |\mathcal{M}_{\text{overflow}}| + N_{\text{steps}} \\ +0 & \text{otherwise} +\end{cases} +$$ -$$\boxed{L_{\text{even}} \cdot \left( \text{HIGHER\_COMPUTATION} - 2^{136} \cdot \text{relation\_wide\_higher\_limb} \right) = 0}$$ +Then sort: +$$\text{ordered}[4] = \text{sort}(\text{ordered}[4]_{\text{unsorted}})$$ -Where `HIGHER_COMPUTATION` includes: +**Illustration:** We start with the 4 interleaved polynomials constructed earlier: -``` -relation_wide_lower_limb -+ combinations of limbs: (0,2), (1,1), (2,0), (0,3), (1,2), (2,1), (3,0), ... -+ higher cross-terms from all products -``` +1. First, we add an extra numerator polynomial $I_5$ containing the step values (shown in green, repeated 5 times) to enable the delta range constraint. -**Together (4.1 & 4.2):** Prove the relation holds modulo 2²⁷². +2. The remainder of $I_5$ is filled with zero-padding (shown in violet) to match the size $N$ of the interleaved polynomials. -#### Subrelation 4.3: Native Field Check +3. In the four interleaved polynomials, we have circuit witness values (orange) and masking values (gray). We also show the overflow microlimbs that will go into the 5th ordered polynomial (smaller orange boxes). -Reconstruct full elements in 𝔽r and check directly: +4. We then construct the ordered polynomials $O_1, \dots, O_5$ by adding the step values into each interleaved polynomial and sorting the witness values appropriately. -$$\boxed{L_{\text{even}} \cdot \text{NATIVE\_CHECK} = 0}$$ +5. The randomess in the masking region (gray) is redistributed to ensure that the multisets of the interleaved polynomials plus extra numerator equal the multisets of the ordered polynomials. Hence, the number of masking rows in each of the ordered polynomials is at least $\left\lfloor\frac{4 \cdot m \cdot I_{\textsf{size}}}{5}\right\rfloor$. The remainder of the rows in each ordered polynomial is filled with zero-padding. -Where: +$$ +\begin{array}{rllll} +& I_1 \quad I_2 \quad I_3 \quad I_4 \\ +N - m \cdot I_{\textsf{size}} +& +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[60pt] +\end{array} +}} +\\ +\\[-10pt] +m \cdot I_{\textsf{size}} +& +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\end{array} -``` -NATIVE_CHECK = - acc_prev_native Β· x_native + op + P_x_native Β· v_native + P_y_native Β· vΒ²_native - + z₁_native Β· vΒ³_native + zβ‚‚_native Β· v⁴_native - - quot_native Β· q_native - acc_curr_native -``` +\xrightarrow[]{\textsf{add extra numerator}} + +\begin{array}{lrrrrr} +I_1 \quad I_2 \quad I_3 \quad I_4 \\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\\ +\\[-10pt] +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\\ +\\[-10pt] +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-3pt]\\[-3pt] +\end{array} +}} +\end{array} -And: +\begin{array}{l} + I_5 \\ + \textcolor{lightgreen}{ + \boxed{ + \begin{array}{c} + s \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{lightgreen}{ + \boxed{ + \begin{array}{c} + s \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{lightgreen}{ + \boxed{ + \begin{array}{c} + s \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{lightgreen}{ + \boxed{ + \begin{array}{c} + s \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{lightgreen}{ + \boxed{ + \begin{array}{c} + s \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{violet}{ + \boxed{ + \begin{array}{c} + \\ \\ z \\ \\[2pt] + \end{array} + }} +\end{array} -``` -acc_prev_native = acc_prev[0] + 2^68Β·acc_prev[1] + 2^136Β·acc_prev[2] + 2^204Β·acc_prev[3] (mod r) -``` +\xrightarrow[]{\textsf{sort into ordered polys}} + + +\begin{array}{lrrrrr} +O_1 \quad O_2 \ \ O_3 \quad O_4 \\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\ +\textcolor{orange}{ +\boxed{ +\begin{array}{c} +\\ \\ \\ \\ \\ \\ \\[25pt] +\end{array} +}} +\\ +\\[-10pt] +\textcolor{lightgreen}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\ +\textcolor{lightgreen}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\ +\textcolor{lightgreen}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\ +\textcolor{lightgreen}{ +\boxed{ +\begin{array}{c} +\\[1pt] +\end{array} +}} +\\ +\\[-10pt] \hline\hline +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-6pt]\\[-6pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-6pt]\\[-6pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-6pt]\\[-6pt] +\end{array} +}} +\ +\textcolor{gray}{ +\boxed{ +\begin{array}{c} +\\[-6pt]\\[-6pt] +\end{array} +}} +\\ +\\[-10pt] +\textcolor{violet}{ +\boxed{ +\begin{array}{c} +\\[-2pt] +\end{array} +}} +\ +\textcolor{violet}{ +\boxed{ +\begin{array}{c} +\\[-2pt] +\end{array} +}} +\ +\textcolor{violet}{ +\boxed{ +\begin{array}{c} +\\[-2pt] +\end{array} +}} +\ +\textcolor{violet}{ +\boxed{ +\begin{array}{c} +\\[-2pt] +\end{array} +}} +\end{array} + +\begin{array}{l} + O_5 \\ + \textcolor{orange}{ + \boxed{ + \begin{array}{c} + \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{orange}{ + \boxed{ + \begin{array}{c} + \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{orange}{ + \boxed{ + \begin{array}{c} + \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{orange}{ + \boxed{ + \begin{array}{c} + \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{lightgreen}{ + \boxed{ + \begin{array}{c} + \\[1pt] + \end{array} + }} + \\ + \\[-10pt] + \textcolor{violet}{ + \boxed{ + \begin{array}{c} + \\[10pt] + \end{array} + }} + \\ + \\[-10pt] \hline\hline + \textcolor{gray}{ + \boxed{ + \begin{array}{c} + \\[-6pt]\\[-6pt] + \end{array} + }} + & + \longleftarrow {\scriptsize \textsf{randomness of size}} \left\lfloor\frac{4 \cdot m \cdot I_{\textsf{size}}}{5}\right\rfloor + \\ + \\[-10pt] + \textcolor{violet}{ + \boxed{ + \begin{array}{c} + \\[-2pt] + \end{array} + }} +\end{array} +$$ -**Degree:** 4 (lagrange Γ— triple products like accΒ·x) +> In our case, we have $m=4$ and $I_{\textsf{size}}=16$ which results in $(m \cdot I_{\textsf{size}}) = 64$ masked rows in each interleaved polynomials. Thus, each ordered polynomial will have at least $\left\lfloor\frac{4 \cdot 64}{5}\right\rfloor = 51$ masked rows. The remainder masked row is added to the first ordered polynomial. The masking rows in each ordered polynomial are padded with zero values to ensure the multiset equality holds. +> +> As illustrated, the two sets of interleaved and ordered polynomials satisfy the multiset equality: +> $$\bigcup_{i=1}^5 I_i = \bigcup_{i=1}^5 O_i.$$ + +### Step 7: Zero-Knowledge Masking -**Soundness argument:** +To achieve zero-knowledge, the prover adds random values to the end of polynomials. +For each of the witness polynomials, the masking region is defined as the last $m$ rows of the mini-circuit size, indexed as: -- If the relation holds mod 2²⁷² AND mod r -- AND all values are properly range-constrained -- THEN 2²⁷² Β· r > 2⁡¹⁴ > max_possible_value -- IMPLIES the relation holds in integers -- IMPLIES the relation holds mod q (since q < 2²⁡⁴) +$$[n - m, \ n).$$ -**This is the heart of the Translator circuit.** +After interleaving, the 4 interleaved polynomials have random values at positions: -### Relation 5: Opcode Constraint Relation (5 subrelations) +$$[N - m \cdot I_{\textsf{size}}, \ N).$$ -**Purpose:** Ensure opcodes are valid: op ∈ {0, 1, 2, 3, 4, 8}. +#### Redistributing Randomness to Ordered Polynomials -**Method:** Enforce polynomial identity with roots at valid opcodes. +The ordered polynomials must be committed (unlike interleaved polynomials, which are virtual). To maintain zero-knowledge, the prover redistributes the random values from the 4 interleaved to the 5 ordered polynomials. As illustrated above, each ordered polynomial receives approximately an equal share of the randomness from the interleaved polynomials. The total number of random values in the interleaved polynomials: -$$\boxed{(L_{\text{even}} + L_{\text{mini\_mask}}) \cdot \text{op} \cdot (\text{op} - 1) \cdot (\text{op} - 2) \cdot (\text{op} - 3) \cdot (\text{op} - 4) \cdot (\text{op} - 8) = 0}$$ +$$M = 4 \cdot m \cdot I_{\textsf{size}}.$$ -Actually implemented as 5 separate subrelations for efficiency (one per opcode comparison). +To distribute these $M$ random values to 5 ordered polynomials, each ordered polynomial receives $\left\lfloor\frac{M}{5}\right\rfloor$ random values in its masking region. The remaining random values (if $M$ is not divisible by 5) are distributed one per ordered polynomial starting from the first. Further, since -**Degree:** 6 (lagrange Γ— 5-way product) +$$ +\underbrace{(m \cdot I_{\textsf{size}})}_{\textsf{size of masking region}} > +\underbrace{\left\lfloor \left(\frac{4}{5} \cdot m \cdot I_{\textsf{size}}\right) \right\rfloor}_{\textsf{size of randomness in ordered polys}}, +$$ -**Why important:** Invalid opcodes could allow injection of arbitrary values into the accumulation. +the remaining positions in the ordered masking region are filled with zeros. -### Relation 6: Accumulator Transfer Relation (12 subrelations) +**Note:** The same random values appear in both interleaved and ordered polynomials (just at different positions within the masking region). This is why the $\beta \cdot L_{\text{mask}}$ term is needed in the permutation relation - see [RELATIONS.md](RELATIONS.md#permutation-relation-mathematical-specification) for details. -**Purpose:** Handle non-arithmetic accumulator transitions (initialization, copying, finalization). +Some positions in the ordered masking region contain random values, others contain zeros. The `ordered_extra_range_constraints_numerator` compensates for these zeros in the permutation check. -#### Subrelations 6.1-6.4: Copy at Odd Rows +### Step 8: Precomputed Polynomials -At odd rows, accumulator should not change: +Several polynomials are **precomputed** and independent of the witness: -$$\boxed{L_{\text{odd}} \cdot (\text{acc\_limb}_i - \text{acc\_limb}_i^{(\text{shift})}) = 0}$$ +#### Lagrange Polynomials -For `i ∈ {0, 1, 2, 3}`. +Define row-specific selectors: -#### Subrelations 6.5-6.8: Initialize to Zero +$$ +\begin{aligned} +\texttt{lagrange\_first}[i] &= \begin{cases} 1 & i = 0 \\ 0 & \text{otherwise} \end{cases} \\ +\texttt{lagrange\_last}[i] &= \begin{cases} 1 & i = 2^{17} - 1 \\ 0 & \text{otherwise} \end{cases} \\ +\texttt{lagrange\_even}[i] &= \begin{cases} 1 & i \in [0, 2^{13}), \ i \text{ even} \\ 0 & \text{otherwise} \end{cases} \\ +\texttt{lagrange\_odd}[i] &= \begin{cases} 1 & i \in [0, 2^{13}), \ i \text{ odd} \\ 0 & \text{otherwise} \end{cases} +\end{aligned} +$$ -At the start of accumulation (first row): +#### Ordered Extra Range Constraints Numerator -$$\boxed{L_{\text{first}} \cdot \text{acc\_limb}_i = 0}$$ +This polynomial contains the "step values" repeated to balance the permutation: -For `i ∈ {0, 1, 2, 3}`. +$$\texttt{ordered\_extra}[i \cdot 5 + j] = \text{sorted\_steps}[i] \quad \text{for } i \in [0, 5462), \ j \in [0, 5)$$ -#### Subrelations 6.9-6.12: Final Result Check +where $\text{sorted\_steps} = \{0, 3, 6, 9, \ldots, 16383\}$. -At the result row, accumulator must match expected value: +This ensures the multisets balance: -$$\boxed{L_{\text{result}} \cdot (\text{acc\_limb}_i - \text{expected\_result\_limb}_i) = 0}$$ +- **Numerator:** 4 interleaved + 1 extra (with 5 copies of each step value) +- **Denominator:** 5 ordered (each with 1 copy of each step value) -For `i ∈ {0, 1, 2, 3}`. +--- -The expected result is provided as relation parameters (from ECCVM output). +## Interleaving: The Key Optimization + +The Translator must range-constrain approximately 64 different microlimb sets using permutation argument. The permutation argument's degree equals $1 + \text{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: + +$$ +z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \beta + \gamma) = +z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \beta + \gamma) +$$ -**Degree:** 4 (lagrange Γ— difference) +**The Problem:** Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. -### Relation 7: Zero Constraints Relation (68 subrelations) +**The Solution:** Interleave 16 logical column groups into the same 5 physical wires across 16 circuit segments. Each segment performs an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree by 9Γ—. -**Purpose:** Ensure all range constraint microlimb wires are zero outside the mini-circuit. +### Circuit Structure -**Why needed:** The interleaving structure means full circuit is 16Γ— larger than mini-circuit. Rows outside mini-circuit must be zero to avoid polluting the permutation argument. +``` +Mini-circuit size: 2^13 = 8,192 rows (actual computation) +Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) +FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE = 8,192 Γ— 16 +``` -For each of 64 range constraint wires + 4 transcript wires: +To compute the interleaved polynomials, we group 16 polynomials together and interleave their coefficients. Consider the following 16 polynomials each of size $n=2^{13}$ in the mini-circuit: -$$\boxed{(L_{\text{odd}} + L_{\text{even}} + L_{\text{mini\_mask}})^{\text{complement}} \cdot \text{wire}_i = 0}$$ +$$ +\newcommand{\arraystretch}{1.2} +\begin{array}{|c|c|c|c|c|c|} +\hline +\textsf{index} & \textsf{poly 1} & \textsf{poly 2} & \textsf{poly 3} & \ldots & \textsf{poly 16} \\ +\hline +0 & \textcolor{skyblue}{a_0} & \textcolor{orange}{b_0} & \textcolor{lightgreen}{c_0} & \quad \ldots \quad & \textcolor{firebrick}{p_0} \\ +1 & \textcolor{skyblue}{a_1} & \textcolor{orange}{b_1} & \textcolor{lightgreen}{c_1} & \quad \ldots \quad & \textcolor{firebrick}{p_1} \\ +2 & \textcolor{skyblue}{a_2} & \textcolor{orange}{b_2} & \textcolor{lightgreen}{c_2} & \quad \ldots \quad & \textcolor{firebrick}{p_2} \\ +3 & \textcolor{skyblue}{a_3} & \textcolor{orange}{b_3} & \textcolor{lightgreen}{c_3} & \quad \ldots \quad & \textcolor{firebrick}{p_3} \\[5pt] +\vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\[5pt] +n-1 & \textcolor{skyblue}{a_{n-1}} & \textcolor{orange}{b_{n-1}} & \textcolor{lightgreen}{c_{n-1}} & \quad \ldots \quad & \textcolor{firebrick}{p_{n-1}} \\ +\hline +\end{array} +\quad \longrightarrow \quad +\begin{array}{|c|c|c|} +\hline +\textsf{group} & \textsf{index} & \textsf{interleaved} \\ +\hline +0 & 0 & \textcolor{skyblue}{a_0} \\ +0 & 1 & \textcolor{orange}{b_0} \\ +0 & 2 & \textcolor{lightgreen}{c_0} \\ +\vdots & \vdots & \vdots \\[3pt] +1 & 15 & \textcolor{firebrick}{p_0} \\ \hline +1 & 4 & \textcolor{skyblue}{a_1} \\ +1 & 5 & \textcolor{orange}{b_1} \\ +1 & 6 & \textcolor{lightgreen}{c_1} \\ +\vdots & \vdots & \vdots \\[3pt] +1 & 7 & \textcolor{firebrick}{p_1} \\ \hline +\vdots & \vdots & \vdots \\[5pt] +\vdots & \vdots & \vdots \\ \hline +n-1 & 4n-4 & \textcolor{skyblue}{a_{n-1}} \\ +n-1 & 4n-3 & \textcolor{orange}{b_{n-1}} \\ +n-1 & 4n-2 & \textcolor{lightgreen}{c_{n-1}} \\ +\vdots & \vdots & \vdots \\[3pt] +n-1 & 4n-1 & \textcolor{firebrick}{p_{n-1}} \\ +\hline +\end{array} +$$ -Equivalently (via De Morgan): -$$\boxed{\neg(L_{\text{in\_mini}} \lor L_{\text{mask}}) \implies \text{wire}_i = 0}$$ +The resulting interleaved polynomial has size $16n = 2^{17}$. +For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: -**Special case for no-ops:** If `op = 0` at even rows, additional constraints force range wires to zero. +- **Numerator:** 4 interleaved wires + 1 extra = 5 terms +- **Denominator:** 5 ordered wires = 5 terms +- **Degree:** $1 + 5 = 6$ (or 7 with Lagrange) -**Degree:** 4 (lagrange Γ— wire value) +The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. -**Why important:** Without this, garbage values in unused rows could satisfy the permutation argument while violating actual range constraints. +> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: The interleaved polynomials do not require separate commitments. During proving key construction, the prover computes them for use in sumcheck. In the Gemini PCS phase, the prover sends only **two additional field element evaluations** $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: +> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ +> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. The PCS proof grows by only **2 field elements**. +> +> For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: +> $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ --- @@ -699,7 +1359,7 @@ struct TranslatorProverInput { // Powers of challenges (precomputed) Fq x; - Fq v, v_squared, v_cubed, v_quarted; + Fq v, v_squared, v_cubed, v_quartic; // Proving key std::shared_ptr proving_key; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index 8bd56c7ca248..e13aed0a428c 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -591,3 +591,615 @@ The Decomposition Relation works in tandem with the Delta Range Constraint (a se **Together they guarantee:** All limb decompositions are valid and all values are correctly range-constrained. --- + +## Permutation Relation: Mathematical Specification + +The Permutation Relation is the foundation of all range constraints in the Translator circuit. It proves that every microlimb value used in the circuit belongs to the set $[0, 2^{14} - 1]$. The grand product argument comparing two multisets: + +- **Interleaved multiset:** All microlimbs as they appear in the circuit (spread across 16 segments due to interleaving) +- **Ordered multiset:** The same values, but sorted in ascending order + +If the two multisets are equal (i.e., one is a permutation of the other), then all values are valid. + +The relation consists of **2 subrelations**: + +1. Grand product identity (degree 7) +2. Finalization check (degree 3) + +--- + +#### Interaction with the Delta Range Constraints + +The Permutation Relation works alongside the Delta Range Constraints to enforce microlimb ranges. We use a permutation argument to show that the multiset of microlimb values used in the circuit matches an ordered multiset containing all integers from $0$ to $2^{14} - 1 = 16383$. Instead of including all integers in the range $[0, 2^{14} - 1]$ explicitly, we use a "step" sequence with a fixed step size of 3: + +$$\{0, 3, 6, 9, \ldots, 16380, 16383\}$$ + +resulting in $\left\lceil\frac{16384}{3}\right\rceil = 5462$ values. This ensures that any microlimb value $ \leq 16383$ can be proven to be in range by showing it appears in the ordered multiset. We prove equality of multisets using a grand product argument. The correctness of the ordered multiset is proven by the Delta Range Constraints described in the next section. + +**Balancing the multisets:** The 4 interleaved wires contain only circuit microlimbs, while each of the 5 ordered wires contains circuit microlimbs plus the step sequence. To balance this, we add a 5th numerator wire (`ordered_extra_range_constraints_numerator`) containing 5 copies of the step sequenceβ€”one for each ordered wire. This ensures the multisets have equal cardinality. The Delta Range Constraints enforce that each value in the ordered multiset differs from the previous by at most 3. + +--- + +### Subrelation 1: Grand Product Identity + +**Purpose:** Prove the interleaved and ordered multisets are equal via grand product. + +The grand product polynomial $z_{\text{perm}}$ is defined recursively: + +$$\boxed{z_{\text{perm}}[i+1] \cdot \prod_{j=0}^{4} \left( w_j^{\text{ordered}}[i] + \beta \cdot L_{\text{mask}}[i] + \gamma \right) = z_{\text{perm}}[i] \cdot \prod_{j=0}^{4} \left( w_j^{\text{interleaved}}[i] + \beta \cdot L_{\text{mask}}[i] + \gamma \right)}$$ + +where: + +- $w_j^{\text{interleaved}}[i]$: The $j$-th interleaved range constraint wire at row $i$ +- $w_j^{\text{ordered}}[i]$: The $j$-th ordered (sorted) range constraint wire at row $i$ +- $\beta, \gamma$: Random challenges (from Fiat-Shamir) +- $L_{\text{mask}}[i]$: Lagrange polynomial indicating masking rows (for zero-knowledge) + +The term $(\beta \cdot L_{\text{mask}}[i])$ on both sides enforces that the zero-knowledge masking values in both sets are identical. +The subrelation is then expressed, with boundary conditions, as: + +$$\boxed{\left( z_{\text{perm}} + L_{\text{first}} \right) \cdot \prod_{j=0}^{4} \left( w_j^{\text{interleaved}} + \beta \cdot L_{\text{mask}} + \gamma \right) = \left( z_{\text{perm}}^{\text{shift}} + L_{\text{last}} \right) \cdot \prod_{j=0}^{4} \left( w_j^{\text{ordered}} + \beta \cdot L_{\text{mask}} + \gamma \right)}$$ + +where: + +- $L_{\text{first}}$: Lagrange polynomial for first row (initializes $z_{\text{perm}}[0] = 0$) +- $L_{\text{last}}$: Lagrange polynomial for last row (finalizes $z_{\text{perm}}[\text{last}] = 0$) +- $z_{\text{perm}}^{\text{shift}}$: Shifted grand product polynomial ($z_{\text{perm}}[i+1]$) + +If the two multisets are equal: + +1. At each step, the products telescope: contributions cancel out +2. After processing all rows, the grand product returns to 1 (accounting for initialization/finalization) +3. If any value is out of range or missing from the sorted set, the product cannot telescope correctly + +**Active when:** All rows (both even and odd in the full interleaved circuit) + +**Degree:** 7 (1 + 5 wire products + Lagrange selector) + +--- + +### Subrelation 2: Finalization Check + +**Purpose:** Ensure the grand product polynomial returns to the correct value at the circuit boundary. + +$$\boxed{L_{\text{last}} \cdot z_{\text{perm}}^{\text{shift}} = 0}$$ + +**Interpretation:** + +- At the last row, $L_{\text{last}} = 1$ +- The shifted grand product $z_{\text{perm}}^{\text{shift}}$ (which is $z_{\text{perm}}$ at the row after last) must be 0 +- This ensures the telescoping completed correctly + +**Active when:** Last row only ($L_{\text{last}} = 1$) + +**Degree:** 3 (Lagrange Γ— shifted polynomial) + +--- + +### Security Implications + +**If the Permutation Relation fails:** + +- Attacker can use microlimbs $> 2^{14} - 1$ +- This breaks the range constraint system +- Allows limbs $> 2^{68}$ bits +- Breaks the soundness of Non-Native Field Relation (overflow in Chinese Remainder Theorem) +- Complete circuit soundness failure + +**Critical property:** The sorted multiset must contain: + +- All microlimbs actually used in the circuit +- "Step values" inserted every 3 increments (due to `SORT_STEP = 3`) +- Final value must be exactly $2^{14} - 1 = 16383$ + +--- + +## Delta Range Constraint Relation: Mathematical Specification + +### Purpose and Overview + +The Delta Range Constraint Relation works in tandem with the Permutation Relation to prove that the **ordered (sorted) multiset** is actually sorted and bounded correctly. + +**What it proves:** + +1. The "ordered" wires are actually in non-descending order +2. Consecutive values differ by at most `SORT_STEP = 3` +3. The final value in each column is exactly $2^{14} - 1 = 16383$ + +**Why needed:** The Permutation Relation only proves the multisets are equal. Without the Delta Range Constraint, an attacker could provide an "ordered" set that isn't actually sorted (e.g., [5, 3, 7, 1]), and the permutation would still pass if the interleaved set matches. + +The relation consists of **10 subrelations**: + +- 5 consecutive difference checks (one per ordered wire) +- 5 maximum value checks (one per ordered wire) + +--- + +### Subrelations 1-5: Consecutive Difference Constraints + +**Purpose:** Enforce that each ordered wire is in non-descending order with maximum step 3. + +For each ordered wire $j \in \{0, 1, 2, 3, 4\}$: + +$$\boxed{\left( L_{\text{real\_last}} - 1 \right) \cdot \left( L_{\text{mask}} - 1 \right) \cdot \Delta_j \cdot (\Delta_j - 1) \cdot (\Delta_j - 2) \cdot (\Delta_j - 3) = 0}$$ + +where: +$$\Delta_j := w_j^{\text{ordered}}[i+1] - w_j^{\text{ordered}}[i]$$ + +**Interpretation:** + +The constraint is active when: + +- $L_{\text{real\_last}} = 0$ (not the last real row) +- $L_{\text{mask}} = 0$ (not a masking row) + +When active, it forces: $\Delta_j \in \{0, 1, 2, 3\}$ + +**Why maximum step 3?** + +To ensure full coverage of $[0, 2^{14} - 1]$, we insert "step values" into the sorted array: + +- Start at 0 +- Insert values: 0, 3, 6, 9, ..., 16383 +- This creates `SORTED_STEPS_COUNT = (2^14 - 1) / 3 + 1 = 5462` steps + +Between these steps, actual microlimbs fill in the gaps. With $\Delta \in \{0, 1, 2, 3\}$: + +- No value can "jump over" a step value +- Every value $\leq 16383$ has a step value within distance 3 +- Therefore, all values in range can be represented + +**Excluded rows:** + +- $L_{\text{real\_last}} = 1$: The last real row (boundary condition handled by subrelations 6-10) +- $L_{\text{mask}} = 1$: Zero-knowledge masking rows + +**Active when:** All rows except last and masking rows + +**Degree:** 7 (2 Lagrange terms + 4 polynomial factors for $\Delta$) + +--- + +### Subrelations 6-10: Maximum Value Constraints + +**Purpose:** Ensure the final value in each sorted column is exactly $2^{14} - 1 = 16383$. + +For each ordered wire $j \in \{0, 1, 2, 3, 4\}$: + +$$\boxed{L_{\text{real\_last}} \cdot \left( w_j^{\text{ordered}} - (2^{14} - 1) \right) = 0}$$ + +**Interpretation:** + +At the last real row ($L_{\text{real\_last}} = 1$): +$$w_j^{\text{ordered}}[\text{last}] = 2^{14} - 1 = 16383$$ + +This ensures: + +1. No value in the column exceeds $2^{14} - 1$ +2. The maximum value $2^{14} - 1$ is present in the sorted multiset +3. Combined with the difference constraint, all values are $\leq 2^{14} - 1$ + +**Active when:** Last real row only ($L_{\text{real\_last}} = 1$) + +**Degree:** 3 (Lagrange Γ— difference) + +--- + +### Complete Delta Range Constraint Summary + +| Subrelation | Wire | Constraint Type | Enforces | +| ----------- | ---- | ---------------------- | --------------------------------------------------------------------- | +| 1 | 0 | Consecutive difference | $w_0^{\text{ordered}}[i+1] - w_0^{\text{ordered}}[i] \in \{0,1,2,3\}$ | +| 2 | 1 | Consecutive difference | $w_1^{\text{ordered}}[i+1] - w_1^{\text{ordered}}[i] \in \{0,1,2,3\}$ | +| 3 | 2 | Consecutive difference | $w_2^{\text{ordered}}[i+1] - w_2^{\text{ordered}}[i] \in \{0,1,2,3\}$ | +| 4 | 3 | Consecutive difference | $w_3^{\text{ordered}}[i+1] - w_3^{\text{ordered}}[i] \in \{0,1,2,3\}$ | +| 5 | 4 | Consecutive difference | $w_4^{\text{ordered}}[i+1] - w_4^{\text{ordered}}[i] \in \{0,1,2,3\}$ | +| 6 | 0 | Maximum value | $w_0^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | +| 7 | 1 | Maximum value | $w_1^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | +| 8 | 2 | Maximum value | $w_2^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | +| 9 | 3 | Maximum value | $w_3^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | +| 10 | 4 | Maximum value | $w_4^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | + +--- + +### Interaction with Permutation Relation + +**Together, the two relations prove:** + +| What | Proven By | +| ------------------------------------------------ | ------------------------------------ | +| Ordered set is actually sorted | Delta Range Constraint (subrel 1-5) | +| Maximum value is $2^{14} - 1$ | Delta Range Constraint (subrel 6-10) | +| Interleaved set equals ordered set | Permutation Relation (subrel 1) | +| Grand product telescopes correctly | Permutation Relation (subrel 2) | +| **RESULT:** All microlimbs $\in [0, 2^{14} - 1]$ | Both relations combined | + +**Security:** If either relation fails, range constraints break and circuit soundness is compromised. + +--- + +## Opcode Constraint Relation: Mathematical Specification + +### Purpose and Overview + +The Opcode Constraint Relation enforces that all operation codes (`op`) belong to the valid set: + +$$\boxed{\texttt{op} \in \{0, 1, 2, 3, 4, 8\}}$$ + +**Why needed:** The `op` value is used in selector logic and potentially affects witness generation. Invalid opcodes could: + +- Inject arbitrary values into the accumulation formula +- Bypass range constraints (if `op = 0` has special handling) +- Break the integrity of the EccOpQueue transcript + +**Valid opcodes:** + +- `0`: NULL / No-op +- `1`: Point addition +- `2`: Scalar multiplication +- `3`: Equality check +- `4`: Reset accumulator +- `8`: [Special operation] + +The relation consists of **5 subrelations** (one per non-zero opcode check), implemented for efficiency. + +--- + +### Polynomial Root Constraint + +**Method:** Use a polynomial with roots exactly at the valid opcodes. + +The polynomial: +$$P(\texttt{op}) = \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8)$$ + +has roots at $\{0, 1, 2, 3, 4, 8\}$ and **only** at these values. + +**The constraint:** + +$$\boxed{\left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8) = 0}$$ + +**Interpretation:** + +The constraint is active when: + +- $L_{\text{even}} = 1$ (even rows in mini-circuit), OR +- $L_{\text{mini\_mask}} = 1$ (masking rows in mini-circuit) + +When active: + +- If $\texttt{op} \in \{0, 1, 2, 3, 4, 8\}$, then $P(\texttt{op}) = 0$ βœ“ +- If $\texttt{op} \notin \{0, 1, 2, 3, 4, 8\}$, then $P(\texttt{op}) \neq 0$ βœ— (constraint fails) + +**Active when:** Even rows and mini-circuit masking rows + +**Degree:** 6 (Lagrange + 5-degree polynomial in `op`) + +--- + +### Implementation as 5 Subrelations + +For efficiency in the sumcheck protocol, the constraint is split into 5 subrelations: + +$$ +\boxed{\begin{align*} +&\text{Subrel 1:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) = 0 \\ +&\text{Subrel 2:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 3) = 0 \\ +&\text{Subrel 3:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 4) = 0 \\ +&\text{Subrel 4:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) = 0 \\ +&\text{Subrel 5:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 8) = 0 +\end{align*}} +$$ + +**Why split?** + +- Each subrelation has lower degree (3-4 instead of 6) +- More efficient in sumcheck univariate polynomial computation +- Easier to optimize in implementation + +**Together:** These 5 subrelations are equivalent to the full polynomial constraint. + +--- + +### Security Implications + +**If the Opcode Constraint fails:** + +- Attacker could inject opcode 255 (or any invalid value) +- Potentially bypass range constraint checks (if `op = 0` disables constraints) +- Break accumulation formula integrity +- Compromise EccOpQueue transcript consistency + +**Critical property:** Only valid ECC operations can be proven, ensuring the ECCVM ↔ Translator consistency. + +--- + +## Accumulator Transfer Relation: Mathematical Specification + +### Purpose and Overview + +The Accumulator Transfer Relation manages the **lifecycle of the accumulator** across the circuit: + +1. **Initialization:** Start with zero accumulator +2. **Propagation:** Copy accumulator from even rows to odd rows (data storage) +3. **Computation:** Update accumulator on even rows (handled by Non-Native Field Relation) +4. **Finalization:** Verify final accumulator matches expected result + +**Why needed:** The accumulator must maintain state consistency across rows. Without these constraints: + +- Initial value could be non-zero (offsetting all computations) +- Accumulator could "reset" mid-computation +- Final value might not match ECCVM's expected result + +The relation consists of **12 subrelations**: + +- 4 for odd row propagation (copy previous value) +- 4 for initialization (set to zero) +- 4 for finalization (check against expected result) + +--- + +### Accumulator Structure + +The accumulator is a 254-bit value decomposed into 4 limbs: + +$$a^{\text{curr}} = a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}}$$ + +**Row-by-row behavior:** + +- **Even row $2i$:** Accumulator updated via Non-Native Field Relation (computation) +- **Odd row $2i+1$:** Accumulator copied from even row $2i$ (storage for next cycle) + +The "shift" mechanism: + +- `a_i^{curr}`: Current row's accumulator limb $i$ +- `a_i^{shift}`: Next row's accumulator limb $i$ (accessed via shifted polynomial) + +--- + +### Subrelations 1-4: Odd Row Propagation + +**Purpose:** Ensure accumulator does not change on odd rows (data storage rows). + +For each limb $i \in \{0, 1, 2, 3\}$: + +$$\boxed{L_{\text{odd}} \cdot \left( a_i^{\text{curr}} - a_i^{\text{shift}} \right) = 0}$$ + +**Interpretation:** + +On odd rows ($L_{\text{odd}} = 1$): +$$a_i^{\text{curr}}[\text{odd}] = a_i^{\text{shift}}[\text{odd}] = a_i^{\text{curr}}[\text{next\_even}]$$ + +This creates the "storage" pattern: + +- Even row $2i$: Computes new accumulator value +- Odd row $2i+1$: Stores this value unchanged +- Even row $2i+2$: Accesses odd row $2i+1$ via shift to get "previous" value + +**Active when:** Odd rows only ($L_{\text{odd}} = 1$) + +**Degree:** 3 (Lagrange Γ— difference) + +--- + +### Subrelations 5-8: Initialization + +**Purpose:** Initialize accumulator to zero at the start of the circuit. + +For each limb $i \in \{0, 1, 2, 3\}$: + +$$\boxed{L_{\text{first}} \cdot a_i^{\text{curr}} = 0}$$ + +**Interpretation:** + +At the first row ($L_{\text{first}} = 1$): +$$a_i^{\text{curr}}[0] = 0 \quad \forall i \in \{0, 1, 2, 3\}$$ + +This ensures: +$$a^{\text{curr}}[0] = 0 + 0 \cdot 2^{68} + 0 \cdot 2^{136} + 0 \cdot 2^{204} = 0$$ + +**Why critical:** If the accumulator starts at a non-zero value, all subsequent accumulations are offset by this initial value, breaking the consistency proof. + +**Active when:** First row only ($L_{\text{first}} = 1$) + +**Degree:** 3 (Lagrange Γ— limb value) + +--- + +### Subrelations 9-12: Finalization + +**Purpose:** Verify the final accumulator value matches the expected result from ECCVM. + +For each limb $i \in \{0, 1, 2, 3\}$: + +$$\boxed{L_{\text{result}} \cdot \left( a_i^{\text{curr}} - a_i^{\text{expected}} \right) = 0}$$ + +where $a_i^{\text{expected}}$ is provided as a relation parameter (derived from ECCVM output). + +**Interpretation:** + +At the result row ($L_{\text{result}} = 1$): +$$a_i^{\text{curr}}[\text{result}] = a_i^{\text{expected}} \quad \forall i \in \{0, 1, 2, 3\}$$ + +This ensures: +$$a^{\text{curr}}[\text{result}] = a^{\text{expected}}$$ + +**Expected result derivation:** + +The ECCVM circuit computes the batched evaluation: +$$a^{\text{expected}} = \sum_{j=0}^{n-1} x^{n-1-j} \cdot \left( \texttt{op}_j + v \cdot P_{x,j} + v^2 \cdot P_{y,j} + v^3 \cdot z_{1,j} + v^4 \cdot z_{2,j} \right) \pmod{q}$$ + +The Translator must prove it computed the same value. The finalization check ensures: + +- Translator's computation matches ECCVM's computation +- Consistency between the two circuits + +**Active when:** Result row only ($L_{\text{result}} = 1$) + +**Degree:** 3 (Lagrange Γ— difference) + +--- + +### Complete Accumulator Transfer Summary + +| Subrelation | Limb | Constraint Type | Enforces | +| ----------- | ---- | ------------------- | ---------------------------------------------------------------- | +| 1 | 0 | Odd row propagation | $a_0^{\text{curr}}[\text{odd}] = a_0^{\text{curr}}[\text{next}]$ | +| 2 | 1 | Odd row propagation | $a_1^{\text{curr}}[\text{odd}] = a_1^{\text{curr}}[\text{next}]$ | +| 3 | 2 | Odd row propagation | $a_2^{\text{curr}}[\text{odd}] = a_2^{\text{curr}}[\text{next}]$ | +| 4 | 3 | Odd row propagation | $a_3^{\text{curr}}[\text{odd}] = a_3^{\text{curr}}[\text{next}]$ | +| 5 | 0 | Initialization | $a_0^{\text{curr}}[0] = 0$ | +| 6 | 1 | Initialization | $a_1^{\text{curr}}[0] = 0$ | +| 7 | 2 | Initialization | $a_2^{\text{curr}}[0] = 0$ | +| 8 | 3 | Initialization | $a_3^{\text{curr}}[0] = 0$ | +| 9 | 0 | Finalization | $a_0^{\text{curr}}[\text{result}] = a_0^{\text{expected}}$ | +| 10 | 1 | Finalization | $a_1^{\text{curr}}[\text{result}] = a_1^{\text{expected}}$ | +| 11 | 2 | Finalization | $a_2^{\text{curr}}[\text{result}] = a_2^{\text{expected}}$ | +| 12 | 3 | Finalization | $a_3^{\text{curr}}[\text{result}] = a_3^{\text{expected}}$ | + +--- + +### Interaction with Non-Native Field Relation + +**Division of responsibility:** + +| Relation | Handles | +| ----------------------------- | ----------------------------------------- | +| Non-Native Field Relation | Arithmetic updates on even rows | +| Accumulator Transfer Relation | Initialization, propagation, finalization | + +**Together:** Prove the accumulator correctly accumulates the batched evaluation from start to finish. + +--- + +## Zero Constraints Relation: Mathematical Specification + +### Purpose and Overview + +The Zero Constraints Relation enforces that all witness wires are **zero outside the mini-circuit**. + +**Why needed:** Due to interleaving, the full circuit is 16Γ— larger than the mini-circuit: + +- Mini-circuit: $2^{13} = 8,192$ rows (actual computation) +- Full circuit: $2^{17} = 131,072$ rows (for interleaving optimization) + +Rows outside the mini-circuit (rows 8,192 to 131,071) must be zero. Otherwise: + +- Garbage values pollute the permutation argument +- Range constraints become meaningless +- Circuit soundness breaks + +The relation consists of **68 subrelations**: + +- 64 for range constraint microlimb wires +- 4 for EccOpQueue transcript wires + +--- + +### Which Wires Must Be Zero + +**Range constraint microlimb wires (64 total):** + +- All `*_RANGE_CONSTRAINT_*` columns (see [Witness Trace Structure](#witness-trace-structure)) +- These hold 14-bit microlimbs for decomposition +- Must be zero outside mini-circuit to avoid polluting the permutation + +**Transcript wires (4 total):** + +- `OP`: Opcode +- `X_LO_Y_HI`: Encodes $P_{x,\text{lo}}$ / $P_{y,\text{hi}}$ +- `X_HI_Z_1`: Encodes $P_{x,\text{hi}}$ / $z_1$ +- `Y_LO_Z_2`: Encodes $P_{y,\text{lo}}$ / $z_2$ + +--- + +### Subrelations 1-68: Zero Outside Mini-Circuit + +**General pattern** for each wire $w$: + +$$\boxed{\neg \left( L_{\text{in\_mini}} \lor L_{\text{mask}} \right) \implies w = 0}$$ + +Equivalently (using De Morgan's law and constraint form): + +$$\boxed{\left( 1 - L_{\text{even}} - L_{\text{odd}} - L_{\text{mini\_mask}} + \text{products} \right) \cdot w = 0}$$ + +where: + +- $L_{\text{even}}$: Lagrange for even rows in mini-circuit +- $L_{\text{odd}}$: Lagrange for odd rows in mini-circuit +- $L_{\text{mini\_mask}}$: Lagrange for masking rows in mini-circuit + +**Interpretation:** + +If the row is **not** in the mini-circuit (i.e., row $\geq 8,192$) and **not** a masking row: +$$w[\text{row}] = 0$$ + +This ensures: + +- Only rows 0 to 8,191 contain non-zero witness values +- Rows 8,192 to 131,071 are all zero +- Permutation argument only sees valid microlimbs + +**Active when:** All rows outside the mini-circuit + +**Degree:** 4 (Lagrange polynomial products Γ— wire value) + +--- + +### Special Case: No-Op Rows + +When `op = 0` (no-op) on even rows, additional constraints force range wires to zero **even within the mini-circuit**. + +**Why:** No-op rows don't contribute to the accumulation, so their witness values should be zero to: + +- Reduce prover work +- Improve zero-knowledge properties +- Prevent unnecessary permutation argument entries + +**Additional constraint pattern:** + +$$\boxed{L_{\text{even}} \cdot (1 - \texttt{op}) \cdot w = 0}$$ + +**Interpretation:** + +On even rows ($L_{\text{even}} = 1$) where `op = 0`: +$$w = 0$$ + +This applies to all range constraint wires when the row is a no-op. + +**Active when:** Even rows with `op = 0` + +**Degree:** 4 (Lagrange Γ— (1 - op) Γ— wire) + +--- + +### Complete Zero Constraints Summary + +| Subrelation | Wire Category | Count | Enforces | +| ----------- | --------------------------- | ----- | ------------------------- | +| 1-10 | $P_x$ microlimb wires | 10 | Zero outside mini-circuit | +| 11-20 | $P_y$ microlimb wires | 10 | Zero outside mini-circuit | +| 21-32 | $z$ microlimb wires | 12 | Zero outside mini-circuit | +| 33-42 | Accumulator microlimb wires | 10 | Zero outside mini-circuit | +| 43-52 | Quotient microlimb wires | 10 | Zero outside mini-circuit | +| 53-64 | Carry microlimb wires | 12 | Zero outside mini-circuit | +| 65 | `OP` transcript wire | 1 | Zero outside mini-circuit | +| 66 | `X_LO_Y_HI` transcript wire | 1 | Zero outside mini-circuit | +| 67 | `X_HI_Z_1` transcript wire | 1 | Zero outside mini-circuit | +| 68 | `Y_LO_Z_2` transcript wire | 1 | Zero outside mini-circuit | + +**Additional no-op constraints:** All range wires also zero when `op = 0` on even rows. + +--- + +### Security Implications + +**If the Zero Constraints fail:** + +- Garbage values in rows 8,192+ enter the permutation argument +- Permutation could pass even with invalid microlimbs +- Range constraints become unreliable +- Soundness of entire circuit compromised + +**Critical property:** Interleaving optimization relies on unused rows being zero. Without this, the degree reduction benefit is lost, and soundness breaks. + +--- diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index a9bb94292d5d..8f3bf9f1907e 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -96,7 +96,7 @@ void TranslatorProvingKey::compute_translator_range_constraint_ordered_polynomia // ordered_range_constraint_i up to the given capacity and the remaining elements to the last range constraint. // Sorting is done by converting the elements to uint for efficiency. auto ordering_function = [&](size_t i) { - auto group = to_be_interleaved_groups[i]; + const auto& group = to_be_interleaved_groups[i]; std::vector ordered_vectors_uint(dyadic_circuit_size_without_masking); // Calculate how much space there is for values from the group polynomials given we also need to append the @@ -193,13 +193,12 @@ void TranslatorProvingKey::split_interleaved_random_coefficients_to_ordered() const size_t num_random_values_per_ordered = total_num_random_values / num_ordered_polynomials; const size_t remaining_random_values = total_num_random_values % num_ordered_polynomials; - std::array - random_values = {}; + std::array random_values = {}; // Add the random values from all interleaved polynomials to an array parallel_for(Flavor::NUM_INTERLEAVED_WIRES, [&](size_t i) { size_t idx = i * num_random_values_per_interleaved; - auto current_interleaved = interleaved[i]; + const auto& current_interleaved = interleaved[i]; for (size_t j = dyadic_circuit_size_without_masking; j < current_interleaved.end_index(); j++) { random_values[idx] = current_interleaved.at(j); idx++; From fc7cd8ac52b838b183ebfb3607aa6fc0d3b448d9 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 16 Dec 2025 10:01:13 +0000 Subject: [PATCH 13/29] rm. --- .../src/barretenberg/translator_vm/README.md | 417 ------------------ 1 file changed, 417 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index bfcd1f7d07af..79b6b1ed3194 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -1333,420 +1333,3 @@ The permutation argument verifies that within each group, the interleaved values > $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ --- - -## Proof System Details - -### Proof System Type - -**TranslatorFlavor** uses: - -- **HyperNova-style sumcheck** with ZK (zero-knowledge) -- **KZG polynomial commitment scheme** over BN254 -- **Libra** for ZK masking -- **Gemini + Shplonk** for batched polynomial openings (Shplemini protocol) - -### Inputs to the Prover - -```cpp -struct TranslatorProverInput { - // From ECCVM - std::vector ecc_op_queue; // EC operations to batch - Fq evaluation_challenge_x; // Challenge point x ∈ Fq - Fq batching_challenge_v; // Batching challenge v ∈ Fq - - // Expected output (from ECCVM verification) - Fq expected_accumulator_result; // What acc_final should be - - // Powers of challenges (precomputed) - Fq x; - Fq v, v_squared, v_cubed, v_quartic; - - // Proving key - std::shared_ptr proving_key; -}; -``` - -**Construction:** - -1. For each `UltraOp` in the queue, generate witness values: - - Decompose P.x, P.y, z₁, zβ‚‚ into limbs and microlimbs - - Compute quotient and new accumulator - - Compute relation wide limbs -2. Fill witness polynomials (81 wires Γ— circuit_size values) -3. Construct ordered range constraint polynomials via sorting -4. Create interleaved polynomials - -### Prover Algorithm - -``` -TranslatorProver::prove(): - 1. OINK phase (witness commitment): - - Commit to all 91 witness polynomials (90 + masking) - - Generate commitment challenges - - 2. Sumcheck phase: - - For each round d = 1 to 17: - - Compute sumcheck univariates over all 7 relations - - Send univariate coefficients to verifier - - Receive challenge u_d - - Output: Claimed evaluations at challenge point Ε« - - 3. Libra ZK sumcheck masking: - - Generate ZK commitments - - Prove claimed evaluation matches with ZK - - 4. Gemini multilinear opening: - - Fold multilinear polynomials d-1 times - - Reduce to d univariate openings - - 5. Shplonk batching: - - Batch all opening claims - - Reduce to single KZG opening - - 6. KZG opening proof: - - Compute W commitment - - Output final opening proof - - Return: TranslatorProof (568 field elements) -``` - -### Outputs from the Prover - -```cpp -struct TranslatorProof { - std::vector proof_data; // 568 field elements - Fq accumulated_result; // The batched evaluation result (Fq element) -}; -``` - -The proof contains: - -1. Witness commitments (88 Γ— 2 = 176 Fr elements) -2. Libra commitments and sum (2 + 1 = 3 Fr) -3. Sumcheck univariates (17 rounds Γ— 8 coefficients = 136 Fr) -4. Sumcheck evaluations (188 Fr) -5. Libra evaluation (1 Fr) -6. Libra grand sum and quotient commitments (2 + 2 = 4 Fr) -7. Gemini commitments (16 Γ— 2 = 32 Fr) -8. Gemini evaluations (17 Fr) -9. Gemini positive/negative evaluations (2 Fr) -10. SmallSubgroupIPA evaluations (4 Fr) -11. Shplonk Q commitment (2 Fr) -12. KZG W commitment (2 Fr) -13. Accumulated result in Fq (1 Fq = 1 Fr for encoding) - -### Verifier Algorithm - -``` -TranslatorVerifier::verify(proof, vk): - 1. Deserialize proof - - 2. Reconstruct challenges (Fiat-Shamir): - - Hash commitments to generate challenges - - 3. Sumcheck verification: - - For each round, check univariate identity - - Accumulate claimed evaluations - - 4. Libra verification: - - Verify ZK grand sum - - Check claimed evaluation - - 5. Gemini verification: - - Verify fold commitments - - Check evaluation consistency - - 6. Shplonk verification: - - Batch all opening claims - - 7. KZG pairing check: - - Compute pairing e(W, [Ο„]β‚‚) vs e(commitment, [1]β‚‚) - - Accept if pairing checks pass - - 8. Check accumulated_result matches expected: - - Compare proof's accumulator against ECCVM output - - Return: accept/reject -``` - ---- - -## Proof Size Analysis - -As computed in CHONK_MATH_EXPLAINED.md, the Translator proof size is: - -### Detailed Breakdown - -| Component | Formula | Field Elements | -| --------------------------------- | ------------ | -------------- | -| 1. Accumulated result (BN254 Fq) | `1 Γ— 1` | **1** | -| 2. Witness commitments | `88 Γ— 2` | **176** | -| 3. Libra concatenation commitment | `1 Γ— 2` | **2** | -| 4. Libra sum | `1 Γ— 1` | **1** | -| 5. Sumcheck univariates | `17 Γ— 8 Γ— 1` | **136** | -| 6. Sumcheck evaluations | `188 Γ— 1` | **188** | -| 7. Libra claimed evaluation | `1 Γ— 1` | **1** | -| 8. Libra grand sum commitment | `1 Γ— 2` | **2** | -| 9. Libra quotient commitment | `1 Γ— 2` | **2** | -| 10. Gemini fold commitments | `16 Γ— 2` | **32** | -| 11. Gemini evaluations | `17 Γ— 1` | **17** | -| 12. Gemini P positive evaluation | `1 Γ— 1` | **1** | -| 13. Gemini P negative evaluation | `1 Γ— 1` | **1** | -| 14. SmallSubgroupIPA evals | `4 Γ— 1` | **4** | -| 15. Shplonk Q commitment | `1 Γ— 2` | **2** | -| 16. KZG opening commitment | `1 Γ— 2` | **2** | - -**Total: 568 field elements = 568 Γ— 32 bytes = 18,176 bytes β‰ˆ 17.8 KB** - -### Comparison with Other Components - -| Component | Size (field elements) | Size (KB) | Percentage of Chonk | -| -------------- | --------------------- | --------- | ------------------- | -| **Translator** | **568** | **17.8** | **37.6%** | -| Mega ZK | 356 | 11.1 | 23.6% | -| ECCVM | 488 | 15.2 | 32.3% | -| Merge | 42 | 1.3 | 2.8% | - -**Insight:** Translator is the **largest single component** in the Chonk proof, primarily due to: - -1. 188 sumcheck evaluations (all 91 witness + 86 derived + shifts) -2. 136 sumcheck univariates (17 rounds Γ— 8 coefficients) -3. 176 witness commitments (88 polynomials) - -The large number of witness polynomials (81 explicit + derived) drives the proof size. - ---- - -## Critical Components for Auditing - -Ranked from most to least critical for security: - -### πŸ”΄ **CRITICAL (Audit First)** - -#### 1. Non-Native Field Relation (Relation 4) - -**File:** `translator_non_native_field_relation.hpp` - -**Why critical:** - -- **Core soundness:** This is the heart of the circuit. If this relation is wrong, the entire translation is invalid. -- **Complex arithmetic:** Involves intricate modular arithmetic across two moduli with limb-based computation. -- **Overflow risks:** If the mod 2²⁷² check is wrong, overflow could allow false proofs. - -**What to audit:** - -- Verify the limb combination formulas match the mathematical specification exactly -- Check all powers of 2 (2⁢⁸, 2¹³⁢, etc.) are correct -- Ensure the "wide" relation limbs correctly capture carries -- Confirm native field reconstruction is complete (all cross-terms present) -- Test edge cases: maximum values, zero values, boundary conditions - -**Attack vector:** Incorrect arithmetic could allow proving wrong evaluations, breaking Goblin soundness. - -#### 2. Permutation Relation (Relation 1) - -**File:** `translator_permutation_relation.hpp` - -**Why critical:** - -- **Foundation for range constraints:** If permutation is broken, attacker can use out-of-range values. -- **Grand product soundness:** The z_perm computation must be absolutely correct. -- **Masking handling:** ZK rows must be properly excluded. - -**What to audit:** - -- Verify grand product formula matches the specification -- Check initialization (z_perm[0] = 1 accounting for L_0) -- Verify finalization (z_perm[last] = 0 accounting for L_last and masking) -- Ensure interleaving structure is correctly implemented -- Test with malicious permutations - -**Attack vector:** Broken permutation β†’ use 2⁢⁸ instead of 2¹⁴ limbs β†’ completely break non-native arithmetic. - -#### 3. Delta Range Constraint Relation (Relation 2) - -**File:** `translator_delta_range_constraint_relation.hpp` - -**Why critical:** - -- **Enforces sorted property:** Without this, permutation check is meaningless. -- **Maximum value check:** Must ensure final value is exactly 2¹⁴ - 1. -- **Step constraint:** Max step of 3 is necessary for coverage. - -**What to audit:** - -- Verify Ξ” ∈ {0,1,2,3} check is correctly implemented -- Confirm final value check at lagrange_last is exact -- Check masking rows are properly excluded -- Test boundary: can attacker craft a sequence that looks sorted but isn't? - -**Attack vector:** Wrong max value (e.g., 2¹⁡ instead of 2¹⁴) β†’ double the range β†’ break soundness. - -### 🟠 **HIGH PRIORITY** - -#### 4. Decomposition Relation (Relation 3) - -**File:** `translator_decomposition_relation.hpp` - -**Why high priority:** - -- **Ensures consistency:** Limbs must match original values. -- **Many subrelations (48):** More code = more potential bugs. -- **Tail microlimb logic:** The shift factors must be exact. - -**What to audit:** - -- Verify all 48 decomposition formulas match specification -- Check powers of 2 are correct (2⁢⁸, 2¹⁴, etc.) -- Confirm tail shift calculations (especially the Γ—4, Γ—16 multipliers) -- Test: provide wrong decomposition, ensure relation catches it - -**Attack vector:** Wrong decomposition β†’ mismatch between transcript and limbs β†’ arbitrary values. - -#### 5. Opcode Constraint Relation (Relation 5) - -**File:** `translator_extra_relations.hpp` - -**Why high priority:** - -- **Input validation:** Invalid opcodes could inject malicious data. -- **Relatively simple:** But critical to get right. - -**What to audit:** - -- Verify opcode set {0, 1, 2, 3, 4, 8} is complete and correct -- Check polynomial roots match opcodes exactly -- Ensure masking rows are handled - -**Attack vector:** Missing opcode constraint β†’ inject opcode 255 β†’ break accumulation logic. - -### 🟑 **MEDIUM PRIORITY** - -#### 6. Accumulator Transfer Relation (Relation 6) - -**File:** `translator_extra_relations.hpp` - -**Why medium priority:** - -- **Ensures state consistency:** But doesn't directly affect arithmetic soundness. -- **Edge cases:** Initialization and finalization must be correct. - -**What to audit:** - -- Verify odd row copy constraint is active at all odd rows -- Check initialization to zero at start -- Confirm final result comparison uses correct expected value -- Test: try to skip initialization, see if caught - -**Attack vector:** Wrong initialization β†’ start with non-zero acc β†’ offset all computations. - -#### 7. Zero Constraints Relation (Relation 7) - -**File:** `translator_extra_relations.hpp` - -**Why medium priority:** - -- **Cleanup relation:** Ensures unused rows don't pollute permutation. -- **Many subrelations (68):** But mostly repetitive. - -**What to audit:** - -- Verify all 68 wires are covered -- Check lagrange polynomial logic for "outside minicircuit" -- Ensure no-op case (op = 0) is handled correctly - -**Attack vector:** Garbage in unused rows β†’ permutation allows wrong values β†’ potential soundness break. - -### 🟒 **LOW PRIORITY (But Still Check)** - -#### 8. Circuit Builder Logic - -**File:** `translator_circuit_builder.cpp` - -**Why low priority for audit:** - -- Prover-side only (doesn't affect verification soundness directly) -- But bugs here could cause proof generation failures - -**What to check:** - -- Witness generation formulas match relation formulas -- Quotient calculation is correct -- Microlimb splitting logic matches decomposition relation - -#### 9. Flavor Configuration - -**File:** `translator_flavor.hpp` - -**Why low priority:** - -- Configuration and constants -- But errors here (wrong NUM_LIMB_BITS) would be catastrophic - -**What to check:** - -- All constants match specification -- Proof length formula is correct -- Polynomial commitment configuration is sound - ---- - -## Audit Checklist - -Use this checklist when auditing the Translator: - -### Mathematical Specification - -- [ ] Verify q (Fq modulus) is correct BN254 base field -- [ ] Verify r (Fr modulus) is correct BN254 scalar field -- [ ] Confirm 2²⁷² Β· r > 2⁡¹⁴ (soundness bound) -- [ ] Check limb sizes: 68, 68, 68, 50 bits for 254-bit values -- [ ] Verify microlimb size: 14 bits -- [ ] Confirm SORT_STEP = 3 is sufficient for coverage - -### Non-Native Field Arithmetic - -- [ ] Audit all limb combination formulas in subrelation 4.1 -- [ ] Audit all limb combination formulas in subrelation 4.2 -- [ ] Verify native field reconstruction in subrelation 4.3 -- [ ] Test with maximum value inputs -- [ ] Test with zero inputs -- [ ] Test with adversarial quotients - -### Range Constraints - -- [ ] Verify permutation grand product formula -- [ ] Check delta constraint polynomial (degree 5 product) -- [ ] Confirm final value = 2¹⁴ - 1 exactly -- [ ] Test with out-of-order values -- [ ] Test with values > 2¹⁴ - -### Decomposition - -- [ ] Verify all 6 binary limb decompositions -- [ ] Verify all 44 microlimb decompositions -- [ ] Check all 42 tail microlimb stricter constraints -- [ ] Test with wrong decompositions - -### Edge Cases - -- [ ] First row (initialization) -- [ ] Last row (finalization) -- [ ] No-op case (op = 0) -- [ ] Masking rows (ZK) -- [ ] Interleaving boundary - -### Implementation - -- [ ] Code review all relation implementations -- [ ] Verify relation degrees match specification -- [ ] Check lagrange polynomial usage is correct -- [ ] Ensure no off-by-one errors in indices -- [ ] Test proof generation and verification end-to-end - ---- - -**Document Version:** 1.0 -**Author:** ZK Content Expert -**Last Updated:** 2025-12-04 -**Purpose:** Advanced Modern Cryptography Course Material & Security Audit Guide From 413305355a062617cea7a25139445a91ecacbe9a Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 16 Dec 2025 10:02:29 +0000 Subject: [PATCH 14/29] reorg. --- .../src/barretenberg/translator_vm/README.md | 162 +++++++++--------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 79b6b1ed3194..91990292c300 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -336,6 +336,87 @@ The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange --- +## Interleaving: The Key Optimization + +The Translator must range-constrain approximately 64 different microlimb sets using permutation argument. The permutation argument's degree equals $1 + \text{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: + +$$ +z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \beta + \gamma) = +z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \beta + \gamma) +$$ + +**The Problem:** Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. + +**The Solution:** Interleave 16 logical column groups into the same 5 physical wires across 16 circuit segments. Each segment performs an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree by 9Γ—. + +### Circuit Structure + +``` +Mini-circuit size: 2^13 = 8,192 rows (actual computation) +Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) +FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE = 8,192 Γ— 16 +``` + +To compute the interleaved polynomials, we group 16 polynomials together and interleave their coefficients. Consider the following 16 polynomials each of size $n=2^{13}$ in the mini-circuit: + +$$ +\newcommand{\arraystretch}{1.2} +\begin{array}{|c|c|c|c|c|c|} +\hline +\textsf{index} & \textsf{poly 1} & \textsf{poly 2} & \textsf{poly 3} & \ldots & \textsf{poly 16} \\ +\hline +0 & \textcolor{skyblue}{a_0} & \textcolor{orange}{b_0} & \textcolor{lightgreen}{c_0} & \quad \ldots \quad & \textcolor{firebrick}{p_0} \\ +1 & \textcolor{skyblue}{a_1} & \textcolor{orange}{b_1} & \textcolor{lightgreen}{c_1} & \quad \ldots \quad & \textcolor{firebrick}{p_1} \\ +2 & \textcolor{skyblue}{a_2} & \textcolor{orange}{b_2} & \textcolor{lightgreen}{c_2} & \quad \ldots \quad & \textcolor{firebrick}{p_2} \\ +3 & \textcolor{skyblue}{a_3} & \textcolor{orange}{b_3} & \textcolor{lightgreen}{c_3} & \quad \ldots \quad & \textcolor{firebrick}{p_3} \\[5pt] +\vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\[5pt] +n-1 & \textcolor{skyblue}{a_{n-1}} & \textcolor{orange}{b_{n-1}} & \textcolor{lightgreen}{c_{n-1}} & \quad \ldots \quad & \textcolor{firebrick}{p_{n-1}} \\ +\hline +\end{array} +\quad \longrightarrow \quad +\begin{array}{|c|c|c|} +\hline +\textsf{group} & \textsf{index} & \textsf{interleaved} \\ +\hline +0 & 0 & \textcolor{skyblue}{a_0} \\ +0 & 1 & \textcolor{orange}{b_0} \\ +0 & 2 & \textcolor{lightgreen}{c_0} \\ +\vdots & \vdots & \vdots \\[3pt] +1 & 15 & \textcolor{firebrick}{p_0} \\ \hline +1 & 4 & \textcolor{skyblue}{a_1} \\ +1 & 5 & \textcolor{orange}{b_1} \\ +1 & 6 & \textcolor{lightgreen}{c_1} \\ +\vdots & \vdots & \vdots \\[3pt] +1 & 7 & \textcolor{firebrick}{p_1} \\ \hline +\vdots & \vdots & \vdots \\[5pt] +\vdots & \vdots & \vdots \\ \hline +n-1 & 4n-4 & \textcolor{skyblue}{a_{n-1}} \\ +n-1 & 4n-3 & \textcolor{orange}{b_{n-1}} \\ +n-1 & 4n-2 & \textcolor{lightgreen}{c_{n-1}} \\ +\vdots & \vdots & \vdots \\[3pt] +n-1 & 4n-1 & \textcolor{firebrick}{p_{n-1}} \\ +\hline +\end{array} +$$ + +The resulting interleaved polynomial has size $16n = 2^{17}$. +For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: + +- **Numerator:** 4 interleaved wires + 1 extra = 5 terms +- **Denominator:** 5 ordered wires = 5 terms +- **Degree:** $1 + 5 = 6$ (or 7 with Lagrange) + +The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. + +> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: The interleaved polynomials do not require separate commitments. During proving key construction, the prover computes them for use in sumcheck. In the Gemini PCS phase, the prover sends only **two additional field element evaluations** $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: +> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ +> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. The PCS proof grows by only **2 field elements**. +> +> For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: +> $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ + +--- + ## Witness Generation and Proving Key Construction This section details how the Translator circuit's witness polynomials are populated and how zero-knowledge is achieved through masking. @@ -1252,84 +1333,3 @@ This ensures the multisets balance: - **Denominator:** 5 ordered (each with 1 copy of each step value) --- - -## Interleaving: The Key Optimization - -The Translator must range-constrain approximately 64 different microlimb sets using permutation argument. The permutation argument's degree equals $1 + \text{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: - -$$ -z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \beta + \gamma) = -z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \beta + \gamma) -$$ - -**The Problem:** Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. - -**The Solution:** Interleave 16 logical column groups into the same 5 physical wires across 16 circuit segments. Each segment performs an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree by 9Γ—. - -### Circuit Structure - -``` -Mini-circuit size: 2^13 = 8,192 rows (actual computation) -Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) -FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE = 8,192 Γ— 16 -``` - -To compute the interleaved polynomials, we group 16 polynomials together and interleave their coefficients. Consider the following 16 polynomials each of size $n=2^{13}$ in the mini-circuit: - -$$ -\newcommand{\arraystretch}{1.2} -\begin{array}{|c|c|c|c|c|c|} -\hline -\textsf{index} & \textsf{poly 1} & \textsf{poly 2} & \textsf{poly 3} & \ldots & \textsf{poly 16} \\ -\hline -0 & \textcolor{skyblue}{a_0} & \textcolor{orange}{b_0} & \textcolor{lightgreen}{c_0} & \quad \ldots \quad & \textcolor{firebrick}{p_0} \\ -1 & \textcolor{skyblue}{a_1} & \textcolor{orange}{b_1} & \textcolor{lightgreen}{c_1} & \quad \ldots \quad & \textcolor{firebrick}{p_1} \\ -2 & \textcolor{skyblue}{a_2} & \textcolor{orange}{b_2} & \textcolor{lightgreen}{c_2} & \quad \ldots \quad & \textcolor{firebrick}{p_2} \\ -3 & \textcolor{skyblue}{a_3} & \textcolor{orange}{b_3} & \textcolor{lightgreen}{c_3} & \quad \ldots \quad & \textcolor{firebrick}{p_3} \\[5pt] -\vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\[5pt] -n-1 & \textcolor{skyblue}{a_{n-1}} & \textcolor{orange}{b_{n-1}} & \textcolor{lightgreen}{c_{n-1}} & \quad \ldots \quad & \textcolor{firebrick}{p_{n-1}} \\ -\hline -\end{array} -\quad \longrightarrow \quad -\begin{array}{|c|c|c|} -\hline -\textsf{group} & \textsf{index} & \textsf{interleaved} \\ -\hline -0 & 0 & \textcolor{skyblue}{a_0} \\ -0 & 1 & \textcolor{orange}{b_0} \\ -0 & 2 & \textcolor{lightgreen}{c_0} \\ -\vdots & \vdots & \vdots \\[3pt] -1 & 15 & \textcolor{firebrick}{p_0} \\ \hline -1 & 4 & \textcolor{skyblue}{a_1} \\ -1 & 5 & \textcolor{orange}{b_1} \\ -1 & 6 & \textcolor{lightgreen}{c_1} \\ -\vdots & \vdots & \vdots \\[3pt] -1 & 7 & \textcolor{firebrick}{p_1} \\ \hline -\vdots & \vdots & \vdots \\[5pt] -\vdots & \vdots & \vdots \\ \hline -n-1 & 4n-4 & \textcolor{skyblue}{a_{n-1}} \\ -n-1 & 4n-3 & \textcolor{orange}{b_{n-1}} \\ -n-1 & 4n-2 & \textcolor{lightgreen}{c_{n-1}} \\ -\vdots & \vdots & \vdots \\[3pt] -n-1 & 4n-1 & \textcolor{firebrick}{p_{n-1}} \\ -\hline -\end{array} -$$ - -The resulting interleaved polynomial has size $16n = 2^{17}$. -For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: - -- **Numerator:** 4 interleaved wires + 1 extra = 5 terms -- **Denominator:** 5 ordered wires = 5 terms -- **Degree:** $1 + 5 = 6$ (or 7 with Lagrange) - -The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. - -> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: The interleaved polynomials do not require separate commitments. During proving key construction, the prover computes them for use in sumcheck. In the Gemini PCS phase, the prover sends only **two additional field element evaluations** $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: -> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ -> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. The PCS proof grows by only **2 field elements**. -> -> For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: -> $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ - ---- From 20f2edfdbc53e305d57ca52604b6b606193ffadb Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 16 Dec 2025 10:18:19 +0000 Subject: [PATCH 15/29] correction. --- barretenberg/cpp/src/barretenberg/translator_vm/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 91990292c300..c5e1bea78e3c 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -408,12 +408,12 @@ For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. -> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: The interleaved polynomials do not require separate commitments. During proving key construction, the prover computes them for use in sumcheck. In the Gemini PCS phase, the prover sends only **two additional field element evaluations** $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: -> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ -> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. The PCS proof grows by only **2 field elements**. -> +> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: > For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: > $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ +> The interleaved polynomials do not require separate commitments because they can be derived from the original polynomials' commitments. In the Gemini PCS phase, the prover sends only two additional field element evaluations $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: +> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ +> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. --- From 41ed8ed3fc59c0ec6b410aaf83db764cfb1a2df7 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 16 Dec 2025 11:42:45 +0000 Subject: [PATCH 16/29] update. --- .../src/barretenberg/translator_vm/README.md | 21 +- .../barretenberg/translator_vm/RELATIONS.md | 273 +++--------------- 2 files changed, 52 insertions(+), 242 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index c5e1bea78e3c..1ec2fe610bd4 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -8,32 +8,27 @@ 2. [High-Level Statement](#high-level-statement) 3. [Architecture and Constants](#architecture-and-constants) 4. [Witness Trace Structure](#witness-trace-structure) -5. [Witness Generation and Proving Key Construction](#witness-generation-and-proving-key-construction) -6. [Interleaving: The Key Optimization](#interleaving-the-key-optimization) -7. [The Seven Relations](#the-seven-relations) -8. [Proof System Details](#proof-system-details) -9. [Proof Size Analysis](#proof-size-analysis) -10. [Critical Components for Auditing](#critical-components-for-auditing) +5. [Interleaving: The Key Optimization](#interleaving-the-key-optimization) +6. [Witness Generation and Proving Key Construction](#witness-generation-and-proving-key-construction) +7. [Translator Relations](#translator-relations) --- ## Overview -The **Translator Circuit** is a critical component of the Goblin Plonk proving system in Aztec. It serves as a bridge between the Mega and ECCVM circuits. +The Translator circuit is a critical component of the Goblin Plonk proving system in Aztec. It serves as a bridge between the Mega and ECCVM circuits. | Curve | Base Field | Scalar Field | Usage | | -------- | -------------- | -------------- | ----------------------------------------- | | BN254 | $\mathbb{F}_q$ | $\mathbb{F}_r$ | Used in Mega circuits | | Grumpkin | $\mathbb{F}_r$ | $\mathbb{F}_q$ | Used in ECCVM for efficient EC operations | -When proving recursive circuits with Mega circuit builder, we accumulate elliptic curve operations in an `EccOpQueue`. Proving these ECC operations is delegated to the ECCVM circuit, which operates over the Grumpkin curve. However, the **same operations have different representations** in the two circuits because: +When proving recursive circuits with Mega circuit builder, we accumulate elliptic curve operations in an `EccOpQueue`. Proving these ECC operations is delegated to the ECCVM circuit, which operates over the Grumpkin curve. However, the same operations have different representations in the two circuits because: - Mega circuit operates over the BN254 scalar field $\mathbb{F}_r$ so elements in $\mathbb{F}_q$ are non-native (i.e., they need to decomposed into limbs in $\mathbb{F}_r$) - ECCVM operates over the Grumpkin scalar field $\mathbb{F}_q$ so elements in $\mathbb{F}_q$ are circuit native -For example, consider the operation $(z \cdot P)$ where $P$ is a point on the curve and $z$ is a scalar: - -The ECCVM arithmetisation represents this operation (in 1 row) as: +For example, consider the operation $(z \cdot P)$ where $P$ is a point on the curve and $z$ is a scalar. The ECCVM arithmetisation represents this operation (in 1 row) as: | Opcode | $x$-coordinate | $y$-coordinate | Scalar $z_1$ | Scalar $z_2$ | Full scalar $z$ | | ------ | -------------- | -------------- | ------------ | ------------ | --------------- | @@ -1333,3 +1328,7 @@ This ensures the multisets balance: - **Denominator:** 5 ordered (each with 1 copy of each step value) --- + +## Translator Relations + +Constraints for the translator VM are specified in [RELATIONS.md](RELATIONS.md). diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index e13aed0a428c..d49f0a038fac 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -1,12 +1,8 @@ # Translator Relations -## Document Purpose +The translator VM enforces several relations/constraints to ensure the correctness of non-native field arithmetic and other operations. The primary relation is the **Non-Native Field Relation**, which verifies that certain accumulations hold in a non-native field (the BN254 base field $\mathbb{F}_q$) while operating in the native field (the BN254 scalar field $\mathbb{F}_p$). -This document provides a rigorous mathematical treatment of the **Non-Native Field Relation** in the Translator circuit, using consistent LaTeX nomenclature throughout. This is the core relation that enables computation in 𝔽q (BN254 base field) using only 𝔽p (BN254 scalar field) arithmetic. - ---- - -### Active Constraints by Row Type +Since we follow a two-row trace structure, some relations are only active on even rows, while others are only active on odd rows. Below is a summary of the relations and their activation patterns. | Constraint | Active on Even Rows | Active on Odd Rows | | ------------------------------------------ | ------------------- | ------------------ | @@ -16,37 +12,23 @@ This document provides a rigorous mathematical treatment of the **Non-Native Fie | Range Constraints (Permutation) | βœ“ | βœ“ | | Decomposition Relations | βœ“ | βœ“ | -**Lagrange selectors**: +Lagrange selectors: - $L_{\text{even}}$: Equals 1 on even rows, 0 elsewhere - $L_{\text{odd}}$: Equals 1 on odd rows, 0 elsewhere ---- - ## Table of Contents 1. [Limb Decomposition Structure](#limb-decomposition-structure) -2. [The Problem Statement](#the-problem-statement) -3. [Nomenclature and Notation](#nomenclature-and-notation) -4. [The Three Subrelations](#the-three-subrelations) -5. [Subrelation 1: Lower Mod 2¹³⁢ Check](#subrelation-1-lower-mod-2136-check) -6. [Subrelation 2: Higher Mod 2¹³⁢ Check](#subrelation-2-higher-mod-2136-check) -7. [Subrelation 3: Native Field Check](#subrelation-3-native-field-check) -8. [Soundness Argument](#soundness-argument) -9. [Complete Constraint System](#complete-constraint-system) +2. [Non Native Field Relations](#non-native-field-relations) +3. [Decomposition Relation](#decomposition-relation) +4. [Accumulator Transfer Relation](#accumulator-transfer-relation) +5. [Opcode Constraint](#opcode-constraint) --- ## Limb Decomposition Structure -### Why 68-bit Limbs? - -- Need to represent 254-bit values (elements of 𝔽q) -- Split into **4 limbs**: 68 + 68 + 68 + 50 = 254 bits -- 68 bits chosen for efficient range constraints (68 = 14 Γ— 4 + 12) - -### Complete Decomposition Table - This table establishes **all notation** used in the relations: | Value | Native (𝔽q) | Binary Limbs | Native (𝔽p) | @@ -75,7 +57,7 @@ This table establishes **all notation** used in the relations: | **Opcode (witness, small)** | | $\texttt{op}$ | Operation code | (no decomposition, ≀ 8) | $\texttt{op}$ | -### Reconstruction Formula (General) +#### Reconstruction Formula (General) For a 254-bit value decomposed as $\ell_0, \ell_1, \ell_2, \ell_3$: @@ -105,91 +87,24 @@ The quotient $\mathcal{Q}$ is reconstructed as: $$\mathcal{Q} = q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3$$ ---- - -## The Problem Statement - -### Field Moduli - -| Symbol | Value | Description | -| ------ | -------------------------------------------------------------------- | ------------------------------- | -| $q$ | `0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` | BN254 base field modulus (𝔽q) | -| $p$ | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽p) | - -**Key fact:** $q \neq p$, so we cannot directly compute in 𝔽q using 𝔽p arithmetic. - -### Goal - -Prove the following accumulation identity holds in $\mathbb{F}_q$: - -$$\boxed{a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}}$$ - -### Challenge - -We can only perform arithmetic in $\mathbb{F}_p$ (the scalar field), but we need to prove correctness in $\mathbb{F}_q$ (the base field). - -### Solution Approach - -Rewrite as an integer equation with quotient: - -$$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \mathcal{Q} \cdot q - a^{\text{curr}} = 0 \quad (\text{in integers})$$ - -**Key insight:** If this equation holds: - -1. **Modulo $2^{272}$** (via limb arithmetic in 𝔽p), AND -2. **Modulo $p$** (native 𝔽p computation), AND -3. All values are properly range-constrained - -Then it holds in integers (since $2^{272} \cdot p > 2^{514}$ > max possible value), which implies it holds modulo $q$. - -### Negative Prime Modulus - -We work with $-q \pmod{2^{272}}$ to avoid subtraction: - -$$\bar{q} := 2^{272} - q$$ - -Decomposed into limbs: - -$$\bar{q} = \bar{q}_0 + 2^{68} \cdot \bar{q}_1 + 2^{136} \cdot \bar{q}_2 + 2^{204} \cdot \bar{q}_3$$ - -Plus native field representation: $\bar{q}_4 = -q \pmod{p}$ - ---- - -## The Problem Statement - -### Goal +## Non-Native Field Relations -Prove the following accumulation identity holds in 𝔽q: +We want to prove the following accumulation identity holds in $\mathbb{F}_q$: $$\boxed{a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}}$$ -### Challenge - -We can only perform arithmetic in 𝔽p (the scalar field), but we need to prove correctness in 𝔽q (the base field). -Since $q \neq p$, so we cannot directly compute in 𝔽q using 𝔽p arithmetic. - -| Symbol | LaTeX | Value | Description | -| ------ | ----- | -------------------------------------------------------------------- | ------------------------------- | -| q | `q` | `0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47` | BN254 base field modulus (𝔽q) | -| p | `p` | `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001` | BN254 scalar field modulus (𝔽p) | - -### Solution Approach - -Rewrite as an integer equation with quotient: +We can only perform arithmetic in $\mathbb{F}_p$, but we need to prove correctness in $\mathbb{F}_q$ (the base field). +To do this, we rewrite the above equation as an integer equation with quotient $\mathcal{Q}$: $$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \mathcal{Q} \cdot q - a^{\text{curr}} = 0 \quad (\text{in integers})$$ -**Key insight:** If this equation holds: +If this equation holds: -1. **Modulo 2²⁷²** (via limb arithmetic in 𝔽p), AND -2. **Modulo p** (native 𝔽p computation), AND +1. Modulo $2^{272}$ (via limb arithmetic in $\mathbb{F}_p$), and +2. Modulo $p$ (native $\mathbb{F}_p$ computation), and 3. All values are properly range-constrained -Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot p > 2^{514}$ > max possible value), which implies it holds modulo q. -See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. - -## Non-Native Field Relations +Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot p > 2^{514}$ > max possible value), which implies it holds modulo $q$. See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. The non-native field relation is enforced through **three separate subrelations**: @@ -201,6 +116,12 @@ The non-native field relation is enforced through **three separate subrelations* Together, these prove the relation holds in integers. +> **Negative Modulus Constant**: We work with $-q \pmod{2^{272}}$ to avoid subtraction: +> $$\bar{q} := 2^{272} - q$$ +> Decomposed into limbs: +> $$\bar{q} = \bar{q}_0 + 2^{68} \cdot \bar{q}_1 + 2^{136} \cdot \bar{q}_2 + 2^{204} \cdot \bar{q}_3$$ +> Plus native field representation: $\bar{q}_4 = -q \pmod{p}$ + --- ### Subrelation 1: Lower Mod 2¹³⁢ Check @@ -261,8 +182,6 @@ $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_0 + 2^{68} \cdot T_1 - - $L_{\text{even}} = 1$ (even rows in mini-circuit) - $\texttt{op} \neq 0$ (not a no-op) ---- - ### Subrelation 2: Higher Mod 2¹³⁢ Check Prove that when we compute the accumulation formula using limbs 2 and 3, plus the carry from subrelation 1, the result is a multiple of $2^{136}$. @@ -308,7 +227,7 @@ The combined subrelation 2 is: $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_2 + 2^{68} \cdot T_3 - 2^{136} \cdot c^{\text{hi}} \right) = 0}$$ -**Interpretation:** +Interpretation: - Start with carry $c^{\text{lo}}$ from subrelation 1 - Add limb 2 contribution $T_2$ @@ -316,11 +235,9 @@ $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_2 + 2^{68} \cdot T_3 - - Result should be $c^{\text{hi}} \cdot 2^{136}$ - If this holds, the higher 136 bits are correct -**Together with Subrelation 1:** We've proven the relation holds modulo $2^{272}$. - ---- +Together with Subrelation 1: We've proven the relation holds modulo $2^{272}$. -## Subrelation 3: Native Field Check +### Subrelation 3: Native Field Check Prove the accumulation formula holds when computed directly in 𝔽p (the native field). @@ -361,7 +278,7 @@ Where: - $x_4, v_4, (v^2)_4, (v^3)_4, (v^4)_4$ are the native field representations of the challenges - $\bar{q}_4 = -q \pmod{p}$ -**Interpretation:** +Interpretation: - Reconstruct all limbed values back to native $\mathbb{F}_{p}$ elements - Compute the accumulation formula directly in $\mathbb{F}_{p}$ @@ -369,64 +286,7 @@ Where: --- -## Soundness Argument - -### The Two-Moduli Approach - -We prove the accumulation identity holds in three ways: - -1. **Modulo $2^{136}$ (lower):** Subrelation 1 -2. **Modulo $2^{136}$ (higher):** Subrelation 2, which together with 1 gives mod $2^{272}$ -3. **Modulo $p$:** Subrelation 3 - -### Chinese Remainder Theorem Intuition - -If an equation holds modulo $M_1$ and modulo $M_2$ where $\gcd(M_1, M_2) = 1$, then it holds modulo $M_1 \cdot M_2$. - -**Application:** - -- $\gcd(2^{272}, p) = 1$ (since $p$ is odd prime) -- If equation holds mod $2^{272}$ AND mod $p$ -- Then it holds mod $2^{272} \cdot p$ - -### Maximum Value Bound - -**Maximum possible value of LHS:** - -$$\text{Max} = \max(a^{\text{prev}}) \cdot \max(x) + \text{sum of other products}$$ - -Each factor is at most $2^{254}$, so: - -$$\text{Max} < 2^{254} \cdot 2^{254} + 4 \cdot 2^{254} \cdot 2^{254} < 5 \cdot 2^{508} < 2^{511}$$ - -$$\implies 2^{272} \cdot p > 2^{272} \cdot 2^{253} = 2^{525} > 2^{511} > \text{Max}$$ - -**Conclusion:** - -- If the equation holds mod $2^{272} \cdot p$ -- AND all values are bounded as above -- THEN the equation holds in integers (no wraparound possible) -- THEREFORE it holds modulo any smaller modulus, including $q$ - -### Range Constraints are Critical - -The soundness argument **requires** that all limbs are properly range-constrained: - -| Limb | Required Range | Enforced By | -| ------------------------------------------------ | ------------------------------ | -------------------------------------- | -| $P_{x,i}^{\text{lo}}, P_{x,i}^{\text{hi}}$ (i=0) | $[0, 2^{68})$ | Decomposition + Delta Range Constraint | -| $P_{x,1}^{\text{hi}}$ | $[0, 2^{50})$ | Stricter constraint via tail microlimb | -| All other 68-bit limbs | $[0, 2^{68})$ | Permutation argument | -| Quotient limbs | $[0, 2^{68})$ or $[0, 2^{52})$ | Permutation argument | -| Carries $c^{\text{lo}}, c^{\text{hi}}$ | $[0, 2^{84})$ | Relation wide limb range constraints | - -**If any limb is out of range**, the maximum value bound is violated and soundness breaks. - ---- - -## Decomposition Relation: Mathematical Specification - -### Purpose and Overview +## Decomposition Relation The decomposition relation enforces the integrity of the limb decomposition system. While the Non-Native Field Relation proves the accumulation formula is correct, the Decomposition Relation proves all limb decompositions are valid. @@ -444,7 +304,7 @@ These work with the **Delta Range Constraint** permutation argument that proves ### The 14-bit Microlimb System -**Two-level decomposition hierarchy:** +Two-level decomposition hierarchy: 1. Level 1 (68-bit limbs): 254-bit values β†’ 68 + 68 + 68 + 50 bits 2. Level 2 (14-bit microlimbs): 68-bit limbs β†’ 14 + 14 + 14 + 14 + 12 bits @@ -453,7 +313,7 @@ Microlimb reconstruction formula for a 68-bit limb $\ell$ with microlimbs $m_0, $$\boxed{\ell = m_0 + m_1 \cdot 2^{14} + m_2 \cdot 2^{28} + m_3 \cdot 2^{42} + m_4 \cdot 2^{56}}$$ -**Range constraints:** +Range constraints: - All microlimbs $m_j \in [0, 2^{14})$ (enforced by permutation) - For 68-bit limbs: $m_4 \in [0, 2^{12})$ @@ -461,11 +321,9 @@ $$\boxed{\ell = m_0 + m_1 \cdot 2^{14} + m_2 \cdot 2^{28} + m_3 \cdot 2^{42} + m - For 52-bit limbs: $m_3 \in [0, 2^{10})$ - For 60-bit limbs: $m_4 \in [0, 2^{4})$ ---- - -### Categories 1-2: Microlimb Decomposition (Subrelations 0-19) +### Categories 1 and 2: Microlimb Decomposition (Subrelations 0-19) -**General pattern** for decomposing a limb $\ell_i$ into microlimbs $\{\ell_{i,j}\}$: +General pattern for decomposing a limb $\ell_i$ into microlimbs $\{\ell_{i,j}\}$: $$\boxed{L_{\text{selector}} \cdot \left( \sum_{j=0}^{k} \ell_{i,j} \cdot 2^{14j} - \ell_i \right) = 0}$$ where $k=4$ for 68/60-bit limbs and $k=3$ for 50/52-bit limbs. @@ -484,8 +342,6 @@ where $k=4$ for 68/60-bit limbs and $k=3$ for 50/52-bit limbs. | $\mathcal{Q}$ | $q_0, q_1, q_2, q_3$ | 4 | 68 + 68 + 68 + 52 bits | | | | | | ---- - ### Category 3: Wide Limb Decomposition (Subrelations 20-21) Carry limbs $c^{\text{lo}}, c^{\text{hi}}$ are **84 bits** (6 Γ— 14-bit microlimbs). To save space, the 5th and 6th microlimbs are stored in unused "tail" columns: @@ -501,8 +357,6 @@ where $c^{(0)} = c^{\text{lo}}$, $c^{(1)} = c^{\text{hi}}$. - $c_{1,4}^{\text{micro}}$ = `p_y_high_limbs_range_constraint_tail_shift` - $c_{1,5}^{\text{micro}}$ = `quotient_high_limbs_range_constraint_tail_shift` ---- - ### Category 4: Range Constraint Tightening (Subrelations 22-41) For limbs with $b = 14k + r$ bits (where $0 < r < 14$), the highest microlimb $m_k$ must satisfy $m_k < 2^r$. @@ -555,44 +409,21 @@ $$\boxed{L_{\text{even}} \cdot \left( \ell_{\text{low}} + 2^{68} \cdot \ell_{\te - `X_HI_Z_1`: $P_{x,\text{hi}}$ / $z_1$ - `Y_LO_Z_2`: $P_{y,\text{lo}}$ / $z_2$ ---- - -### Complete Decomposition Relation Summary - -The Decomposition Relation enforces 48 independent constraints: - -| Subrelations | Category | Purpose | -| ------------ | ---------------------------- | ---------------------------------------------------------- | -| 0-3 | Accumulator microlimb decomp | Prove $a_i^{\text{curr}}$ correctly decomposes (4 limbs) | -| 4-7 | $P_y$ microlimb decomp | Prove $P_y$ limbs correctly decompose (4 limbs) | -| 8-11 | $z_1, z_2$ microlimb decomp | Prove $z$ limbs correctly decompose (2 values Γ— 2 limbs) | -| 12-15 | $P_x$ microlimb decomp | Prove $P_x$ limbs correctly decompose (4 limbs) | -| 16-19 | Quotient microlimb decomp | Prove $\mathcal{Q}$ limbs correctly decompose (4 limbs) | -| 20-21 | Wide limb decomp | Prove carry limbs $c^{\text{lo}}, c^{\text{hi}}$ decompose | -| 22-25 | $P_x$ range tightening | Constrain $P_x$ highest microlimbs to 12/8 bits | -| 26-29 | $P_y$ range tightening | Constrain $P_y$ highest microlimbs to 12/8 bits | -| 30-33 | $z$ range tightening | Constrain $z$ highest microlimbs to 12/4 bits | -| 34-37 | Accumulator range tightening | Constrain accumulator highest microlimbs to 12/8 bits | -| 38-41 | Quotient range tightening | Constrain quotient highest microlimbs to 12/10 bits | -| 42-47 | Transcript value composition | Prove 68-bit limbs correctly form transcript values | - -### Interaction with Delta Range Constraint +#### Interaction with Delta Range Constraint The Decomposition Relation works in tandem with the Delta Range Constraint (a separate permutation argument): -**Delta Range Constraint proves:** Every microlimb column (all `*_range_constraint_*` columns) contains only values in $[0, 2^{14})$. +Delta Range Constraint proves: Every microlimb column (all `*_range_constraint_*` columns) contains only values in $[0, 2^{14})$. -**Decomposition Relation proves:** +Decomposition Relation proves: 1. Large limbs are correctly reconstructed from microlimbs 2. Highest microlimbs are more strictly bounded (4, 8, 10, or 12 bits) 3. Transcript values are correctly formed from 68-bit limbs -**Together they guarantee:** All limb decompositions are valid and all values are correctly range-constrained. +Together they guarantee: All limb decompositions are valid and all values are correctly range-constrained. ---- - -## Permutation Relation: Mathematical Specification +## Permutation Relation The Permutation Relation is the foundation of all range constraints in the Translator circuit. It proves that every microlimb value used in the circuit belongs to the set $[0, 2^{14} - 1]$. The grand product argument comparing two multisets: @@ -601,7 +432,7 @@ The Permutation Relation is the foundation of all range constraints in the Trans If the two multisets are equal (i.e., one is a permutation of the other), then all values are valid. -The relation consists of **2 subrelations**: +The relation consists of 2 subrelations: 1. Grand product identity (degree 7) 2. Finalization check (degree 3) @@ -652,9 +483,9 @@ If the two multisets are equal: 2. After processing all rows, the grand product returns to 1 (accounting for initialization/finalization) 3. If any value is out of range or missing from the sorted set, the product cannot telescope correctly -**Active when:** All rows (both even and odd in the full interleaved circuit) +Active when: All rows (both even and odd in the full interleaved circuit) -**Degree:** 7 (1 + 5 wire products + Lagrange selector) +Degree: 7 (1 + 5 wire products + Lagrange selector) --- @@ -676,37 +507,17 @@ $$\boxed{L_{\text{last}} \cdot z_{\text{perm}}^{\text{shift}} = 0}$$ --- -### Security Implications - -**If the Permutation Relation fails:** - -- Attacker can use microlimbs $> 2^{14} - 1$ -- This breaks the range constraint system -- Allows limbs $> 2^{68}$ bits -- Breaks the soundness of Non-Native Field Relation (overflow in Chinese Remainder Theorem) -- Complete circuit soundness failure - -**Critical property:** The sorted multiset must contain: - -- All microlimbs actually used in the circuit -- "Step values" inserted every 3 increments (due to `SORT_STEP = 3`) -- Final value must be exactly $2^{14} - 1 = 16383$ - ---- - -## Delta Range Constraint Relation: Mathematical Specification - -### Purpose and Overview +## Delta Range Constraint Relation The Delta Range Constraint Relation works in tandem with the Permutation Relation to prove that the **ordered (sorted) multiset** is actually sorted and bounded correctly. -**What it proves:** +What it proves: 1. The "ordered" wires are actually in non-descending order 2. Consecutive values differ by at most `SORT_STEP = 3` 3. The final value in each column is exactly $2^{14} - 1 = 16383$ -**Why needed:** The Permutation Relation only proves the multisets are equal. Without the Delta Range Constraint, an attacker could provide an "ordered" set that isn't actually sorted (e.g., [5, 3, 7, 1]), and the permutation would still pass if the interleaved set matches. +The Permutation Relation only proves the multisets are equal. Without the Delta Range Constraint, an attacker could provide an "ordered" set that isn't actually sorted (e.g., [5, 3, 7, 1]), and the permutation would still pass if the interleaved set matches. The relation consists of **10 subrelations**: From b69aa012f3145876d1aa328192402154987a6bda Mon Sep 17 00:00:00 2001 From: suyash67 Date: Tue, 16 Dec 2025 13:53:11 +0000 Subject: [PATCH 17/29] minor edits. --- .../src/barretenberg/translator_vm/README.md | 9 +- .../barretenberg/translator_vm/RELATIONS.md | 412 +++++------------- 2 files changed, 118 insertions(+), 303 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 1ec2fe610bd4..9bf40f6c3b24 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -1,6 +1,6 @@ # The Translator Circuit -> $\textcolor{orange}{\textsf{Warning}}$: This document provides a technical overview of the Translator Circuit used in the Goblin Plonk proving system. It is intended for understanding the design and optimizations. The code is the source of truth for implementation specifics. +> **Warning**: This document provides a technical overview of the Translator Circuit used in the Goblin Plonk proving system. It is intended for understanding the design and optimizations. The code is the source of truth for implementation specifics. ## Table of Contents @@ -176,8 +176,6 @@ This architecture exists because of how polynomial commitments work in the KZG s - Even row $2i$ accesses "previous" values from odd row $2i+1$ via shift columns - Odd row $2i+1$ stores the data that will become "previous" for the next computation at row $2i+2$ -The Translator circuit has **81 witness columns** organized into several categories: - #### 1. EccOpQueue Transcript Columns (4 columns) These columns directly represent the EccOpQueue transcript: @@ -300,7 +298,7 @@ Each limb is further decomposed into **14-bit microlimbs** for range checking. E | `QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL` | $\textcolor{yellow}{q_{2}[\textsf{tail}]}$ | $c^{\text{hi}}[5]$ (reassigned) | | | | | -The tail microlimbs (shown in yellow) enforce tight range constraints by ensuring top limbs use exactly the required number of bits (explained in [Relation 3](#relation-3-decomposition-relation-48-subrelations)). +The tail microlimbs (shown in yellow) enforce tight range constraints by ensuring top limbs use exactly the required number of bits (explained in the Decomposition Relation section of [RELATIONS.md](RELATIONS.md)). **Column reuse optimization:** Some columns are reassigned in odd rows to hold tail microlimbs for limbs that don't need all 5 microlimbs. For example, limb $P_{x, 3}$ is only 50 bits (= 3Γ—14 + 8), requiring only 4 microlimbs. The 5th microlimb column `P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4` at odd rows is therefore reassigned to hold the tail microlimb for $P_{x,3}$ (and carry values $c^{\text{lo}}[4]$, $c^{\text{hi}}[4]$, etc.). @@ -403,8 +401,7 @@ For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. -> $\textcolor{orange}{\textsf{Effect on Commitment Scheme}}$: -> For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: +> **Effect on Commitment Scheme**: For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: > $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ > The interleaved polynomials do not require separate commitments because they can be derived from the original polynomials' commitments. In the Gemini PCS phase, the prover sends only two additional field element evaluations $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: > $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index d49f0a038fac..061e4070d40b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -1,16 +1,18 @@ # Translator Relations -The translator VM enforces several relations/constraints to ensure the correctness of non-native field arithmetic and other operations. The primary relation is the **Non-Native Field Relation**, which verifies that certain accumulations hold in a non-native field (the BN254 base field $\mathbb{F}_q$) while operating in the native field (the BN254 scalar field $\mathbb{F}_p$). +The translator VM enforces several relations/constraints to ensure the correctness of non-native field arithmetic and other operations. The primary relation is the **Non-Native Field Relation**, which verifies that certain accumulations hold in a non-native field (the BN254 base field $\mathbb{F}_q$) while operating in the native field (the BN254 scalar field $\mathbb{F}_r$). Since we follow a two-row trace structure, some relations are only active on even rows, while others are only active on odd rows. Below is a summary of the relations and their activation patterns. -| Constraint | Active on Even Rows | Active on Odd Rows | -| ------------------------------------------ | ------------------- | ------------------ | -| Non-Native Field Relation (3 subrelations) | βœ“ | βœ— | -| Accumulator Transfer Relation | βœ— | βœ“ | -| Opcode Constraint | βœ“ | βœ“ | -| Range Constraints (Permutation) | βœ“ | βœ“ | -| Decomposition Relations | βœ“ | βœ“ | +| Constraint | Active on Even Rows | Active on Odd Rows | +| ----------------------------------------------- | ------------------- | ------------------ | +| Non-Native Field Relation (3 subrelations) | βœ“ | βœ— | +| Decomposition Relation (48 subrelations) | βœ“ | βœ“ | +| Permutation Relation (2 subrelations) | βœ“ | βœ“ | +| Delta Range Constraint (10 subrelations) | βœ“ | βœ“ | +| Opcode Constraint Relation (5 subrelations) | βœ“ | βœ“ | +| Accumulator Transfer Relation (12 subrelations) | βœ— | βœ“ (propagation) | +| Zero Constraints Relation (68 subrelations) | βœ“ | βœ“ | Lagrange selectors: @@ -20,10 +22,13 @@ Lagrange selectors: ## Table of Contents 1. [Limb Decomposition Structure](#limb-decomposition-structure) -2. [Non Native Field Relations](#non-native-field-relations) +2. [Non-Native Field Relations](#non-native-field-relations) 3. [Decomposition Relation](#decomposition-relation) -4. [Accumulator Transfer Relation](#accumulator-transfer-relation) -5. [Opcode Constraint](#opcode-constraint) +4. [Permutation Relation](#permutation-relation) +5. [Delta Range Constraint Relation](#delta-range-constraint-relation) +6. [Opcode Constraint Relation](#opcode-constraint-relation) +7. [Accumulator Transfer Relation](#accumulator-transfer-relation) +8. [Zero Constraints Relation](#zero-constraints-relation) --- @@ -31,7 +36,7 @@ Lagrange selectors: This table establishes **all notation** used in the relations: -| Value | Native (𝔽q) | Binary Limbs | Native (𝔽p) | +| Value | Native (𝔽q) | Binary Limbs | Native (𝔽r) | | ------------------------------- | -------------------- | ------------------------------------------------------------------------------------ | --------------- | | **Evaluation challenge** | | $x$ | Evaluation point | $x_0, x_1, x_2, x_3$ | $x_4$ | @@ -93,18 +98,18 @@ We want to prove the following accumulation identity holds in $\mathbb{F}_q$: $$\boxed{a^{\text{curr}} = a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}}$$ -We can only perform arithmetic in $\mathbb{F}_p$, but we need to prove correctness in $\mathbb{F}_q$ (the base field). +We can only perform arithmetic in $\mathbb{F}_r$, but we need to prove correctness in $\mathbb{F}_q$ (the base field). To do this, we rewrite the above equation as an integer equation with quotient $\mathcal{Q}$: $$a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \mathcal{Q} \cdot q - a^{\text{curr}} = 0 \quad (\text{in integers})$$ If this equation holds: -1. Modulo $2^{272}$ (via limb arithmetic in $\mathbb{F}_p$), and -2. Modulo $p$ (native $\mathbb{F}_p$ computation), and +1. Modulo $2^{272}$ (via limb arithmetic in $\mathbb{F}_r$), and +2. Modulo $r$ (native $\mathbb{F}_r$ computation), and 3. All values are properly range-constrained -Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot p > 2^{514}$ > max possible value), which implies it holds modulo $q$. See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. +Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot r > 2^{514}$ > max possible value), which implies it holds modulo $q$. See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. The non-native field relation is enforced through **three separate subrelations**: @@ -112,7 +117,7 @@ The non-native field relation is enforced through **three separate subrelations* | ----------- | --------------------- | --------- | ------------------------------------- | | 1 | Lower mod 2²⁷² check | $2^{136}$ | Limbs 0, 1 | | 2 | Higher mod 2²⁷² check | $2^{136}$ | Limbs 2, 3 (with carry from subrel 1) | -| 3 | Native field check | $p$ | Full native reconstruction | +| 3 | Native field check | $r$ | Full native reconstruction | Together, these prove the relation holds in integers. @@ -120,7 +125,7 @@ Together, these prove the relation holds in integers. > $$\bar{q} := 2^{272} - q$$ > Decomposed into limbs: > $$\bar{q} = \bar{q}_0 + 2^{68} \cdot \bar{q}_1 + 2^{136} \cdot \bar{q}_2 + 2^{204} \cdot \bar{q}_3$$ -> Plus native field representation: $\bar{q}_4 = -q \pmod{p}$ +> Plus native field representation: $\bar{q}_4 = -q \pmod{r}$ --- @@ -239,23 +244,23 @@ Together with Subrelation 1: We've proven the relation holds modulo $2^{272}$. ### Subrelation 3: Native Field Check -Prove the accumulation formula holds when computed directly in 𝔽p (the native field). +Prove the accumulation formula holds when computed directly in 𝔽r (the native field). First, reconstruct all values from their limbs: $$ \begin{align*} -\tilde{P}_x &= P_{x,0}^{\text{lo}} + 2^{68} \cdot P_{x,1}^{\text{lo}} + 2^{136} \cdot P_{x,0}^{\text{hi}} + 2^{204} \cdot P_{x,1}^{\text{hi}} \pmod{p} \\ -\tilde{P}_y &= P_{y,0}^{\text{lo}} + 2^{68} \cdot P_{y,1}^{\text{lo}} + 2^{136} \cdot P_{y,0}^{\text{hi}} + 2^{204} \cdot P_{y,1}^{\text{hi}} \pmod{p} \\ -\tilde{z}_1 &= z_{1,0} + 2^{68} \cdot z_{1,1} \pmod{p} \\ -\tilde{z}_2 &= z_{2,0} + 2^{68} \cdot z_{2,1} \pmod{p} \\ -\tilde{a}^{\text{prev}} &= a_0^{\text{prev}} + 2^{68} \cdot a_1^{\text{prev}} + 2^{136} \cdot a_2^{\text{prev}} + 2^{204} \cdot a_3^{\text{prev}} \pmod{p} \\ -\tilde{a}^{\text{curr}} &= a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}} \pmod{p} \\ -\tilde{\mathcal{Q}} &= q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3 \pmod{p} +\tilde{P}_x &= P_{x,0}^{\text{lo}} + 2^{68} \cdot P_{x,1}^{\text{lo}} + 2^{136} \cdot P_{x,0}^{\text{hi}} + 2^{204} \cdot P_{x,1}^{\text{hi}} \pmod{r} \\ +\tilde{P}_y &= P_{y,0}^{\text{lo}} + 2^{68} \cdot P_{y,1}^{\text{lo}} + 2^{136} \cdot P_{y,0}^{\text{hi}} + 2^{204} \cdot P_{y,1}^{\text{hi}} \pmod{r} \\ +\tilde{z}_1 &= z_{1,0} + 2^{68} \cdot z_{1,1} \pmod{r} \\ +\tilde{z}_2 &= z_{2,0} + 2^{68} \cdot z_{2,1} \pmod{r} \\ +\tilde{a}^{\text{prev}} &= a_0^{\text{prev}} + 2^{68} \cdot a_1^{\text{prev}} + 2^{136} \cdot a_2^{\text{prev}} + 2^{204} \cdot a_3^{\text{prev}} \pmod{r} \\ +\tilde{a}^{\text{curr}} &= a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}} \pmod{r} \\ +\tilde{\mathcal{Q}} &= q_0 + 2^{68} \cdot q_1 + 2^{136} \cdot q_2 + 2^{204} \cdot q_3 \pmod{r} \end{align*} $$ -**Note:** The tilde indicates these are native field reconstructions in 𝔽p, not the original 𝔽q values. +**Note:** The tilde indicates these are native field reconstructions in 𝔽r, not the original 𝔽q values. The subrelation 3 is then: @@ -274,31 +279,31 @@ $$ Where: -- All arithmetic is performed in $\mathbb{F}_{p}$ +- All arithmetic is performed in $\mathbb{F}_{r}$ - $x_4, v_4, (v^2)_4, (v^3)_4, (v^4)_4$ are the native field representations of the challenges -- $\bar{q}_4 = -q \pmod{p}$ +- $\bar{q}_4 = -q \pmod{r}$ Interpretation: -- Reconstruct all limbed values back to native $\mathbb{F}_{p}$ elements -- Compute the accumulation formula directly in $\mathbb{F}_{p}$ -- If subrelations 1 and 2 prove it holds mod $2^{272}$, and subrelation 3 proves it holds mod $p$, then it holds in integers +- Reconstruct all limbed values back to native $\mathbb{F}_{r}$ elements +- Compute the accumulation formula directly in $\mathbb{F}_{r}$ +- If subrelations 1 and 2 prove it holds mod $2^{272}$, and subrelation 3 proves it holds mod $r$, then it holds in integers --- ## Decomposition Relation -The decomposition relation enforces the integrity of the limb decomposition system. While the Non-Native Field Relation proves the accumulation formula is correct, the Decomposition Relation proves all limb decompositions are valid. +The Decomposition Relation enforces the integrity of the limb decomposition system. While the Non-Native Field Relation proves the accumulation formula is correct, the Decomposition Relation proves all limb decompositions are valid. -The relation consists of 48 subrelations organized into five categories: +The relation consists of **48 subrelations** organized into five categories: -1. Accumulator microlimb decomposition (4 subrelations): Active when $L_{\text{even}} \cdot \texttt{op} = 1$ -2. Point & Scalar microlimb decomposition (18 subrelations): Active when $L_{\text{even}} = 1$ -3. Wide limb decomposition (2 subrelations): Decompose 84-bit carry limbs -4. Range constraint tightening (20 subrelations): Enforce stricter bounds on highest microlimbs -5. Transcript composition (6 subrelations): Prove 68-bit limbs reconstruct transcript values +1. **Accumulator microlimb decomposition** (4 subrelations) β€” Active when $L_{\text{even}} \cdot \texttt{op} = 1$ +2. **Point & Scalar microlimb decomposition** (18 subrelations) β€” Active when $L_{\text{even}} = 1$ +3. **Wide limb decomposition** (2 subrelations) β€” Decompose 84-bit carry limbs +4. **Range constraint tightening** (20 subrelations) β€” Enforce stricter bounds on highest microlimbs +5. **Transcript composition** (6 subrelations) β€” Prove 68-bit limbs reconstruct transcript values -These work with the **Delta Range Constraint** permutation argument that proves each microlimb is in $[0, 2^{14})$. +These work with the **Permutation Relation** and **Delta Range Constraint** which together prove each microlimb is in $[0, 2^{14})$. --- @@ -425,7 +430,9 @@ Together they guarantee: All limb decompositions are valid and all values are co ## Permutation Relation -The Permutation Relation is the foundation of all range constraints in the Translator circuit. It proves that every microlimb value used in the circuit belongs to the set $[0, 2^{14} - 1]$. The grand product argument comparing two multisets: +### Overview + +The Permutation Relation is the foundation of all range constraints in the Translator circuit. It proves that every microlimb value used in the circuit belongs to the set $[0, 2^{14} - 1]$. The relation uses a grand product argument comparing two multisets: - **Interleaved multiset:** All microlimbs as they appear in the circuit (spread across 16 segments due to interleaving) - **Ordered multiset:** The same values, but sorted in ascending order @@ -467,6 +474,7 @@ where: - $L_{\text{mask}}[i]$: Lagrange polynomial indicating masking rows (for zero-knowledge) The term $(\beta \cdot L_{\text{mask}}[i])$ on both sides enforces that the zero-knowledge masking values in both sets are identical. +It is added only to the masking region, to avoid interfering with the actual circuit values (which must be in the range $[0, 2^{14} - 1]$). The subrelation is then expressed, with boundary conditions, as: $$\boxed{\left( z_{\text{perm}} + L_{\text{first}} \right) \cdot \prod_{j=0}^{4} \left( w_j^{\text{interleaved}} + \beta \cdot L_{\text{mask}} + \gamma \right) = \left( z_{\text{perm}}^{\text{shift}} + L_{\text{last}} \right) \cdot \prod_{j=0}^{4} \left( w_j^{\text{ordered}} + \beta \cdot L_{\text{mask}} + \gamma \right)}$$ @@ -485,31 +493,31 @@ If the two multisets are equal: Active when: All rows (both even and odd in the full interleaved circuit) -Degree: 7 (1 + 5 wire products + Lagrange selector) +Degree: 6 (each side is degree 1 polynomial Γ— product of 5 degree-1 terms) --- ### Subrelation 2: Finalization Check -**Purpose:** Ensure the grand product polynomial returns to the correct value at the circuit boundary. +Purpose: Ensure the grand product polynomial returns to the correct value at the circuit boundary. $$\boxed{L_{\text{last}} \cdot z_{\text{perm}}^{\text{shift}} = 0}$$ -**Interpretation:** +Interpretation: - At the last row, $L_{\text{last}} = 1$ - The shifted grand product $z_{\text{perm}}^{\text{shift}}$ (which is $z_{\text{perm}}$ at the row after last) must be 0 - This ensures the telescoping completed correctly -**Active when:** Last row only ($L_{\text{last}} = 1$) +Active when: Last row only ($L_{\text{last}} = 1$) -**Degree:** 3 (Lagrange Γ— shifted polynomial) +Degree: 2 (Lagrange Γ— shifted polynomial) --- ## Delta Range Constraint Relation -The Delta Range Constraint Relation works in tandem with the Permutation Relation to prove that the **ordered (sorted) multiset** is actually sorted and bounded correctly. +The Delta Range Constraint Relation works in tandem with the Permutation Relation to prove that the ordered (sorted) multiset is actually sorted and bounded correctly. What it proves: @@ -517,9 +525,9 @@ What it proves: 2. Consecutive values differ by at most `SORT_STEP = 3` 3. The final value in each column is exactly $2^{14} - 1 = 16383$ -The Permutation Relation only proves the multisets are equal. Without the Delta Range Constraint, an attacker could provide an "ordered" set that isn't actually sorted (e.g., [5, 3, 7, 1]), and the permutation would still pass if the interleaved set matches. +The Permutation Relation only proves the multisets are equal. Without the Delta Range Constraint, an attacker could provide out of range values and the permutation would still pass if the interleaved set matches. -The relation consists of **10 subrelations**: +The relation consists of 10 subrelations: - 5 consecutive difference checks (one per ordered wire) - 5 maximum value checks (one per ordered wire) @@ -528,7 +536,7 @@ The relation consists of **10 subrelations**: ### Subrelations 1-5: Consecutive Difference Constraints -**Purpose:** Enforce that each ordered wire is in non-descending order with maximum step 3. +Purpose: Enforce that each ordered wire is in non-descending order with maximum step 3. For each ordered wire $j \in \{0, 1, 2, 3, 4\}$: @@ -537,7 +545,7 @@ $$\boxed{\left( L_{\text{real\_last}} - 1 \right) \cdot \left( L_{\text{mask}} - where: $$\Delta_j := w_j^{\text{ordered}}[i+1] - w_j^{\text{ordered}}[i]$$ -**Interpretation:** +Interpretation: The constraint is active when: @@ -546,7 +554,7 @@ The constraint is active when: When active, it forces: $\Delta_j \in \{0, 1, 2, 3\}$ -**Why maximum step 3?** +Why maximum step 3? To ensure full coverage of $[0, 2^{14} - 1]$, we insert "step values" into the sorted array: @@ -560,26 +568,24 @@ Between these steps, actual microlimbs fill in the gaps. With $\Delta \in \{0, 1 - Every value $\leq 16383$ has a step value within distance 3 - Therefore, all values in range can be represented -**Excluded rows:** +Active when: All rows except last and masking rows - $L_{\text{real\_last}} = 1$: The last real row (boundary condition handled by subrelations 6-10) - $L_{\text{mask}} = 1$: Zero-knowledge masking rows -**Active when:** All rows except last and masking rows - -**Degree:** 7 (2 Lagrange terms + 4 polynomial factors for $\Delta$) +Degree: 6 (product of 6 degree-1 polynomials: $(L_{\text{real\_last}} - 1) \cdot (L_{\text{mask}} - 1) \cdot \Delta \cdot (\Delta-1) \cdot (\Delta-2) \cdot (\Delta-3)$) --- ### Subrelations 6-10: Maximum Value Constraints -**Purpose:** Ensure the final value in each sorted column is exactly $2^{14} - 1 = 16383$. +Purpose: Ensure the final value in each sorted column is exactly $2^{14} - 1 = 16383$. For each ordered wire $j \in \{0, 1, 2, 3, 4\}$: $$\boxed{L_{\text{real\_last}} \cdot \left( w_j^{\text{ordered}} - (2^{14} - 1) \right) = 0}$$ -**Interpretation:** +Interpretation: At the last real row ($L_{\text{real\_last}} = 1$): $$w_j^{\text{ordered}}[\text{last}] = 2^{14} - 1 = 16383$$ @@ -590,60 +596,27 @@ This ensures: 2. The maximum value $2^{14} - 1$ is present in the sorted multiset 3. Combined with the difference constraint, all values are $\leq 2^{14} - 1$ -**Active when:** Last real row only ($L_{\text{real\_last}} = 1$) - -**Degree:** 3 (Lagrange Γ— difference) +Active when: Last real row only ($L_{\text{real\_last}} = 1$) ---- - -### Complete Delta Range Constraint Summary - -| Subrelation | Wire | Constraint Type | Enforces | -| ----------- | ---- | ---------------------- | --------------------------------------------------------------------- | -| 1 | 0 | Consecutive difference | $w_0^{\text{ordered}}[i+1] - w_0^{\text{ordered}}[i] \in \{0,1,2,3\}$ | -| 2 | 1 | Consecutive difference | $w_1^{\text{ordered}}[i+1] - w_1^{\text{ordered}}[i] \in \{0,1,2,3\}$ | -| 3 | 2 | Consecutive difference | $w_2^{\text{ordered}}[i+1] - w_2^{\text{ordered}}[i] \in \{0,1,2,3\}$ | -| 4 | 3 | Consecutive difference | $w_3^{\text{ordered}}[i+1] - w_3^{\text{ordered}}[i] \in \{0,1,2,3\}$ | -| 5 | 4 | Consecutive difference | $w_4^{\text{ordered}}[i+1] - w_4^{\text{ordered}}[i] \in \{0,1,2,3\}$ | -| 6 | 0 | Maximum value | $w_0^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | -| 7 | 1 | Maximum value | $w_1^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | -| 8 | 2 | Maximum value | $w_2^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | -| 9 | 3 | Maximum value | $w_3^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | -| 10 | 4 | Maximum value | $w_4^{\text{ordered}}[\text{last}] = 2^{14} - 1$ | +Degree: 2 (Lagrange Γ— difference) --- -### Interaction with Permutation Relation - -**Together, the two relations prove:** +## Opcode Constraint Relation -| What | Proven By | -| ------------------------------------------------ | ------------------------------------ | -| Ordered set is actually sorted | Delta Range Constraint (subrel 1-5) | -| Maximum value is $2^{14} - 1$ | Delta Range Constraint (subrel 6-10) | -| Interleaved set equals ordered set | Permutation Relation (subrel 1) | -| Grand product telescopes correctly | Permutation Relation (subrel 2) | -| **RESULT:** All microlimbs $\in [0, 2^{14} - 1]$ | Both relations combined | - -**Security:** If either relation fails, range constraints break and circuit soundness is compromised. - ---- - -## Opcode Constraint Relation: Mathematical Specification - -### Purpose and Overview +### Overview The Opcode Constraint Relation enforces that all operation codes (`op`) belong to the valid set: $$\boxed{\texttt{op} \in \{0, 1, 2, 3, 4, 8\}}$$ -**Why needed:** The `op` value is used in selector logic and potentially affects witness generation. Invalid opcodes could: +Why needed: The `op` value is used in selector logic and potentially affects witness generation. Invalid opcodes could: - Inject arbitrary values into the accumulation formula - Bypass range constraints (if `op = 0` has special handling) - Break the integrity of the EccOpQueue transcript -**Valid opcodes:** +Valid opcodes: - `0`: NULL / No-op - `1`: Point addition @@ -658,19 +631,10 @@ The relation consists of **5 subrelations** (one per non-zero opcode check), imp ### Polynomial Root Constraint -**Method:** Use a polynomial with roots exactly at the valid opcodes. - -The polynomial: -$$P(\texttt{op}) = \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8)$$ - -has roots at $\{0, 1, 2, 3, 4, 8\}$ and **only** at these values. - -**The constraint:** +The constraint is expressed as a polynomial that has roots at the valid opcode values: $$\boxed{\left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8) = 0}$$ -**Interpretation:** - The constraint is active when: - $L_{\text{even}} = 1$ (even rows in mini-circuit), OR @@ -681,13 +645,11 @@ When active: - If $\texttt{op} \in \{0, 1, 2, 3, 4, 8\}$, then $P(\texttt{op}) = 0$ βœ“ - If $\texttt{op} \notin \{0, 1, 2, 3, 4, 8\}$, then $P(\texttt{op}) \neq 0$ βœ— (constraint fails) -**Active when:** Even rows and mini-circuit masking rows +Active when: Even rows and mini-circuit masking rows -**Degree:** 6 (Lagrange + 5-degree polynomial in `op`) +Degree: 7 (degree-1 Lagrange Γ— degree-6 polynomial in `op`) ---- - -### Implementation as 5 Subrelations +#### Implementation as 5 Subrelations For efficiency in the sumcheck protocol, the constraint is split into 5 subrelations: @@ -701,47 +663,31 @@ $$ \end{align*}} $$ -**Why split?** +Why split? -- Each subrelation has lower degree (3-4 instead of 6) +- Each subrelation has lower degree (3-4 instead of 7) - More efficient in sumcheck univariate polynomial computation -- Easier to optimize in implementation -**Together:** These 5 subrelations are equivalent to the full polynomial constraint. +Together, these 5 subrelations are equivalent to the full polynomial constraint. --- -### Security Implications - -**If the Opcode Constraint fails:** - -- Attacker could inject opcode 255 (or any invalid value) -- Potentially bypass range constraint checks (if `op = 0` disables constraints) -- Break accumulation formula integrity -- Compromise EccOpQueue transcript consistency - -**Critical property:** Only valid ECC operations can be proven, ensuring the ECCVM ↔ Translator consistency. - ---- +## Accumulator Transfer Relation -## Accumulator Transfer Relation: Mathematical Specification +The Accumulator Transfer Relation manages the lifecycle of the accumulator across the circuit: -### Purpose and Overview +1. Initialization: Start with zero accumulator +2. Propagation: Copy accumulator from even rows to odd rows (data storage) +3. Computation: Update accumulator on even rows (handled by Non-Native Field Relation) +4. Finalization: Verify final accumulator matches expected result -The Accumulator Transfer Relation manages the **lifecycle of the accumulator** across the circuit: - -1. **Initialization:** Start with zero accumulator -2. **Propagation:** Copy accumulator from even rows to odd rows (data storage) -3. **Computation:** Update accumulator on even rows (handled by Non-Native Field Relation) -4. **Finalization:** Verify final accumulator matches expected result - -**Why needed:** The accumulator must maintain state consistency across rows. Without these constraints: +The accumulator must maintain state consistency across rows. Without these constraints: - Initial value could be non-zero (offsetting all computations) - Accumulator could "reset" mid-computation - Final value might not match ECCVM's expected result -The relation consists of **12 subrelations**: +The relation consists of 12 subrelations: - 4 for odd row propagation (copy previous value) - 4 for initialization (set to zero) @@ -755,52 +701,40 @@ The accumulator is a 254-bit value decomposed into 4 limbs: $$a^{\text{curr}} = a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}}$$ -**Row-by-row behavior:** - -- **Even row $2i$:** Accumulator updated via Non-Native Field Relation (computation) -- **Odd row $2i+1$:** Accumulator copied from even row $2i$ (storage for next cycle) - -The "shift" mechanism: - -- `a_i^{curr}`: Current row's accumulator limb $i$ -- `a_i^{shift}`: Next row's accumulator limb $i$ (accessed via shifted polynomial) +Row-by-row behavior: ---- +- Even row $2i$: Accumulator updated via Non-Native Field Relation (computation) +- Odd row $2i+1$: Accumulator copied from even row $2i$ (storage for next cycle) ### Subrelations 1-4: Odd Row Propagation -**Purpose:** Ensure accumulator does not change on odd rows (data storage rows). +Purpose: Ensure accumulator does not change on odd rows (data storage rows). For each limb $i \in \{0, 1, 2, 3\}$: $$\boxed{L_{\text{odd}} \cdot \left( a_i^{\text{curr}} - a_i^{\text{shift}} \right) = 0}$$ -**Interpretation:** - -On odd rows ($L_{\text{odd}} = 1$): -$$a_i^{\text{curr}}[\text{odd}] = a_i^{\text{shift}}[\text{odd}] = a_i^{\text{curr}}[\text{next\_even}]$$ - This creates the "storage" pattern: - Even row $2i$: Computes new accumulator value - Odd row $2i+1$: Stores this value unchanged - Even row $2i+2$: Accesses odd row $2i+1$ via shift to get "previous" value -**Active when:** Odd rows only ($L_{\text{odd}} = 1$) +Active when: Odd rows only ($L_{\text{odd}} = 1$) -**Degree:** 3 (Lagrange Γ— difference) +Degree: 2 (Lagrange Γ— difference) --- ### Subrelations 5-8: Initialization -**Purpose:** Initialize accumulator to zero at the start of the circuit. +Purpose: Initialize accumulator to zero at the start of the circuit. For each limb $i \in \{0, 1, 2, 3\}$: $$\boxed{L_{\text{first}} \cdot a_i^{\text{curr}} = 0}$$ -**Interpretation:** +Interpretation: At the first row ($L_{\text{first}} = 1$): $$a_i^{\text{curr}}[0] = 0 \quad \forall i \in \{0, 1, 2, 3\}$$ @@ -808,124 +742,66 @@ $$a_i^{\text{curr}}[0] = 0 \quad \forall i \in \{0, 1, 2, 3\}$$ This ensures: $$a^{\text{curr}}[0] = 0 + 0 \cdot 2^{68} + 0 \cdot 2^{136} + 0 \cdot 2^{204} = 0$$ -**Why critical:** If the accumulator starts at a non-zero value, all subsequent accumulations are offset by this initial value, breaking the consistency proof. +If the accumulator starts at a non-zero value, all subsequent accumulations are offset by this initial value, breaking the consistency proof. -**Active when:** First row only ($L_{\text{first}} = 1$) +Active when: First row only ($L_{\text{first}} = 1$) -**Degree:** 3 (Lagrange Γ— limb value) +Degree: 2 (Lagrange Γ— limb value) --- ### Subrelations 9-12: Finalization -**Purpose:** Verify the final accumulator value matches the expected result from ECCVM. +Purpose: Verify the final accumulator value matches the expected result from ECCVM. For each limb $i \in \{0, 1, 2, 3\}$: $$\boxed{L_{\text{result}} \cdot \left( a_i^{\text{curr}} - a_i^{\text{expected}} \right) = 0}$$ -where $a_i^{\text{expected}}$ is provided as a relation parameter (derived from ECCVM output). - -**Interpretation:** - -At the result row ($L_{\text{result}} = 1$): -$$a_i^{\text{curr}}[\text{result}] = a_i^{\text{expected}} \quad \forall i \in \{0, 1, 2, 3\}$$ - -This ensures: -$$a^{\text{curr}}[\text{result}] = a^{\text{expected}}$$ +where $a_i^{\text{expected}}$ is provided as a relation parameter (derived from ECCVM output). The ECCVM circuit computes the batched evaluation: -**Expected result derivation:** - -The ECCVM circuit computes the batched evaluation: $$a^{\text{expected}} = \sum_{j=0}^{n-1} x^{n-1-j} \cdot \left( \texttt{op}_j + v \cdot P_{x,j} + v^2 \cdot P_{y,j} + v^3 \cdot z_{1,j} + v^4 \cdot z_{2,j} \right) \pmod{q}$$ -The Translator must prove it computed the same value. The finalization check ensures: - -- Translator's computation matches ECCVM's computation -- Consistency between the two circuits - -**Active when:** Result row only ($L_{\text{result}} = 1$) - -**Degree:** 3 (Lagrange Γ— difference) - ---- - -### Complete Accumulator Transfer Summary - -| Subrelation | Limb | Constraint Type | Enforces | -| ----------- | ---- | ------------------- | ---------------------------------------------------------------- | -| 1 | 0 | Odd row propagation | $a_0^{\text{curr}}[\text{odd}] = a_0^{\text{curr}}[\text{next}]$ | -| 2 | 1 | Odd row propagation | $a_1^{\text{curr}}[\text{odd}] = a_1^{\text{curr}}[\text{next}]$ | -| 3 | 2 | Odd row propagation | $a_2^{\text{curr}}[\text{odd}] = a_2^{\text{curr}}[\text{next}]$ | -| 4 | 3 | Odd row propagation | $a_3^{\text{curr}}[\text{odd}] = a_3^{\text{curr}}[\text{next}]$ | -| 5 | 0 | Initialization | $a_0^{\text{curr}}[0] = 0$ | -| 6 | 1 | Initialization | $a_1^{\text{curr}}[0] = 0$ | -| 7 | 2 | Initialization | $a_2^{\text{curr}}[0] = 0$ | -| 8 | 3 | Initialization | $a_3^{\text{curr}}[0] = 0$ | -| 9 | 0 | Finalization | $a_0^{\text{curr}}[\text{result}] = a_0^{\text{expected}}$ | -| 10 | 1 | Finalization | $a_1^{\text{curr}}[\text{result}] = a_1^{\text{expected}}$ | -| 11 | 2 | Finalization | $a_2^{\text{curr}}[\text{result}] = a_2^{\text{expected}}$ | -| 12 | 3 | Finalization | $a_3^{\text{curr}}[\text{result}] = a_3^{\text{expected}}$ | - ---- - -### Interaction with Non-Native Field Relation - -**Division of responsibility:** +The Translator must prove it computed the same value. The finalization check ensures that Translator's computation matches ECCVM's computation -| Relation | Handles | -| ----------------------------- | ----------------------------------------- | -| Non-Native Field Relation | Arithmetic updates on even rows | -| Accumulator Transfer Relation | Initialization, propagation, finalization | +Active when: Result row only ($L_{\text{result}} = 1$) -**Together:** Prove the accumulator correctly accumulates the batched evaluation from start to finish. +Degree: 2 (Lagrange Γ— difference) --- -## Zero Constraints Relation: Mathematical Specification +## Zero Constraints Relation -### Purpose and Overview +The Zero Constraints Relation enforces that all witness wires are zero outside the mini-circuit. -The Zero Constraints Relation enforces that all witness wires are **zero outside the mini-circuit**. - -**Why needed:** Due to interleaving, the full circuit is 16Γ— larger than the mini-circuit: +Due to interleaving, the full circuit is 16Γ— larger than the mini-circuit: - Mini-circuit: $2^{13} = 8,192$ rows (actual computation) - Full circuit: $2^{17} = 131,072$ rows (for interleaving optimization) -Rows outside the mini-circuit (rows 8,192 to 131,071) must be zero. Otherwise: - -- Garbage values pollute the permutation argument -- Range constraints become meaningless -- Circuit soundness breaks - -The relation consists of **68 subrelations**: +Rows outside the mini-circuit (rows 8,192 to 131,071) must be zero. The relation consists of **68 subrelations**: - 64 for range constraint microlimb wires - 4 for EccOpQueue transcript wires ---- - ### Which Wires Must Be Zero -**Range constraint microlimb wires (64 total):** +Range constraint microlimb wires (64 total): - All `*_RANGE_CONSTRAINT_*` columns (see [Witness Trace Structure](#witness-trace-structure)) - These hold 14-bit microlimbs for decomposition - Must be zero outside mini-circuit to avoid polluting the permutation -**Transcript wires (4 total):** +Transcript wires (4 total): - `OP`: Opcode - `X_LO_Y_HI`: Encodes $P_{x,\text{lo}}$ / $P_{y,\text{hi}}$ - `X_HI_Z_1`: Encodes $P_{x,\text{hi}}$ / $z_1$ - `Y_LO_Z_2`: Encodes $P_{y,\text{lo}}$ / $z_2$ ---- - ### Subrelations 1-68: Zero Outside Mini-Circuit -**General pattern** for each wire $w$: +General pattern for each wire $w$: $$\boxed{\neg \left( L_{\text{in\_mini}} \lor L_{\text{mask}} \right) \implies w = 0}$$ @@ -939,78 +815,20 @@ where: - $L_{\text{odd}}$: Lagrange for odd rows in mini-circuit - $L_{\text{mini\_mask}}$: Lagrange for masking rows in mini-circuit -**Interpretation:** - -If the row is **not** in the mini-circuit (i.e., row $\geq 8,192$) and **not** a masking row: -$$w[\text{row}] = 0$$ - -This ensures: - -- Only rows 0 to 8,191 contain non-zero witness values -- Rows 8,192 to 131,071 are all zero -- Permutation argument only sees valid microlimbs - -**Active when:** All rows outside the mini-circuit - -**Degree:** 4 (Lagrange polynomial products Γ— wire value) +Active when: All rows outside the mini-circuit ---- +Degree: 2 (Lagrange polynomial products Γ— wire value) ### Special Case: No-Op Rows -When `op = 0` (no-op) on even rows, additional constraints force range wires to zero **even within the mini-circuit**. - -**Why:** No-op rows don't contribute to the accumulation, so their witness values should be zero to: - -- Reduce prover work -- Improve zero-knowledge properties -- Prevent unnecessary permutation argument entries +When `op = 0` (no-op) on even rows, additional constraints force range wires to zero even within the mini-circuit. -**Additional constraint pattern:** +No-op rows don't contribute to the accumulation, so their witness values should be zero. $$\boxed{L_{\text{even}} \cdot (1 - \texttt{op}) \cdot w = 0}$$ -**Interpretation:** - -On even rows ($L_{\text{even}} = 1$) where `op = 0`: -$$w = 0$$ - -This applies to all range constraint wires when the row is a no-op. - -**Active when:** Even rows with `op = 0` - -**Degree:** 4 (Lagrange Γ— (1 - op) Γ— wire) +Active when: Even rows with `op = 0` ---- - -### Complete Zero Constraints Summary - -| Subrelation | Wire Category | Count | Enforces | -| ----------- | --------------------------- | ----- | ------------------------- | -| 1-10 | $P_x$ microlimb wires | 10 | Zero outside mini-circuit | -| 11-20 | $P_y$ microlimb wires | 10 | Zero outside mini-circuit | -| 21-32 | $z$ microlimb wires | 12 | Zero outside mini-circuit | -| 33-42 | Accumulator microlimb wires | 10 | Zero outside mini-circuit | -| 43-52 | Quotient microlimb wires | 10 | Zero outside mini-circuit | -| 53-64 | Carry microlimb wires | 12 | Zero outside mini-circuit | -| 65 | `OP` transcript wire | 1 | Zero outside mini-circuit | -| 66 | `X_LO_Y_HI` transcript wire | 1 | Zero outside mini-circuit | -| 67 | `X_HI_Z_1` transcript wire | 1 | Zero outside mini-circuit | -| 68 | `Y_LO_Z_2` transcript wire | 1 | Zero outside mini-circuit | - -**Additional no-op constraints:** All range wires also zero when `op = 0` on even rows. - ---- +Degree: 3 -### Security Implications - -**If the Zero Constraints fail:** - -- Garbage values in rows 8,192+ enter the permutation argument -- Permutation could pass even with invalid microlimbs -- Range constraints become unreliable -- Soundness of entire circuit compromised - -**Critical property:** Interleaving optimization relies on unused rows being zero. Without this, the degree reduction benefit is lost, and soundness breaks. - ---- +Additional no-op constraints: All range wires also zero when `op = 0` on even rows. From 807aa43a20a28761529c2c78a2d966be599a7c47 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Wed, 17 Dec 2025 10:44:44 +0000 Subject: [PATCH 18/29] update. --- .../barretenberg/translator_vm/RELATIONS.md | 196 ++++++------------ 1 file changed, 67 insertions(+), 129 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index 061e4070d40b..7ff75dc1e57f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -4,17 +4,17 @@ The translator VM enforces several relations/constraints to ensure the correctne Since we follow a two-row trace structure, some relations are only active on even rows, while others are only active on odd rows. Below is a summary of the relations and their activation patterns. -| Constraint | Active on Even Rows | Active on Odd Rows | -| ----------------------------------------------- | ------------------- | ------------------ | -| Non-Native Field Relation (3 subrelations) | βœ“ | βœ— | -| Decomposition Relation (48 subrelations) | βœ“ | βœ“ | -| Permutation Relation (2 subrelations) | βœ“ | βœ“ | -| Delta Range Constraint (10 subrelations) | βœ“ | βœ“ | -| Opcode Constraint Relation (5 subrelations) | βœ“ | βœ“ | -| Accumulator Transfer Relation (12 subrelations) | βœ— | βœ“ (propagation) | -| Zero Constraints Relation (68 subrelations) | βœ“ | βœ“ | - -Lagrange selectors: +| Constraint | No of subtrelations | Active on even rows | Active on odd rows | +| ----------------------------- | ------------------- | ------------------- | ------------------ | +| Non-Native Field Relation | 3 | βœ“ | βœ— | +| Decomposition Relation | 48 | βœ“ | βœ“ | +| Permutation Relation | 2 | βœ“ | βœ“ | +| Delta Range Constraint | 10 | βœ“ | βœ“ | +| Opcode Constraint Relation | 5 | βœ“ | βœ“ | +| Accumulator Transfer Relation | 12 | βœ— | βœ“ (propagation) | +| Zero Constraints Relation | 68 | βœ“ | βœ“ | + +Lagrange selectors for activation: - $L_{\text{even}}$: Equals 1 on even rows, 0 elsewhere - $L_{\text{odd}}$: Equals 1 on odd rows, 0 elsewhere @@ -34,7 +34,7 @@ Lagrange selectors: ## Limb Decomposition Structure -This table establishes **all notation** used in the relations: +This table establishes all notation used in the relations: | Value | Native (𝔽q) | Binary Limbs | Native (𝔽r) | | ------------------------------- | -------------------- | ------------------------------------------------------------------------------------ | --------------- | @@ -56,6 +56,8 @@ This table establishes **all notation** used in the relations: | $a^{\text{curr}}$ | Current accumulator | $a_0^{\text{curr}}, a_1^{\text{curr}}, a_2^{\text{curr}}, a_3^{\text{curr}}$ | (reconstructed) | | **Quotient (witness)** | | $\mathcal{Q}$ | Division quotient | $q_0, q_1, q_2, q_3$ | (reconstructed) | +| **Negative $q$ constant** | +| $\bar{q}$ | $-q \pmod{2^{272}}$ | $\bar{q}_0, \bar{q}_1, \bar{q}_2, \bar{q}_3$ | $\bar{q}_4$ | | **Carries (witness)** | | $c^{\text{lo}}$ | Lower carry | (single 84-bit value) | - | | $c^{\text{hi}}$ | Higher carry | (single 84-bit value) | - | @@ -111,25 +113,19 @@ If this equation holds: Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot r > 2^{514}$ > max possible value), which implies it holds modulo $q$. See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. -The non-native field relation is enforced through **three separate subrelations**: +The non-native field relation is enforced through three separate subrelations: -| Subrelation | Purpose | Modulus | Limbs Checked | -| ----------- | --------------------- | --------- | ------------------------------------- | -| 1 | Lower mod 2²⁷² check | $2^{136}$ | Limbs 0, 1 | -| 2 | Higher mod 2²⁷² check | $2^{136}$ | Limbs 2, 3 (with carry from subrel 1) | -| 3 | Native field check | $r$ | Full native reconstruction | +| Subrelation | Purpose | Modulus | Limbs checked | +| ----------- | -------------------------- | --------- | ------------------------------------- | +| 1 | Lower mod $2^{272}$ check | $2^{136}$ | Limbs 0, 1 | +| 2 | Higher mod $2^{272}$ check | $2^{136}$ | Limbs 2, 3 (with carry from subrel 1) | +| 3 | Native field check | $r$ | Full native reconstruction | Together, these prove the relation holds in integers. -> **Negative Modulus Constant**: We work with $-q \pmod{2^{272}}$ to avoid subtraction: -> $$\bar{q} := 2^{272} - q$$ -> Decomposed into limbs: -> $$\bar{q} = \bar{q}_0 + 2^{68} \cdot \bar{q}_1 + 2^{136} \cdot \bar{q}_2 + 2^{204} \cdot \bar{q}_3$$ -> Plus native field representation: $\bar{q}_4 = -q \pmod{r}$ - --- -### Subrelation 1: Lower Mod 2¹³⁢ Check +### Subrelation 1: Lower Mod $2^{136}$ Check Prove that when we compute the accumulation formula using limbs 0 and 1, the result is a multiple of $2^{136}$. @@ -139,7 +135,6 @@ We compute the accumulation using: - Limb 1 terms (contribute at weight $2^{68}$) The result should be: $\text{Result} = c^{\text{lo}} \cdot 2^{136}$ for some carry $c^{\text{lo}}$. - The limb 0 contribution is: $$ @@ -175,19 +170,19 @@ Thus, the combined subrelation is: $$\boxed{L_{\text{even}} \cdot \texttt{op} \cdot \left( T_0 + 2^{68} \cdot T_1 - 2^{136} \cdot c^{\text{lo}} \right) = 0}$$ -**Interpretation:** +Interpretation: - Compute $T_0$ (limb 0 contribution) - Compute $T_1 \cdot 2^{68}$ (limb 1 contribution, shifted by 68 bits) - Their sum should equal $c^{\text{lo}} \cdot 2^{136}$ - If this holds, the lower 136 bits of the accumulation equation are correct -**Active when:** +This subrelation is only active when: - $L_{\text{even}} = 1$ (even rows in mini-circuit) - $\texttt{op} \neq 0$ (not a no-op) -### Subrelation 2: Higher Mod 2¹³⁢ Check +### Subrelation 2: Higher Mod $2^{136}$ Check Prove that when we compute the accumulation formula using limbs 2 and 3, plus the carry from subrelation 1, the result is a multiple of $2^{136}$. @@ -198,7 +193,6 @@ We compute using: - Limb 3 terms (contribute at weight $2^{204}$) The result should be: $\text{Result} = c^{\text{hi}} \cdot 2^{136}$ for some carry $c^{\text{hi}}$. - The limb 2 contribution (with carry) is: $$ @@ -245,7 +239,6 @@ Together with Subrelation 1: We've proven the relation holds modulo $2^{272}$. ### Subrelation 3: Native Field Check Prove the accumulation formula holds when computed directly in 𝔽r (the native field). - First, reconstruct all values from their limbs: $$ @@ -277,7 +270,7 @@ L_{\text{even}} \cdot \texttt{op} \cdot \Big( &\tilde{a}^{\text{prev}} \cdot x_4 \end{align*}} $$ -Where: +where: - All arithmetic is performed in $\mathbb{F}_{r}$ - $x_4, v_4, (v^2)_4, (v^3)_4, (v^4)_4$ are the native field representations of the challenges @@ -289,19 +282,18 @@ Interpretation: - Compute the accumulation formula directly in $\mathbb{F}_{r}$ - If subrelations 1 and 2 prove it holds mod $2^{272}$, and subrelation 3 proves it holds mod $r$, then it holds in integers ---- - ## Decomposition Relation -The Decomposition Relation enforces the integrity of the limb decomposition system. While the Non-Native Field Relation proves the accumulation formula is correct, the Decomposition Relation proves all limb decompositions are valid. - -The relation consists of **48 subrelations** organized into five categories: +The Decomposition Relation enforces the integrity of the limb decomposition system. While the Non-Native Field Relation proves the accumulation formula is correct, the Decomposition Relation proves all limb decompositions are valid. It consists of 48 subrelations organized into five categories: -1. **Accumulator microlimb decomposition** (4 subrelations) β€” Active when $L_{\text{even}} \cdot \texttt{op} = 1$ -2. **Point & Scalar microlimb decomposition** (18 subrelations) β€” Active when $L_{\text{even}} = 1$ -3. **Wide limb decomposition** (2 subrelations) β€” Decompose 84-bit carry limbs -4. **Range constraint tightening** (20 subrelations) β€” Enforce stricter bounds on highest microlimbs -5. **Transcript composition** (6 subrelations) β€” Prove 68-bit limbs reconstruct transcript values +| Category | No. of Subrelations | Note | +| -------------------------------------- | ------------------- | --------------------------------------------------- | +| Accumulator microlimb decomposition | 4 | Active when $L_{\text{even}} \cdot \texttt{op} = 1$ | +| Point & Scalar microlimb decomposition | 18 | Active when $L_{\text{even}} = 1$ | +| Wide limb decomposition | 2 | Decompose 84-bit carry limbs | +| Range constraint tightening | 20 | Enforce stricter bounds on highest microlimbs | +| Transcript composition | 6 | Prove 68-bit limbs reconstruct transcript values | +| | | | These work with the **Permutation Relation** and **Delta Range Constraint** which together prove each microlimb is in $[0, 2^{14})$. @@ -349,13 +341,12 @@ where $k=4$ for 68/60-bit limbs and $k=3$ for 50/52-bit limbs. ### Category 3: Wide Limb Decomposition (Subrelations 20-21) -Carry limbs $c^{\text{lo}}, c^{\text{hi}}$ are **84 bits** (6 Γ— 14-bit microlimbs). To save space, the 5th and 6th microlimbs are stored in unused "tail" columns: +Carry limbs $c^{\text{lo}}, c^{\text{hi}}$ are 84 bits (6 Γ— 14-bit microlimbs). To save space, the 5th and 6th microlimbs are stored in unused "tail" columns: $$\boxed{L_{\text{even}} \cdot \left( \sum_{j=0}^{3} c_{i,j} \cdot 2^{14j} + c_{i,4} \cdot 2^{56} + c_{i,5} \cdot 2^{70} - c^{(i)} \right) = 0}$$ where $c^{(0)} = c^{\text{lo}}$, $c^{(1)} = c^{\text{hi}}$. - -**Microlimb reuse:** +Microlimb reuse: - $c_{0,4}^{\text{micro}}$ = `p_x_high_limbs_range_constraint_tail_shift` - $c_{0,5}^{\text{micro}}$ = `accumulator_high_limbs_range_constraint_tail_shift` @@ -378,41 +369,39 @@ $$\boxed{L_{\text{even}} \cdot \left( m_k \cdot 2^{14-r} - m_k^{\text{tail}} \ri implying $m_k \in [0, 2^r)$. -**Shift factors:** - -- $2^2 = 4$: Constrains to 12 bits (68-bit limbs) -- $2^4 = 16$: Constrains to 10 bits (52-bit limbs) -- $2^6 = 64$: Constrains to 8 bits (50-bit limbs) -- $2^{10} = 1024$: Constrains to 4 bits (60-bit limbs) +Shift factors: -**Subrelations 22-41** apply this pattern to: +- for 68-bit limbs: $2^2 = 4$: Constrains to 12 bits +- for 52-bit limbs: $2^4 = 16$: Constrains to 10 bits +- for 50-bit limbs: $2^6 = 64$: Constrains to 8 bits +- for 60-bit limbs: $2^{10} = 1024$: Constrains to 4 bits -- $P_x$ limbs (4 constraints): 12, 12, 12, 8 bits -- $P_y$ limbs (4 constraints): 12, 12, 12, 8 bits -- $z_1, z_2$ limbs (4 constraints): 12, 12, 4, 4 bits -- Accumulator limbs (4 constraints): 12, 12, 12, 8 bits -- Quotient limbs (4 constraints): 12, 12, 12, 10 bits +Subrelations 22-41 apply this pattern to: ---- +| Elements | No of subrelations | Tail bits | +| ----------- | ------------------ | ------------------- | +| $P_x$ limbs | 4 | 12, 12, 12, 8 bits | +| $P_y$ limbs | 4 | 12, 12, 12, 8 bits | +| $z_1$ limbs | 2 | 12, 4 bits | +| $z_2$ limbs | 2 | 12, 4 bits | +| Accumulator | 4 | 12, 12, 12, 8 bits | +| Quotient | 4 | 12, 12, 12, 10 bits | +| | | | ### Category 5: Transcript Value Composition (Subrelations 42-47) These prove that 68-bit limbs correctly reconstruct EccOpQueue transcript values. - -**General pattern** for composing two limbs into a transcript value: +General pattern for composing two limbs into a transcript value: $$\boxed{L_{\text{even}} \cdot \left( \ell_{\text{low}} + 2^{68} \cdot \ell_{\text{high}} - \text{transcript}_{\text{value}} \right) = 0}$$ -**Subrelations:** - -- **42-43:** $P_x$ composition: $P_{x,\text{lo}}$ (136-bit) and $P_{x,\text{hi}}$ (118-bit) -- **44-45:** $P_y$ composition: $P_{y,\text{lo}}$ (136-bit) and $P_{y,\text{hi}}$ (118-bit) -- **46-47:** $z_1, z_2$ composition: (128-bit each) - -**EccOpQueue encoding** (even/odd rows): +Subrelations: -- `X_LO_Y_HI`: $P_{x,\text{lo}}$ / $P_{y,\text{hi}}$ -- `X_HI_Z_1`: $P_{x,\text{hi}}$ / $z_1$ -- `Y_LO_Z_2`: $P_{y,\text{lo}}$ / $z_2$ +| Column | Even row | Odd row | No. of subrelations | +| ----------- | ---------------------------- | ---------------------------- | ------------------- | +| `X_LO_Y_HI` | $P_{x,\text{lo}}$ (136 bits) | $P_{y,\text{hi}}$ (118 bits) | 2 | +| `X_HI_Z_1` | $P_{x,\text{hi}}$ (118 bits) | $z_1$ (128 bits) | 2 | +| `Y_LO_Z_2` | $P_{y,\text{lo}}$ (136 bits) | $z_2$ (128 bits) | 2 | +| | | | | #### Interaction with Delta Range Constraint @@ -430,8 +419,6 @@ Together they guarantee: All limb decompositions are valid and all values are co ## Permutation Relation -### Overview - The Permutation Relation is the foundation of all range constraints in the Translator circuit. It proves that every microlimb value used in the circuit belongs to the set $[0, 2^{14} - 1]$. The relation uses a grand product argument comparing two multisets: - **Interleaved multiset:** All microlimbs as they appear in the circuit (spread across 16 segments due to interleaving) @@ -543,19 +530,14 @@ For each ordered wire $j \in \{0, 1, 2, 3, 4\}$: $$\boxed{\left( L_{\text{real\_last}} - 1 \right) \cdot \left( L_{\text{mask}} - 1 \right) \cdot \Delta_j \cdot (\Delta_j - 1) \cdot (\Delta_j - 2) \cdot (\Delta_j - 3) = 0}$$ where: -$$\Delta_j := w_j^{\text{ordered}}[i+1] - w_j^{\text{ordered}}[i]$$ - -Interpretation: +$$\Delta_j := w_j^{\text{ordered}}[i+1] - w_j^{\text{ordered}}[i].$$ -The constraint is active when: +When active, it forces: $\Delta_j \in \{0, 1, 2, 3\}$. The constraint is active when: - $L_{\text{real\_last}} = 0$ (not the last real row) - $L_{\text{mask}} = 0$ (not a masking row) -When active, it forces: $\Delta_j \in \{0, 1, 2, 3\}$ - Why maximum step 3? - To ensure full coverage of $[0, 2^{14} - 1]$, we insert "step values" into the sorted array: - Start at 0 @@ -568,25 +550,17 @@ Between these steps, actual microlimbs fill in the gaps. With $\Delta \in \{0, 1 - Every value $\leq 16383$ has a step value within distance 3 - Therefore, all values in range can be represented -Active when: All rows except last and masking rows - -- $L_{\text{real\_last}} = 1$: The last real row (boundary condition handled by subrelations 6-10) -- $L_{\text{mask}} = 1$: Zero-knowledge masking rows - Degree: 6 (product of 6 degree-1 polynomials: $(L_{\text{real\_last}} - 1) \cdot (L_{\text{mask}} - 1) \cdot \Delta \cdot (\Delta-1) \cdot (\Delta-2) \cdot (\Delta-3)$) --- ### Subrelations 6-10: Maximum Value Constraints -Purpose: Ensure the final value in each sorted column is exactly $2^{14} - 1 = 16383$. - +Ensure the final value in each sorted column is exactly $2^{14} - 1 = 16383$. For each ordered wire $j \in \{0, 1, 2, 3, 4\}$: $$\boxed{L_{\text{real\_last}} \cdot \left( w_j^{\text{ordered}} - (2^{14} - 1) \right) = 0}$$ -Interpretation: - At the last real row ($L_{\text{real\_last}} = 1$): $$w_j^{\text{ordered}}[\text{last}] = 2^{14} - 1 = 16383$$ @@ -604,8 +578,6 @@ Degree: 2 (Lagrange Γ— difference) ## Opcode Constraint Relation -### Overview - The Opcode Constraint Relation enforces that all operation codes (`op`) belong to the valid set: $$\boxed{\texttt{op} \in \{0, 1, 2, 3, 4, 8\}}$$ @@ -625,12 +597,6 @@ Valid opcodes: - `4`: Reset accumulator - `8`: [Special operation] -The relation consists of **5 subrelations** (one per non-zero opcode check), implemented for efficiency. - ---- - -### Polynomial Root Constraint - The constraint is expressed as a polynomial that has roots at the valid opcode values: $$\boxed{\left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8) = 0}$$ @@ -649,9 +615,7 @@ Active when: Even rows and mini-circuit masking rows Degree: 7 (degree-1 Lagrange Γ— degree-6 polynomial in `op`) -#### Implementation as 5 Subrelations - -For efficiency in the sumcheck protocol, the constraint is split into 5 subrelations: +Implementation as 5 Subrelations: For efficiency in the sumcheck protocol, the constraint is split into 5 subrelations: $$ \boxed{\begin{align*} @@ -681,12 +645,6 @@ The Accumulator Transfer Relation manages the lifecycle of the accumulator acros 3. Computation: Update accumulator on even rows (handled by Non-Native Field Relation) 4. Finalization: Verify final accumulator matches expected result -The accumulator must maintain state consistency across rows. Without these constraints: - -- Initial value could be non-zero (offsetting all computations) -- Accumulator could "reset" mid-computation -- Final value might not match ECCVM's expected result - The relation consists of 12 subrelations: - 4 for odd row propagation (copy previous value) @@ -708,7 +666,7 @@ Row-by-row behavior: ### Subrelations 1-4: Odd Row Propagation -Purpose: Ensure accumulator does not change on odd rows (data storage rows). +Ensure accumulator does not change on odd rows (data storage rows). For each limb $i \in \{0, 1, 2, 3\}$: @@ -724,35 +682,23 @@ Active when: Odd rows only ($L_{\text{odd}} = 1$) Degree: 2 (Lagrange Γ— difference) ---- - ### Subrelations 5-8: Initialization -Purpose: Initialize accumulator to zero at the start of the circuit. +Ensure the accumulator starts at zero at the beginning of the circuit. For each limb $i \in \{0, 1, 2, 3\}$: $$\boxed{L_{\text{first}} \cdot a_i^{\text{curr}} = 0}$$ -Interpretation: - -At the first row ($L_{\text{first}} = 1$): -$$a_i^{\text{curr}}[0] = 0 \quad \forall i \in \{0, 1, 2, 3\}$$ - -This ensures: -$$a^{\text{curr}}[0] = 0 + 0 \cdot 2^{68} + 0 \cdot 2^{136} + 0 \cdot 2^{204} = 0$$ - -If the accumulator starts at a non-zero value, all subsequent accumulations are offset by this initial value, breaking the consistency proof. +This implies that at the first row, all limbs of the accumulator are zero, ensuring the accumulator starts at 0. Active when: First row only ($L_{\text{first}} = 1$) Degree: 2 (Lagrange Γ— limb value) ---- - ### Subrelations 9-12: Finalization -Purpose: Verify the final accumulator value matches the expected result from ECCVM. +Verify the final accumulator value matches the expected result from ECCVM. For each limb $i \in \{0, 1, 2, 3\}$: @@ -768,12 +714,9 @@ Active when: Result row only ($L_{\text{result}} = 1$) Degree: 2 (Lagrange Γ— difference) ---- - ## Zero Constraints Relation The Zero Constraints Relation enforces that all witness wires are zero outside the mini-circuit. - Due to interleaving, the full circuit is 16Γ— larger than the mini-circuit: - Mini-circuit: $2^{13} = 8,192$ rows (actual computation) @@ -781,11 +724,6 @@ Due to interleaving, the full circuit is 16Γ— larger than the mini-circuit: Rows outside the mini-circuit (rows 8,192 to 131,071) must be zero. The relation consists of **68 subrelations**: -- 64 for range constraint microlimb wires -- 4 for EccOpQueue transcript wires - -### Which Wires Must Be Zero - Range constraint microlimb wires (64 total): - All `*_RANGE_CONSTRAINT_*` columns (see [Witness Trace Structure](#witness-trace-structure)) From 00027987851560a264c4db3a022f042a60f313e9 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Wed, 17 Dec 2025 11:45:56 +0000 Subject: [PATCH 19/29] chore: remove code changes (moved to separate branch) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move code changes to sb/translator-code-changes branch. This branch should only contain newly added .md files. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- ...translator_decomposition_relation_impl.hpp | 778 ++++++++---------- ...nslator_non_native_field_relation_impl.hpp | 294 +++---- .../translator_vm/translator_proving_key.cpp | 7 +- 3 files changed, 468 insertions(+), 611 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp index 768039e3da23..fcbe7b13dd7f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp @@ -13,15 +13,13 @@ namespace bb { * @brief Expression for decomposition of various values into smaller limbs or microlimbs. * @details This relation enforces three types of subrelations: * 1) A subrelation decomposing a value from the transcript (for example, z1) into 68-bit limbs. These relations - * will have the structure - * `lagrange_even_in_minicircuitβ‹…(a - a_low - a_highβ‹…2⁢⁸)` - * 2) A subrelation decomposing a value of one of the limbs used in bigfield computation (for example, the lower - * wide relation limb) into 14-bit limbs. These relations will have the structure - * `lagrange_even_in_minicircuitβ‹…(a - a_0 - a_1β‹…2¹⁴ - ....)` - * 3) A subrelation making a microlimb range constraint more constraining. For example, we want to constrain - * some values to 12 bits instead of 14. So we add a constraint - * `lagrange_even_in_minicircuitβ‹…(a_highestβ‹…4 - a_tail)`. - * In a separate relation both a_highest and a_tail are constrained to be 14 bits, but this relation + * will have the structure `lagrange_even_in_minicircuitβ‹…(a - a_low - a_highβ‹…2⁢⁸)` + * 2) A subrelation decomposing a value of one of the limbs used in bigfield computation (for example, the lower + * wide relation limb) into 14-bit limbs. These relations will have the structure `lagrange_even_in_minicircuitβ‹…(a - + * a_0 - a_1β‹…2¹⁴ - + * ....)` 3) A subrelation making a microlimb range constraint more constraining. For example, we want to constrain + * some values to 12 bits instead of 14. So we add a constraint `lagrange_even_in_minicircuitβ‹…(a_highestβ‹…4 - + * a_tail)`. In a separate relation both a_highest and a_tail are constrained to be 14 bits, but this relation * changes the constraint on a_highest to be 12 bits. * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` @@ -46,92 +44,76 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio using View = typename Accumulator::View; // Values to multiply an element by to perform an appropriate shift - static constexpr auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); - static constexpr auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; - static constexpr auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; - static constexpr auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); + static auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; - // A = (A₃ || Aβ‚‚ || A₁ || Aβ‚€) auto accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); auto accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); auto accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); auto accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); - - // Aβ‚€ = (Aβ‚€,β‚„ || Aβ‚€,₃ || Aβ‚€,β‚‚ || Aβ‚€,₁ || Aβ‚€,β‚€) (68-bit limb) - auto accumulator_limb_0_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0); - auto accumulator_limb_0_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1); - auto accumulator_limb_0_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2); - auto accumulator_limb_0_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3); - auto accumulator_limb_0_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); - - // A₁ = (A₁,β‚„ || A₁,₃ || A₁,β‚‚ || A₁,₁ || A₁,β‚€) (68-bit limb) - auto accumulator_limb_1_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0_shift); - auto accumulator_limb_1_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1_shift); - auto accumulator_limb_1_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2_shift); - auto accumulator_limb_1_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3_shift); - auto accumulator_limb_1_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4_shift); - - // Aβ‚‚ = (Aβ‚‚,β‚„ || Aβ‚‚,₃ || Aβ‚‚,β‚‚ || Aβ‚‚,₁ || Aβ‚‚,β‚€) (68-bit limb) - auto accumulator_limb_2_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0); - auto accumulator_limb_2_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1); - auto accumulator_limb_2_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2); - auto accumulator_limb_2_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3); - auto accumulator_limb_2_range_constraint_4 = View(in.accumulator_high_limbs_range_constraint_4); - - // A₃ = (A₃,₃ || A₃,β‚‚ || A₃,₁ || A₃,β‚€) (50-bit limb) - auto accumulator_limb_3_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0_shift); - auto accumulator_limb_3_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1_shift); - auto accumulator_limb_3_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2_shift); - auto accumulator_limb_3_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3_shift); - + auto accumulator_low_limbs_range_constraint_0 = View(in.accumulator_low_limbs_range_constraint_0); + auto accumulator_low_limbs_range_constraint_1 = View(in.accumulator_low_limbs_range_constraint_1); + auto accumulator_low_limbs_range_constraint_2 = View(in.accumulator_low_limbs_range_constraint_2); + auto accumulator_low_limbs_range_constraint_3 = View(in.accumulator_low_limbs_range_constraint_3); + auto accumulator_low_limbs_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); + auto accumulator_low_limbs_range_constraint_0_shift = View(in.accumulator_low_limbs_range_constraint_0_shift); + auto accumulator_low_limbs_range_constraint_1_shift = View(in.accumulator_low_limbs_range_constraint_1_shift); + auto accumulator_low_limbs_range_constraint_2_shift = View(in.accumulator_low_limbs_range_constraint_2_shift); + auto accumulator_low_limbs_range_constraint_3_shift = View(in.accumulator_low_limbs_range_constraint_3_shift); + auto accumulator_low_limbs_range_constraint_4_shift = View(in.accumulator_low_limbs_range_constraint_4_shift); + auto accumulator_high_limbs_range_constraint_0 = View(in.accumulator_high_limbs_range_constraint_0); + auto accumulator_high_limbs_range_constraint_1 = View(in.accumulator_high_limbs_range_constraint_1); + auto accumulator_high_limbs_range_constraint_2 = View(in.accumulator_high_limbs_range_constraint_2); + auto accumulator_high_limbs_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3); + auto accumulator_high_limbs_range_constraint_4 = View(in.accumulator_high_limbs_range_constraint_4); + auto accumulator_high_limbs_range_constraint_0_shift = View(in.accumulator_high_limbs_range_constraint_0_shift); + auto accumulator_high_limbs_range_constraint_1_shift = View(in.accumulator_high_limbs_range_constraint_1_shift); + auto accumulator_high_limbs_range_constraint_2_shift = View(in.accumulator_high_limbs_range_constraint_2_shift); + auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); auto op = View(in.op); auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); auto not_even_or_no_op_scaled = lagrange_even_in_minicircuit * op * scaling_factor; // Contribution 1, accumulator lowest limb decomposition - // clang-format off auto tmp_1 = - ((accumulator_limb_0_range_constraint_0 + - accumulator_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - accumulator_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + ((accumulator_low_limbs_range_constraint_0 + accumulator_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + accumulator_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - accumulators_binary_limbs_0); tmp_1 *= not_even_or_no_op_scaled; std::get<0>(accumulators) += tmp_1; // Contribution 2, accumulator second limb decomposition - auto tmp_2 = - ((accumulator_limb_1_range_constraint_0 + - accumulator_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - accumulator_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - accumulators_binary_limbs_1); + auto tmp_2 = ((accumulator_low_limbs_range_constraint_0_shift + + accumulator_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + accumulator_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + accumulator_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + accumulator_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + accumulators_binary_limbs_1); tmp_2 *= not_even_or_no_op_scaled; std::get<1>(accumulators) += tmp_2; // Contribution 3, accumulator second highest limb decomposition auto tmp_3 = - ((accumulator_limb_2_range_constraint_0 + - accumulator_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - accumulator_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + ((accumulator_high_limbs_range_constraint_0 + accumulator_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + accumulator_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + accumulator_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + accumulator_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - accumulators_binary_limbs_2); tmp_3 *= not_even_or_no_op_scaled; std::get<2>(accumulators) += tmp_3; // Contribution 4, accumulator highest limb decomposition - auto tmp_4 = - ((accumulator_limb_3_range_constraint_0 + - accumulator_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + - accumulator_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - accumulator_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - - accumulators_binary_limbs_3); + auto tmp_4 = ((accumulator_high_limbs_range_constraint_0_shift + + accumulator_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + accumulator_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + accumulator_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + accumulators_binary_limbs_3); tmp_4 *= not_even_or_no_op_scaled; std::get<3>(accumulators) += tmp_4; - // clang-format on }(); [&]() { @@ -139,14 +121,14 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio using View = typename Accumulator::View; // Value to multiply an element by to perform an appropriate shift - static constexpr auto LIMB_SHIFT = FF(uint256_t(1) << NUM_LIMB_BITS); + static auto LIMB_SHIFT = FF(uint256_t(1) << NUM_LIMB_BITS); // Values to multiply an element by to perform an appropriate shift - static constexpr auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); - static constexpr auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; - static constexpr auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; - static constexpr auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; - static constexpr auto MICRO_LIMB_SHIFTx5 = MICRO_LIMB_SHIFTx4 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFT = FF(uint256_t(1) << NUM_MICRO_LIMB_BITS); + static auto MICRO_LIMB_SHIFTx2 = MICRO_LIMB_SHIFT * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx3 = MICRO_LIMB_SHIFTx2 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx4 = MICRO_LIMB_SHIFTx3 * MICRO_LIMB_SHIFT; + static auto MICRO_LIMB_SHIFTx5 = MICRO_LIMB_SHIFTx4 * MICRO_LIMB_SHIFT; auto accumulator_low_limbs_range_constraint_4 = View(in.accumulator_low_limbs_range_constraint_4); auto accumulator_low_limbs_range_constraint_4_shift = View(in.accumulator_low_limbs_range_constraint_4_shift); @@ -162,405 +144,305 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio static auto SHIFT_4_TO_14 = FF(1024); // Shift used to range constrain the last mircrolimb of 60-bit limbs from z scalars - // Basic notation: - // - // Pβ‚“ = (Pβ‚“,₃ || Pβ‚“,β‚‚ || Pβ‚“,₁ || Pβ‚“,β‚€) - // Pα΅§ = (Pα΅§,₃ || Pα΅§,β‚‚ || Pα΅§,₁ || Pα΅§,β‚€) - // z₁ = (z₁,₁ || z₁,β‚€) - // zβ‚‚ = (zβ‚‚,₁ || zβ‚‚,β‚€) - // Q = (q₃ || qβ‚‚ || q₁ || qβ‚€) - // - // Each of these is further decomposed into 14-bit microlimbs as follows: - // - // Pβ‚“,β‚€ = (Pβ‚“,β‚€[4] || Pβ‚“,β‚€[3] || Pβ‚“,β‚€[2] || Pβ‚“,β‚€[1] || Pβ‚“,β‚€[0]) - auto p_x_limb_0 = View(in.p_x_low_limbs); - auto p_x_limb_0_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0); - auto p_x_limb_0_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1); - auto p_x_limb_0_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2); - auto p_x_limb_0_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3); - auto p_x_limb_0_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4); - - // Pβ‚“,₁ = (Pβ‚“,₁[4] || Pβ‚“,₁[3] || Pβ‚“,₁[2] || Pβ‚“,₁[1] || Pβ‚“,₁[0]) - auto p_x_limb_1 = View(in.p_x_low_limbs_shift); - auto p_x_limb_1_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0_shift); - auto p_x_limb_1_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1_shift); - auto p_x_limb_1_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2_shift); - auto p_x_limb_1_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3_shift); - auto p_x_limb_1_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4_shift); - - // Pβ‚“,β‚‚ = (Pβ‚“,β‚‚[4] || Pβ‚“,β‚‚[3] || Pβ‚“,β‚‚[2] || Pβ‚“,β‚‚[1] || Pβ‚“,β‚‚[0]) - auto p_x_limb_2 = View(in.p_x_high_limbs); - auto p_x_limb_2_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0); - auto p_x_limb_2_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1); - auto p_x_limb_2_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2); - auto p_x_limb_2_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3); - auto p_x_limb_2_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_4); - - // Pβ‚“,₃ = (Pβ‚“,₃[4] || Pβ‚“,₃[3] || Pβ‚“,₃[2] || Pβ‚“,₃[1] || Pβ‚“,₃[0]) - auto p_x_limb_3 = View(in.p_x_high_limbs_shift); - auto p_x_limb_3_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0_shift); - auto p_x_limb_3_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1_shift); - auto p_x_limb_3_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2_shift); - auto p_x_limb_3_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3_shift); - - // Pα΅§,β‚€ = (Pα΅§,β‚€[4] || Pα΅§,β‚€[3] || Pα΅§,β‚€[2] || Pα΅§,β‚€[1] || Pα΅§,β‚€[0]) - auto p_y_limb_0 = View(in.p_y_low_limbs); - auto p_y_limb_0_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0); - auto p_y_limb_0_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1); - auto p_y_limb_0_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2); - auto p_y_limb_0_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3); - auto p_y_limb_0_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4); - - // Pα΅§,₁ = (Pα΅§,₁[4] || Pα΅§,₁[3] || Pα΅§,₁[2] || Pα΅§,₁[1] || Pα΅§,₁[0]) - auto p_y_limb_1 = View(in.p_y_low_limbs_shift); - auto p_y_limb_1_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0_shift); - auto p_y_limb_1_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1_shift); - auto p_y_limb_1_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2_shift); - auto p_y_limb_1_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3_shift); - auto p_y_limb_1_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4_shift); - - // Pα΅§,β‚‚ = (Pα΅§,β‚‚[4] || Pα΅§,β‚‚[3] || Pα΅§,β‚‚[2] || Pα΅§,β‚‚[1] || Pα΅§,β‚‚[0]) - auto p_y_limb_2 = View(in.p_y_high_limbs); - auto p_y_limb_2_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0); - auto p_y_limb_2_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1); - auto p_y_limb_2_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2); - auto p_y_limb_2_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3); - auto p_y_limb_2_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_4); - - // Pα΅§,₃ = (Pα΅§,₃[3] || Pα΅§,₃[2] || Pα΅§,₃[1] || Pα΅§,₃[0]) - auto p_y_limb_3 = View(in.p_y_high_limbs_shift); - auto p_y_limb_3_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0_shift); - auto p_y_limb_3_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1_shift); - auto p_y_limb_3_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2_shift); - auto p_y_limb_3_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3_shift); - - // z₁,β‚€ = (z₁,β‚€[4] || z₁,β‚€[3] || z₁,β‚€[2] || z₁,β‚€[1] || z₁,β‚€[0]) - auto z_1_limb_0 = View(in.z_low_limbs); - auto z_1_limb_0_range_constraint_0 = View(in.z_low_limbs_range_constraint_0); - auto z_1_limb_0_range_constraint_1 = View(in.z_low_limbs_range_constraint_1); - auto z_1_limb_0_range_constraint_2 = View(in.z_low_limbs_range_constraint_2); - auto z_1_limb_0_range_constraint_3 = View(in.z_low_limbs_range_constraint_3); - auto z_1_limb_0_range_constraint_4 = View(in.z_low_limbs_range_constraint_4); - - // zβ‚‚,β‚€ = (zβ‚‚,β‚€[4] || zβ‚‚,β‚€[3] || zβ‚‚,β‚€[2] || zβ‚‚,β‚€[1] || zβ‚‚,β‚€[0]) - auto z_2_limb_0 = View(in.z_low_limbs_shift); - auto z_2_limb_0_range_constraint_0 = View(in.z_low_limbs_range_constraint_0_shift); - auto z_2_limb_0_range_constraint_1 = View(in.z_low_limbs_range_constraint_1_shift); - auto z_2_limb_0_range_constraint_2 = View(in.z_low_limbs_range_constraint_2_shift); - auto z_2_limb_0_range_constraint_3 = View(in.z_low_limbs_range_constraint_3_shift); - auto z_2_limb_0_range_constraint_4 = View(in.z_low_limbs_range_constraint_4_shift); - - // z₁,₁ = (z₁,₁[4] || z₁,₁[3] || z₁,₁[2] || z₁,₁[1] || z₁,₁[0]) - auto z_1_limb_1 = View(in.z_high_limbs); - auto z_1_limb_1_range_constraint_0 = View(in.z_high_limbs_range_constraint_0); - auto z_1_limb_1_range_constraint_1 = View(in.z_high_limbs_range_constraint_1); - auto z_1_limb_1_range_constraint_2 = View(in.z_high_limbs_range_constraint_2); - auto z_1_limb_1_range_constraint_3 = View(in.z_high_limbs_range_constraint_3); - auto z_1_limb_1_range_constraint_4 = View(in.z_high_limbs_range_constraint_4); - - // zβ‚‚,₁ = (zβ‚‚,₁[4] || zβ‚‚,₁[3] || zβ‚‚,₁[2] || zβ‚‚,₁[1] || zβ‚‚,₁[0]) - auto z_2_limb_1 = View(in.z_high_limbs_shift); - auto z_2_limb_1_range_constraint_0 = View(in.z_high_limbs_range_constraint_0_shift); - auto z_2_limb_1_range_constraint_1 = View(in.z_high_limbs_range_constraint_1_shift); - auto z_2_limb_1_range_constraint_2 = View(in.z_high_limbs_range_constraint_2_shift); - auto z_2_limb_1_range_constraint_3 = View(in.z_high_limbs_range_constraint_3_shift); - auto z_2_limb_1_range_constraint_4 = View(in.z_high_limbs_range_constraint_4_shift); - - // Qβ‚€ = (Qβ‚€[4] || Qβ‚€[3] || Qβ‚€[2] || Qβ‚€[1] || Qβ‚€[0]) - auto quotient_binary_limbs_0 = View(in.quotient_low_binary_limbs); - auto quotient_limb_0_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0); - auto quotient_limb_0_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1); - auto quotient_limb_0_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2); - auto quotient_limb_0_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3); - auto quotient_limb_0_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4); - - // Q₁ = (Q₁[4] || Q₁[3] || Q₁[2] || Q₁[1] || Q₁[0]) - auto quotient_binary_limbs_1 = View(in.quotient_low_binary_limbs_shift); - auto quotient_limb_1_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0_shift); - auto quotient_limb_1_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1_shift); - auto quotient_limb_1_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2_shift); - auto quotient_limb_1_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3_shift); - auto quotient_limb_1_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4_shift); - - // Qβ‚‚ = (Qβ‚‚[4] || Qβ‚‚[3] || Qβ‚‚[2] || Qβ‚‚[1] || Qβ‚‚[0]) - auto quotient_binary_limbs_2 = View(in.quotient_high_binary_limbs); - auto quotient_limb_2_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0); - auto quotient_limb_2_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1); - auto quotient_limb_2_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2); - auto quotient_limb_2_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3); - auto quotient_limb_2_range_constraint_4 = View(in.quotient_high_limbs_range_constraint_4); - - // Q₃ = (Q₃[3] || Q₃[2] || Q₃[1] || Q₃[0]) - auto quotient_binary_limbs_3 = View(in.quotient_high_binary_limbs_shift); - auto quotient_limb_3_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0_shift); - auto quotient_limb_3_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1_shift); - auto quotient_limb_3_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2_shift); - auto quotient_limb_3_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3_shift); - - // Carry limbs: relation_wide_limbs_lo (84 bits) - // cβ‚—β‚’ = (cβ‚—β‚’[5] || cβ‚—β‚’[4] || cβ‚—β‚’[3] || cβ‚—β‚’[2] || cβ‚—β‚’[1] || cβ‚—β‚’[0]) - auto relation_wide_limbs_lo = View(in.relation_wide_limbs); - auto relation_wide_limbs_lo_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0); - auto relation_wide_limbs_lo_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1); - auto relation_wide_limbs_lo_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2); - auto relation_wide_limbs_lo_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3); - - // The final two limbs of cβ‚—β‚’ are stored in the unused tail columns of pβ‚“ and accumulator. - auto relation_wide_limbs_lo_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_tail_shift); - auto relation_wide_limbs_lo_range_constraint_5 = View(in.accumulator_high_limbs_range_constraint_tail_shift); - - // Carry limbs: relation_wide_limbs_hi (84 bits) - // cβ‚•α΅’ = (cβ‚•α΅’[5] || cβ‚•α΅’[4] || cβ‚•α΅’[3] || cβ‚•α΅’[2] || cβ‚•α΅’[1] || cβ‚•α΅’[0]) - auto relation_wide_limbs_hi = View(in.relation_wide_limbs_shift); - auto relation_wide_limbs_hi_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0_shift); - auto relation_wide_limbs_hi_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1_shift); - auto relation_wide_limbs_hi_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2_shift); - auto relation_wide_limbs_hi_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3_shift); - - // The final two limbs of cβ‚•α΅’ are stored in the unused tail columns of pα΅§ and quotient. - auto relation_wide_limbs_hi_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_tail_shift); - auto relation_wide_limbs_hi_range_constraint_5 = View(in.quotient_high_limbs_range_constraint_tail_shift); - - // Additional tail microlimbs for tighter range constraints - // ==> [Pβ‚“,β‚€[tail], Pβ‚“,₁[tail], Pβ‚“,β‚‚[tail], Pβ‚“,₃[tail]] - auto p_x_limb_0_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail); - auto p_x_limb_1_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail_shift); - auto p_x_limb_2_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_tail); - - // Pβ‚“,₃[tail] is stored in the unused (odd) column of Pβ‚“,₃[4]. - auto p_x_limb_3_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_4_shift); - - // ==> [Pα΅§,β‚€[tail], Pα΅§,₁[tail], Pα΅§,β‚‚[tail], Pα΅§,₃[tail]] - auto p_y_limb_0_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail); - auto p_y_limb_1_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail_shift); - auto p_y_limb_2_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_tail); - - // Pα΅§,₃[tail] is stored in the unused (odd) column of Pα΅§,₃[4]. - auto p_y_limb_3_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_4_shift); - - // ==> [z₁,β‚€[tail], zβ‚‚,β‚€[tail], z₁,₁[tail], zβ‚‚,₁[tail]] - auto z_1_limb_0_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail); - auto z_2_limb_0_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail_shift); - auto z_1_limb_1_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail); - auto z_2_limb_1_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail_shift); - - // Accumulator and quotient tail microlimbs for tighter range constraints - // ==> [Aβ‚€[tail], A₁[tail], Aβ‚‚[tail], A₃[tail]] - auto accumulator_limb_0_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail); - auto accumulator_limb_1_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail_shift); - auto accumulator_limb_2_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_tail); - - // Fetch the highest microlimb of A₃ for range constraint - // To get A₃[tail]], we fetch the unused (odd) column of A₃[3]. - auto accumulator_limb_3_range_constraint_3 = View(in.accumulator_high_limbs_range_constraint_3_shift); - auto accumulator_limb_3_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_4_shift); - - // ==> [Qβ‚€[tail], Q₁[tail], Qβ‚‚[tail], Q₃[tail]] - // To get Q₃[tail], we fetch the unused (odd) column of Q₃[3]. - auto quotient_limb_0_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail); - auto quotient_limb_1_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail_shift); - auto quotient_limb_2_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_tail); - auto quotient_limb_3_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_4_shift); - - // Coordinate decompositions - // first column: [x_lo, y_hi] - // second column: [x_hi, z_1] - // third column: [y_lo, z_2] - auto x_lo = View(in.x_lo_y_hi); - auto y_hi = View(in.x_lo_y_hi_shift); - auto x_hi = View(in.x_hi_z_1); - auto z_one = View(in.x_hi_z_1_shift); - auto y_lo = View(in.y_lo_z_2); - auto z_two = View(in.y_lo_z_2_shift); + auto p_x_low_limbs = View(in.p_x_low_limbs); + auto p_x_low_limbs_range_constraint_0 = View(in.p_x_low_limbs_range_constraint_0); + auto p_x_low_limbs_range_constraint_1 = View(in.p_x_low_limbs_range_constraint_1); + auto p_x_low_limbs_range_constraint_2 = View(in.p_x_low_limbs_range_constraint_2); + auto p_x_low_limbs_range_constraint_3 = View(in.p_x_low_limbs_range_constraint_3); + auto p_x_low_limbs_range_constraint_4 = View(in.p_x_low_limbs_range_constraint_4); + auto p_x_low_limbs_shift = View(in.p_x_low_limbs_shift); + auto p_x_low_limbs_range_constraint_0_shift = View(in.p_x_low_limbs_range_constraint_0_shift); + auto p_x_low_limbs_range_constraint_1_shift = View(in.p_x_low_limbs_range_constraint_1_shift); + auto p_x_low_limbs_range_constraint_2_shift = View(in.p_x_low_limbs_range_constraint_2_shift); + auto p_x_low_limbs_range_constraint_3_shift = View(in.p_x_low_limbs_range_constraint_3_shift); + auto p_x_low_limbs_range_constraint_4_shift = View(in.p_x_low_limbs_range_constraint_4_shift); + auto p_x_high_limbs = View(in.p_x_high_limbs); + auto p_x_high_limbs_range_constraint_0 = View(in.p_x_high_limbs_range_constraint_0); + auto p_x_high_limbs_range_constraint_1 = View(in.p_x_high_limbs_range_constraint_1); + auto p_x_high_limbs_range_constraint_2 = View(in.p_x_high_limbs_range_constraint_2); + auto p_x_high_limbs_range_constraint_3 = View(in.p_x_high_limbs_range_constraint_3); + auto p_x_high_limbs_range_constraint_4 = View(in.p_x_high_limbs_range_constraint_4); + auto p_x_high_limbs_shift = View(in.p_x_high_limbs_shift); + auto p_x_high_limbs_range_constraint_0_shift = View(in.p_x_high_limbs_range_constraint_0_shift); + auto p_x_high_limbs_range_constraint_1_shift = View(in.p_x_high_limbs_range_constraint_1_shift); + auto p_x_high_limbs_range_constraint_2_shift = View(in.p_x_high_limbs_range_constraint_2_shift); + auto p_x_high_limbs_range_constraint_3_shift = View(in.p_x_high_limbs_range_constraint_3_shift); + auto p_y_low_limbs = View(in.p_y_low_limbs); + auto p_y_low_limbs_range_constraint_0 = View(in.p_y_low_limbs_range_constraint_0); + auto p_y_low_limbs_range_constraint_1 = View(in.p_y_low_limbs_range_constraint_1); + auto p_y_low_limbs_range_constraint_2 = View(in.p_y_low_limbs_range_constraint_2); + auto p_y_low_limbs_range_constraint_3 = View(in.p_y_low_limbs_range_constraint_3); + auto p_y_low_limbs_range_constraint_4 = View(in.p_y_low_limbs_range_constraint_4); + auto p_y_low_limbs_shift = View(in.p_y_low_limbs_shift); + auto p_y_low_limbs_range_constraint_0_shift = View(in.p_y_low_limbs_range_constraint_0_shift); + auto p_y_low_limbs_range_constraint_1_shift = View(in.p_y_low_limbs_range_constraint_1_shift); + auto p_y_low_limbs_range_constraint_2_shift = View(in.p_y_low_limbs_range_constraint_2_shift); + auto p_y_low_limbs_range_constraint_3_shift = View(in.p_y_low_limbs_range_constraint_3_shift); + auto p_y_low_limbs_range_constraint_4_shift = View(in.p_y_low_limbs_range_constraint_4_shift); + auto p_y_high_limbs = View(in.p_y_high_limbs); + auto p_y_high_limbs_range_constraint_0 = View(in.p_y_high_limbs_range_constraint_0); + auto p_y_high_limbs_range_constraint_1 = View(in.p_y_high_limbs_range_constraint_1); + auto p_y_high_limbs_range_constraint_2 = View(in.p_y_high_limbs_range_constraint_2); + auto p_y_high_limbs_range_constraint_3 = View(in.p_y_high_limbs_range_constraint_3); + auto p_y_high_limbs_range_constraint_4 = View(in.p_y_high_limbs_range_constraint_4); + auto p_y_high_limbs_shift = View(in.p_y_high_limbs_shift); + auto p_y_high_limbs_range_constraint_0_shift = View(in.p_y_high_limbs_range_constraint_0_shift); + auto p_y_high_limbs_range_constraint_1_shift = View(in.p_y_high_limbs_range_constraint_1_shift); + auto p_y_high_limbs_range_constraint_2_shift = View(in.p_y_high_limbs_range_constraint_2_shift); + auto p_y_high_limbs_range_constraint_3_shift = View(in.p_y_high_limbs_range_constraint_3_shift); + auto z_low_limbs = View(in.z_low_limbs); + auto z_low_limbs_range_constraint_0 = View(in.z_low_limbs_range_constraint_0); + auto z_low_limbs_range_constraint_1 = View(in.z_low_limbs_range_constraint_1); + auto z_low_limbs_range_constraint_2 = View(in.z_low_limbs_range_constraint_2); + auto z_low_limbs_range_constraint_3 = View(in.z_low_limbs_range_constraint_3); + auto z_low_limbs_range_constraint_4 = View(in.z_low_limbs_range_constraint_4); + auto z_low_limbs_shift = View(in.z_low_limbs_shift); + auto z_low_limbs_range_constraint_0_shift = View(in.z_low_limbs_range_constraint_0_shift); + auto z_low_limbs_range_constraint_1_shift = View(in.z_low_limbs_range_constraint_1_shift); + auto z_low_limbs_range_constraint_2_shift = View(in.z_low_limbs_range_constraint_2_shift); + auto z_low_limbs_range_constraint_3_shift = View(in.z_low_limbs_range_constraint_3_shift); + auto z_low_limbs_range_constraint_4_shift = View(in.z_low_limbs_range_constraint_4_shift); + auto z_high_limbs = View(in.z_high_limbs); + auto z_high_limbs_range_constraint_0 = View(in.z_high_limbs_range_constraint_0); + auto z_high_limbs_range_constraint_1 = View(in.z_high_limbs_range_constraint_1); + auto z_high_limbs_range_constraint_2 = View(in.z_high_limbs_range_constraint_2); + auto z_high_limbs_range_constraint_3 = View(in.z_high_limbs_range_constraint_3); + auto z_high_limbs_range_constraint_4 = View(in.z_high_limbs_range_constraint_4); + auto z_high_limbs_shift = View(in.z_high_limbs_shift); + auto z_high_limbs_range_constraint_0_shift = View(in.z_high_limbs_range_constraint_0_shift); + auto z_high_limbs_range_constraint_1_shift = View(in.z_high_limbs_range_constraint_1_shift); + auto z_high_limbs_range_constraint_2_shift = View(in.z_high_limbs_range_constraint_2_shift); + auto z_high_limbs_range_constraint_3_shift = View(in.z_high_limbs_range_constraint_3_shift); + auto z_high_limbs_range_constraint_4_shift = View(in.z_high_limbs_range_constraint_4_shift); + auto quotient_low_binary_limbs = View(in.quotient_low_binary_limbs); + auto quotient_low_limbs_range_constraint_0 = View(in.quotient_low_limbs_range_constraint_0); + auto quotient_low_limbs_range_constraint_1 = View(in.quotient_low_limbs_range_constraint_1); + auto quotient_low_limbs_range_constraint_2 = View(in.quotient_low_limbs_range_constraint_2); + auto quotient_low_limbs_range_constraint_3 = View(in.quotient_low_limbs_range_constraint_3); + auto quotient_low_limbs_range_constraint_4 = View(in.quotient_low_limbs_range_constraint_4); + auto quotient_low_binary_limbs_shift = View(in.quotient_low_binary_limbs_shift); + auto quotient_low_limbs_range_constraint_0_shift = View(in.quotient_low_limbs_range_constraint_0_shift); + auto quotient_low_limbs_range_constraint_1_shift = View(in.quotient_low_limbs_range_constraint_1_shift); + auto quotient_low_limbs_range_constraint_2_shift = View(in.quotient_low_limbs_range_constraint_2_shift); + auto quotient_low_limbs_range_constraint_3_shift = View(in.quotient_low_limbs_range_constraint_3_shift); + auto quotient_low_limbs_range_constraint_4_shift = View(in.quotient_low_limbs_range_constraint_4_shift); + auto quotient_high_binary_limbs = View(in.quotient_high_binary_limbs); + auto quotient_high_limbs_range_constraint_0 = View(in.quotient_high_limbs_range_constraint_0); + auto quotient_high_limbs_range_constraint_1 = View(in.quotient_high_limbs_range_constraint_1); + auto quotient_high_limbs_range_constraint_2 = View(in.quotient_high_limbs_range_constraint_2); + auto quotient_high_limbs_range_constraint_3 = View(in.quotient_high_limbs_range_constraint_3); + auto quotient_high_limbs_range_constraint_4 = View(in.quotient_high_limbs_range_constraint_4); + auto quotient_high_binary_limbs_shift = View(in.quotient_high_binary_limbs_shift); + auto quotient_high_limbs_range_constraint_0_shift = View(in.quotient_high_limbs_range_constraint_0_shift); + auto quotient_high_limbs_range_constraint_1_shift = View(in.quotient_high_limbs_range_constraint_1_shift); + auto quotient_high_limbs_range_constraint_2_shift = View(in.quotient_high_limbs_range_constraint_2_shift); + auto quotient_high_limbs_range_constraint_3_shift = View(in.quotient_high_limbs_range_constraint_3_shift); + auto relation_wide_limbs = View(in.relation_wide_limbs); + auto relation_wide_limbs_range_constraint_0 = View(in.relation_wide_limbs_range_constraint_0); + auto relation_wide_limbs_range_constraint_1 = View(in.relation_wide_limbs_range_constraint_1); + auto relation_wide_limbs_range_constraint_2 = View(in.relation_wide_limbs_range_constraint_2); + auto relation_wide_limbs_range_constraint_3 = View(in.relation_wide_limbs_range_constraint_3); + auto p_x_high_limbs_range_constraint_tail_shift = View(in.p_x_high_limbs_range_constraint_tail_shift); + auto accumulator_high_limbs_range_constraint_tail_shift = + View(in.accumulator_high_limbs_range_constraint_tail_shift); + auto relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); + auto relation_wide_limbs_range_constraint_0_shift = View(in.relation_wide_limbs_range_constraint_0_shift); + auto relation_wide_limbs_range_constraint_1_shift = View(in.relation_wide_limbs_range_constraint_1_shift); + auto relation_wide_limbs_range_constraint_2_shift = View(in.relation_wide_limbs_range_constraint_2_shift); + auto relation_wide_limbs_range_constraint_3_shift = View(in.relation_wide_limbs_range_constraint_3_shift); + auto p_y_high_limbs_range_constraint_tail_shift = View(in.p_y_high_limbs_range_constraint_tail_shift); + auto quotient_high_limbs_range_constraint_tail_shift = View(in.quotient_high_limbs_range_constraint_tail_shift); + auto p_x_low_limbs_range_constraint_tail = View(in.p_x_low_limbs_range_constraint_tail); + auto p_x_low_limbs_range_constraint_tail_shift = View(in.p_x_low_limbs_range_constraint_tail_shift); + auto p_x_high_limbs_range_constraint_tail = View(in.p_x_high_limbs_range_constraint_tail); + auto p_x_high_limbs_range_constraint_4_shift = View(in.p_x_high_limbs_range_constraint_4_shift); + auto p_y_low_limbs_range_constraint_tail = View(in.p_y_low_limbs_range_constraint_tail); + auto p_y_low_limbs_range_constraint_tail_shift = View(in.p_y_low_limbs_range_constraint_tail_shift); + auto p_y_high_limbs_range_constraint_tail = View(in.p_y_high_limbs_range_constraint_tail); + auto p_y_high_limbs_range_constraint_4_shift = View(in.p_y_high_limbs_range_constraint_4_shift); + auto z_low_limbs_range_constraint_tail = View(in.z_low_limbs_range_constraint_tail); + auto z_low_limbs_range_constraint_tail_shift = View(in.z_low_limbs_range_constraint_tail_shift); + auto z_high_limbs_range_constraint_tail = View(in.z_high_limbs_range_constraint_tail); + auto z_high_limbs_range_constraint_tail_shift = View(in.z_high_limbs_range_constraint_tail_shift); + auto accumulator_low_limbs_range_constraint_tail = View(in.accumulator_low_limbs_range_constraint_tail); + auto accumulator_low_limbs_range_constraint_tail_shift = + View(in.accumulator_low_limbs_range_constraint_tail_shift); + auto accumulator_high_limbs_range_constraint_tail = View(in.accumulator_high_limbs_range_constraint_tail); + auto accumulator_high_limbs_range_constraint_3_shift = View(in.accumulator_high_limbs_range_constraint_3_shift); + auto accumulator_high_limbs_range_constraint_4_shift = View(in.accumulator_high_limbs_range_constraint_4_shift); + auto quotient_low_limbs_range_constraint_tail = View(in.quotient_low_limbs_range_constraint_tail); + auto quotient_low_limbs_range_constraint_tail_shift = View(in.quotient_low_limbs_range_constraint_tail_shift); + auto quotient_high_limbs_range_constraint_tail = View(in.quotient_high_limbs_range_constraint_tail); + auto quotient_high_limbs_range_constraint_4_shift = View(in.quotient_high_limbs_range_constraint_4_shift); + auto x_lo_y_hi = View(in.x_lo_y_hi); + auto x_hi_z_1 = View(in.x_hi_z_1); + auto y_lo_z_2 = View(in.y_lo_z_2); + auto x_lo_y_hi_shift = View(in.x_lo_y_hi_shift); + auto x_hi_z_1_shift = View(in.x_hi_z_1_shift); + auto y_lo_z_2_shift = View(in.y_lo_z_2_shift); auto lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - // clang-format off - // Contribution 5 , Pα΅§,β‚€ limb decomposition - auto tmp_5 = - ((p_y_limb_0_range_constraint_0 + - p_y_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_y_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_y_limb_0); + // Contribution 5 , P_y lowest limb decomposition + auto tmp_5 = ((p_y_low_limbs_range_constraint_0 + p_y_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_y_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_y_low_limbs); tmp_5 *= lagrange_even_in_minicircuit; tmp_5 *= scaling_factor; std::get<4>(accumulators) += tmp_5; - // Contribution 6 , Pα΅§,₁ limb decomposition + // Contribution 6 , P_y second lowest limb decomposition auto tmp_6 = - ((p_y_limb_1_range_constraint_0 + - p_y_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_y_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_y_limb_1); + ((p_y_low_limbs_range_constraint_0_shift + p_y_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_y_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_y_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + p_y_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + p_y_low_limbs_shift); tmp_6 *= lagrange_even_in_minicircuit; tmp_6 *= scaling_factor; std::get<5>(accumulators) += tmp_6; - // Contribution 7 , Pα΅§,β‚‚ limb decomposition - auto tmp_7 = - ((p_y_limb_2_range_constraint_0 + - p_y_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_y_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_y_limb_2); + // Contribution 7 , P_y third limb decomposition + auto tmp_7 = ((p_y_high_limbs_range_constraint_0 + p_y_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_y_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_y_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_y_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_y_high_limbs); tmp_7 *= lagrange_even_in_minicircuit; tmp_7 *= scaling_factor; std::get<6>(accumulators) += tmp_7; - // Contribution 8 , Pα΅§,₃ limb decomposition + // Contribution 8 , P_y highest limb decomposition auto tmp_8 = - ((p_y_limb_3_range_constraint_0 + - p_y_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + - p_y_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_y_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - - p_y_limb_3); + ((p_y_high_limbs_range_constraint_0_shift + p_y_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_y_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_y_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + p_y_high_limbs_shift); tmp_8 *= lagrange_even_in_minicircuit; tmp_8 *= scaling_factor; std::get<7>(accumulators) += tmp_8; - // Contribution 9 , z₁,β‚€ limb decomposition - auto tmp_9 = - ((z_1_limb_0_range_constraint_0 + - z_1_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + - z_1_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - z_1_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_1_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_1_limb_0); + // Contribution 9 , z_1 low limb decomposition + auto tmp_9 = ((z_low_limbs_range_constraint_0 + z_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + z_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_low_limbs); tmp_9 *= lagrange_even_in_minicircuit; tmp_9 *= scaling_factor; std::get<8>(accumulators) += tmp_9; - // Contribution 10 , zβ‚‚,β‚€ limb decomposition - auto tmp_10 = - ((z_2_limb_0_range_constraint_0 + - z_2_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + - z_2_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - z_2_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_2_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_2_limb_0); + // Contribution 10 , z_2 low limb decomposition + auto tmp_10 = ((z_low_limbs_range_constraint_0_shift + z_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + z_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + z_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + z_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + z_low_limbs_shift); tmp_10 *= lagrange_even_in_minicircuit; tmp_10 *= scaling_factor; std::get<9>(accumulators) += tmp_10; - // Contribution 11 , z₁,₁ limb decomposition - auto tmp_11 = - ((z_1_limb_1_range_constraint_0 + - z_1_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + - z_1_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - z_1_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_1_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_1_limb_1); + // Contribution 11 , z_1 high limb decomposition + auto tmp_11 = ((z_high_limbs_range_constraint_0 + z_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + z_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + z_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + z_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + z_high_limbs); tmp_11 *= lagrange_even_in_minicircuit; tmp_11 *= scaling_factor; std::get<10>(accumulators) += tmp_11; - // Contribution 12 , zβ‚‚,₁ limb decomposition + // Contribution 12 , z_2 high limb decomposition auto tmp_12 = - ((z_2_limb_1_range_constraint_0 + - z_2_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + - z_2_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - z_2_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - z_2_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - z_2_limb_1); + ((z_high_limbs_range_constraint_0_shift + z_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + z_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + z_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + z_high_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + z_high_limbs_shift); tmp_12 *= lagrange_even_in_minicircuit; tmp_12 *= scaling_factor; std::get<11>(accumulators) += tmp_12; // Contributions that decompose 50, 52, 68 or 84 bit limbs used for computation into range-constrained chunks - // Contribution 13, Pβ‚“,β‚€ limb decomposition - auto tmp_13 = - ((p_x_limb_0_range_constraint_0 + - p_x_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_x_limb_0); + // Contribution 13, P_x lowest limb decomposition + auto tmp_13 = ((p_x_low_limbs_range_constraint_0 + p_x_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_x_low_limbs); tmp_13 *= lagrange_even_in_minicircuit; tmp_13 *= scaling_factor; std::get<12>(accumulators) += tmp_13; - // Contribution 14 , Pβ‚“,₁ limb decomposition + // Contribution 14 , P_x second lowest limb decomposition auto tmp_14 = - ((p_x_limb_1_range_constraint_0 + - p_x_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_x_limb_1); + ((p_x_low_limbs_range_constraint_0_shift + p_x_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_x_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_x_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + p_x_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + p_x_low_limbs_shift); tmp_14 *= lagrange_even_in_minicircuit; tmp_14 *= scaling_factor; std::get<13>(accumulators) += tmp_14; - // Contribution 15 , Pβ‚“,β‚‚ limb decomposition - auto tmp_15 = - ((p_x_limb_2_range_constraint_0 + - p_x_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - p_x_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - p_x_limb_2); + // Contribution 15 , P_x third limb decomposition + auto tmp_15 = ((p_x_high_limbs_range_constraint_0 + p_x_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + p_x_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + p_x_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + p_x_high_limbs); tmp_15 *= lagrange_even_in_minicircuit; tmp_15 *= scaling_factor; std::get<14>(accumulators) += tmp_15; - // Contribution 16 , Pβ‚“,₃ limb decomposition + // Contribution 16 , P_x highest limb decomposition auto tmp_16 = - ((p_x_limb_3_range_constraint_0 + - p_x_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + - p_x_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - p_x_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - - p_x_limb_3); + ((p_x_high_limbs_range_constraint_0_shift + p_x_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + p_x_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + p_x_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + p_x_high_limbs_shift); tmp_16 *= lagrange_even_in_minicircuit; tmp_16 *= scaling_factor; std::get<15>(accumulators) += tmp_16; - // Contribution 17 , Qβ‚€ limb decomposition + // Contribution 17 , quotient lowest limb decomposition auto tmp_17 = - ((quotient_limb_0_range_constraint_0 + - quotient_limb_0_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_limb_0_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_limb_0_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - quotient_limb_0_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - quotient_binary_limbs_0); + ((quotient_low_limbs_range_constraint_0 + quotient_low_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_low_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_low_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + quotient_low_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + quotient_low_binary_limbs); tmp_17 *= lagrange_even_in_minicircuit; tmp_17 *= scaling_factor; std::get<16>(accumulators) += tmp_17; - - // Contribution 18 , Q₁ limb decomposition - auto tmp_18 = - ((quotient_limb_1_range_constraint_0 + - quotient_limb_1_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_limb_1_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_limb_1_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - quotient_limb_1_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - quotient_binary_limbs_1); + // Contribution 18 , quotient second lowest limb decomposition + auto tmp_18 = ((quotient_low_limbs_range_constraint_0_shift + + quotient_low_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + quotient_low_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + quotient_low_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + quotient_low_limbs_range_constraint_4_shift * MICRO_LIMB_SHIFTx4) - + quotient_low_binary_limbs_shift); tmp_18 *= lagrange_even_in_minicircuit; tmp_18 *= scaling_factor; std::get<17>(accumulators) += tmp_18; - // Contribution 19 , Qβ‚‚ limb decomposition + // Contribution 19 , quotient second highest limb decomposition auto tmp_19 = - ((quotient_limb_2_range_constraint_0 + - quotient_limb_2_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_limb_2_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_limb_2_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - quotient_limb_2_range_constraint_4 * MICRO_LIMB_SHIFTx4) - - quotient_binary_limbs_2); + ((quotient_high_limbs_range_constraint_0 + quotient_high_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + quotient_high_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + quotient_high_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + quotient_high_limbs_range_constraint_4 * MICRO_LIMB_SHIFTx4) - + quotient_high_binary_limbs); tmp_19 *= lagrange_even_in_minicircuit; tmp_19 *= scaling_factor; std::get<18>(accumulators) += tmp_19; - - // Contribution 20 , Q₃ limb decomposition - auto tmp_20 = - ((quotient_limb_3_range_constraint_0 + - quotient_limb_3_range_constraint_1 * MICRO_LIMB_SHIFT + - quotient_limb_3_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - quotient_limb_3_range_constraint_3 * MICRO_LIMB_SHIFTx3) - - quotient_binary_limbs_3); + // Contribution 20 , quotient highest limb decomposition + auto tmp_20 = ((quotient_high_limbs_range_constraint_0_shift + + quotient_high_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + quotient_high_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + quotient_high_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3) - + quotient_high_binary_limbs_shift); tmp_20 *= lagrange_even_in_minicircuit; tmp_20 *= scaling_factor; std::get<19>(accumulators) += tmp_20; @@ -570,26 +452,24 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // accumulator and quotient. This is to save space and because these microlimbs are not used by their namesakes, // since top limbs in 254/6-bit values use one less microlimb for the top 50/52-bit limb auto tmp_21 = - ((relation_wide_limbs_lo_range_constraint_0 + - relation_wide_limbs_lo_range_constraint_1 * MICRO_LIMB_SHIFT + - relation_wide_limbs_lo_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - relation_wide_limbs_lo_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - relation_wide_limbs_lo_range_constraint_4 * MICRO_LIMB_SHIFTx4 + - relation_wide_limbs_lo_range_constraint_5 * MICRO_LIMB_SHIFTx5) - - relation_wide_limbs_lo); + ((relation_wide_limbs_range_constraint_0 + relation_wide_limbs_range_constraint_1 * MICRO_LIMB_SHIFT + + relation_wide_limbs_range_constraint_2 * MICRO_LIMB_SHIFTx2 + + relation_wide_limbs_range_constraint_3 * MICRO_LIMB_SHIFTx3 + + p_x_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + + accumulator_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - + relation_wide_limbs); tmp_21 *= lagrange_even_in_minicircuit; tmp_21 *= scaling_factor; std::get<20>(accumulators) += tmp_21; // Contribution 22 , decomposition of high relation limb - auto tmp_22 = - ((relation_wide_limbs_hi_range_constraint_0 + - relation_wide_limbs_hi_range_constraint_1 * MICRO_LIMB_SHIFT + - relation_wide_limbs_hi_range_constraint_2 * MICRO_LIMB_SHIFTx2 + - relation_wide_limbs_hi_range_constraint_3 * MICRO_LIMB_SHIFTx3 + - relation_wide_limbs_hi_range_constraint_4 * MICRO_LIMB_SHIFTx4 + - relation_wide_limbs_hi_range_constraint_5 * MICRO_LIMB_SHIFTx5) - - relation_wide_limbs_hi); + auto tmp_22 = ((relation_wide_limbs_range_constraint_0_shift + + relation_wide_limbs_range_constraint_1_shift * MICRO_LIMB_SHIFT + + relation_wide_limbs_range_constraint_2_shift * MICRO_LIMB_SHIFTx2 + + relation_wide_limbs_range_constraint_3_shift * MICRO_LIMB_SHIFTx3 + + p_y_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx4 + + quotient_high_limbs_range_constraint_tail_shift * MICRO_LIMB_SHIFTx5) - + relation_wide_limbs_shift); tmp_22 *= lagrange_even_in_minicircuit; tmp_22 *= scaling_factor; std::get<21>(accumulators) += tmp_22; @@ -598,84 +478,89 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // each limb to be more severely range constrained) // Contribution 23, range constrain the highest microlimb of lowest P.x limb to be 12 bits (68 % 14 = 12) - auto tmp_23 = p_x_limb_0_range_constraint_4 * SHIFT_12_TO_14 - p_x_limb_0_range_constraint_tail; + auto tmp_23 = p_x_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail; tmp_23 *= lagrange_even_in_minicircuit; tmp_23 *= scaling_factor; std::get<22>(accumulators) += tmp_23; // Contribution 24, range constrain the highest microlimb of second lowest P.x limb to be 12 bits - auto tmp_24 = p_x_limb_1_range_constraint_4 * SHIFT_12_TO_14 - p_x_limb_1_range_constraint_tail; + auto tmp_24 = + p_x_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_x_low_limbs_range_constraint_tail_shift; tmp_24 *= lagrange_even_in_minicircuit; tmp_24 *= scaling_factor; std::get<23>(accumulators) += tmp_24; // Contribution 25, range constrain the highest microlimb of second highest P.x limb to be 12 bits - auto tmp_25 = p_x_limb_2_range_constraint_4 * SHIFT_12_TO_14 - p_x_limb_2_range_constraint_tail; + auto tmp_25 = p_x_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_x_high_limbs_range_constraint_tail; tmp_25 *= lagrange_even_in_minicircuit; tmp_25 *= scaling_factor; std::get<24>(accumulators) += tmp_25; // Contribution 26, range constrain the highest microilmb of highest P.x limb to be 8 bits (50 % 14 = 8) - auto tmp_26 = p_x_limb_3_range_constraint_3 * SHIFT_8_TO_14 - p_x_limb_3_range_constraint_tail; + auto tmp_26 = + (p_x_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_x_high_limbs_range_constraint_4_shift); tmp_26 *= lagrange_even_in_minicircuit; tmp_26 *= scaling_factor; std::get<25>(accumulators) += tmp_26; // Contribution 27, range constrain the highest microlimb of lowest P.y limb to be 12 bits (68 % 14 = 12) - auto tmp_27 = p_y_limb_0_range_constraint_4 * SHIFT_12_TO_14 - p_y_limb_0_range_constraint_tail; + auto tmp_27 = p_y_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail; tmp_27 *= lagrange_even_in_minicircuit; tmp_27 *= scaling_factor; std::get<26>(accumulators) += tmp_27; // Contribution 28, range constrain the highest microlimb of second lowest P.y limb to be 12 bits (68 % 14 = 12) auto tmp_28 = - p_y_limb_1_range_constraint_4 * SHIFT_12_TO_14 - p_y_limb_1_range_constraint_tail; + p_y_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - p_y_low_limbs_range_constraint_tail_shift; tmp_28 *= lagrange_even_in_minicircuit; tmp_28 *= scaling_factor; std::get<27>(accumulators) += tmp_28; // Contribution 29, range constrain the highest microlimb of second highest P.y limb to be 12 bits (68 % 14 = // 12) - auto tmp_29 = p_y_limb_2_range_constraint_4 * SHIFT_12_TO_14 - p_y_limb_2_range_constraint_tail; + auto tmp_29 = p_y_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - p_y_high_limbs_range_constraint_tail; tmp_29 *= lagrange_even_in_minicircuit; tmp_29 *= scaling_factor; std::get<28>(accumulators) += tmp_29; // Contribution 30, range constrain the highest microlimb of highest P.y limb to be 8 bits (50 % 14 = 8) - auto tmp_30 = p_y_limb_3_range_constraint_3 * SHIFT_8_TO_14 - p_y_limb_3_range_constraint_tail; + auto tmp_30 = + (p_y_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - p_y_high_limbs_range_constraint_4_shift); tmp_30 *= lagrange_even_in_minicircuit; tmp_30 *= scaling_factor; std::get<29>(accumulators) += tmp_30; // Contribution 31, range constrain the highest microlimb of low z1 limb to be 12 bits (68 % 14 = 12) - auto tmp_31 = (z_1_limb_0_range_constraint_4 * SHIFT_12_TO_14 - z_1_limb_0_range_constraint_tail); + auto tmp_31 = (z_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail); tmp_31 *= lagrange_even_in_minicircuit; tmp_31 *= scaling_factor; std::get<30>(accumulators) += tmp_31; // Contribution 32, range constrain the highest microlimb of low z2 limb to be 12 bits (68 % 14 = 12) - auto tmp_32 = (z_2_limb_0_range_constraint_4 * SHIFT_12_TO_14 - z_2_limb_0_range_constraint_tail); + auto tmp_32 = (z_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - z_low_limbs_range_constraint_tail_shift); tmp_32 *= lagrange_even_in_minicircuit; tmp_32 *= scaling_factor; std::get<31>(accumulators) += tmp_32; // Contribution 33, range constrain the highest microlimb of high z1 limb to be 4 bits (60 % 14 = 12) - auto tmp_33 = (z_1_limb_1_range_constraint_4 * SHIFT_4_TO_14 - z_1_limb_1_range_constraint_tail); + auto tmp_33 = (z_high_limbs_range_constraint_4 * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail); tmp_33 *= lagrange_even_in_minicircuit; tmp_33 *= scaling_factor; std::get<32>(accumulators) += tmp_33; // Contribution 34, range constrain the highest microlimb of high z2 limb to be 4 bits (60 % 14 = 12) - auto tmp_34 = z_2_limb_1_range_constraint_4 * SHIFT_4_TO_14 - z_2_limb_1_range_constraint_tail; + auto tmp_34 = + (z_high_limbs_range_constraint_4_shift * SHIFT_4_TO_14 - z_high_limbs_range_constraint_tail_shift); tmp_34 *= lagrange_even_in_minicircuit; tmp_34 *= scaling_factor; std::get<33>(accumulators) += tmp_34; // Contribution 35, range constrain the highest microlimb of lowest current accumulator limb to be 12 bits (68 % // 14 = 12) - auto tmp_35 = accumulator_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_limb_0_range_constraint_tail; + auto tmp_35 = + (accumulator_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_low_limbs_range_constraint_tail); tmp_35 *= lagrange_even_in_minicircuit; tmp_35 *= scaling_factor; std::get<34>(accumulators) += tmp_35; @@ -683,7 +568,7 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contribution 36, range constrain the highest microlimb of second lowest current accumulator limb to be 12 // bits (68 % 14 = 12) auto tmp_36 = (accumulator_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - - accumulator_limb_1_range_constraint_tail); + accumulator_low_limbs_range_constraint_tail_shift); tmp_36 *= lagrange_even_in_minicircuit; tmp_36 *= scaling_factor; std::get<35>(accumulators) += tmp_36; @@ -691,28 +576,30 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contribution 37, range constrain the highest microlimb of second highest current accumulator limb to be 12 // bits (68 % 14 = 12) auto tmp_37 = - (accumulator_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_limb_2_range_constraint_tail); + (accumulator_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - accumulator_high_limbs_range_constraint_tail); tmp_37 *= lagrange_even_in_minicircuit; tmp_37 *= scaling_factor; std::get<36>(accumulators) += tmp_37; // Contribution 38, range constrain the highest microlimb of highest current accumulator limb to be 8 bits (50 % // 14 = 12) - auto tmp_38 = (accumulator_limb_3_range_constraint_3 * SHIFT_8_TO_14 - accumulator_limb_3_range_constraint_tail); + auto tmp_38 = (accumulator_high_limbs_range_constraint_3_shift * SHIFT_8_TO_14 - + accumulator_high_limbs_range_constraint_4_shift); tmp_38 *= lagrange_even_in_minicircuit; tmp_38 *= scaling_factor; std::get<37>(accumulators) += tmp_38; // Contribution 39, range constrain the highest microlimb of lowest quotient limb to be 12 bits (68 % 14 = 12) auto tmp_39 = - (quotient_limb_0_range_constraint_4 * SHIFT_12_TO_14 - quotient_limb_0_range_constraint_tail); + (quotient_low_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_low_limbs_range_constraint_tail); tmp_39 *= lagrange_even_in_minicircuit; tmp_39 *= scaling_factor; std::get<38>(accumulators) += tmp_39; // Contribution 40, range constrain the highest microlimb of second lowest quotient limb to be 12 bits (68 % 14 // = 12) - auto tmp_40 = (quotient_limb_1_range_constraint_4 * SHIFT_12_TO_14 - quotient_limb_1_range_constraint_tail); + auto tmp_40 = (quotient_low_limbs_range_constraint_4_shift * SHIFT_12_TO_14 - + quotient_low_limbs_range_constraint_tail_shift); tmp_40 *= lagrange_even_in_minicircuit; tmp_40 *= scaling_factor; std::get<39>(accumulators) += tmp_40; @@ -720,13 +607,14 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contribution 41, range constrain the highest microlimb of second highest quotient limb to be 12 bits (68 % 14 // = 12) auto tmp_41 = - (quotient_limb_2_range_constraint_4 * SHIFT_12_TO_14 - quotient_limb_2_range_constraint_tail); + (quotient_high_limbs_range_constraint_4 * SHIFT_12_TO_14 - quotient_high_limbs_range_constraint_tail); tmp_41 *= lagrange_even_in_minicircuit; tmp_41 *= scaling_factor; std::get<40>(accumulators) += tmp_41; // Contribution 42, range constrain the highest microlimb of highest quotient limb to be 10 bits (52 % 14 = 12) - auto tmp_42 = (quotient_limb_3_range_constraint_3 * SHIFT_10_TO_14 - quotient_limb_3_range_constraint_tail); + auto tmp_42 = (quotient_high_limbs_range_constraint_3_shift * SHIFT_10_TO_14 - + quotient_high_limbs_range_constraint_4_shift); tmp_42 *= lagrange_even_in_minicircuit; tmp_42 *= scaling_factor; std::get<41>(accumulators) += tmp_42; @@ -734,36 +622,36 @@ void TranslatorDecompositionRelationImpl::accumulate(ContainerOverSubrelatio // Contributions where we decompose initial EccOpQueue values into 68-bit limbs // Contribution 43, decompose x_lo - auto tmp_43 = (p_x_limb_0 + p_x_limb_1 * LIMB_SHIFT) - x_lo; + auto tmp_43 = (p_x_low_limbs + p_x_low_limbs_shift * LIMB_SHIFT) - x_lo_y_hi; tmp_43 *= lagrange_even_in_minicircuit; tmp_43 *= scaling_factor; std::get<42>(accumulators) += tmp_43; // Contribution 44, decompose x_hi - auto tmp_44 = (p_x_limb_2 + p_x_limb_3 * LIMB_SHIFT) - x_hi; + auto tmp_44 = (p_x_high_limbs + p_x_high_limbs_shift * LIMB_SHIFT) - x_hi_z_1; tmp_44 *= lagrange_even_in_minicircuit; tmp_44 *= scaling_factor; std::get<43>(accumulators) += tmp_44; // Contribution 45, decompose y_lo - auto tmp_45 = (p_y_limb_0 + p_y_limb_1 * LIMB_SHIFT) - y_lo; + auto tmp_45 = (p_y_low_limbs + p_y_low_limbs_shift * LIMB_SHIFT) - y_lo_z_2; tmp_45 *= lagrange_even_in_minicircuit; tmp_45 *= scaling_factor; std::get<44>(accumulators) += tmp_45; // Contribution 46, decompose y_hi - auto tmp_46 = (p_y_limb_2 + p_y_limb_3 * LIMB_SHIFT) - y_hi; + auto tmp_46 = (p_y_high_limbs + p_y_high_limbs_shift * LIMB_SHIFT) - x_lo_y_hi_shift; tmp_46 *= lagrange_even_in_minicircuit; tmp_46 *= scaling_factor; std::get<45>(accumulators) += tmp_46; // Contribution 47, decompose z1 - auto tmp_47 = (z_1_limb_0 + z_1_limb_1 * LIMB_SHIFT) - z_one; + auto tmp_47 = (z_low_limbs + z_high_limbs * LIMB_SHIFT) - x_hi_z_1_shift; tmp_47 *= lagrange_even_in_minicircuit; tmp_47 *= scaling_factor; std::get<46>(accumulators) += tmp_47; // Contribution 48, decompose z2 - auto tmp_48 = (z_2_limb_0 + z_2_limb_1 * LIMB_SHIFT) - z_two; + auto tmp_48 = (z_low_limbs_shift + z_high_limbs_shift * LIMB_SHIFT) - y_lo_z_2_shift; tmp_48 *= lagrange_even_in_minicircuit; tmp_48 *= scaling_factor; std::get<47>(accumulators) += tmp_48; diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp index a4bc7366d5ad..1a09fde34f1f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation_impl.hpp @@ -11,7 +11,6 @@ namespace bb { /** * @brief Expression for the computation of Translator accumulator in integers through 68-bit limbs and * native field (prime) limb - * * @details This relation is a part of system of relations that enforce a formula in non-native field (base field of * bn254 curve Fp (p - modulus of Fp)). We are trying to compute: * @@ -99,216 +98,185 @@ void TranslatorNonNativeFieldRelationImpl::accumulate(ContainerOverSubrelati -FF(curve::BN254::BaseField::modulus) }; - // Limbs of evaluation challenge x const auto& evaluation_input_x_0 = params.evaluation_input_x[0]; const auto& evaluation_input_x_1 = params.evaluation_input_x[1]; const auto& evaluation_input_x_2 = params.evaluation_input_x[2]; const auto& evaluation_input_x_3 = params.evaluation_input_x[3]; const auto& evaluation_input_x_4 = params.evaluation_input_x[4]; + // for j < 4, v_i_j is the j-th limb of v^{1+i} + // v_i_4 is v^{1+i} in the native field + const auto& v_0_0 = params.batching_challenge_v[0][0]; + const auto& v_0_1 = params.batching_challenge_v[0][1]; + const auto& v_0_2 = params.batching_challenge_v[0][2]; + const auto& v_0_3 = params.batching_challenge_v[0][3]; + const auto& v_0_4 = params.batching_challenge_v[0][4]; + const auto& v_1_0 = params.batching_challenge_v[1][0]; + const auto& v_1_1 = params.batching_challenge_v[1][1]; + const auto& v_1_2 = params.batching_challenge_v[1][2]; + const auto& v_1_3 = params.batching_challenge_v[1][3]; + const auto& v_1_4 = params.batching_challenge_v[1][4]; + const auto& v_2_0 = params.batching_challenge_v[2][0]; + const auto& v_2_1 = params.batching_challenge_v[2][1]; + const auto& v_2_2 = params.batching_challenge_v[2][2]; + const auto& v_2_3 = params.batching_challenge_v[2][3]; + const auto& v_2_4 = params.batching_challenge_v[2][4]; + const auto& v_3_0 = params.batching_challenge_v[3][0]; + const auto& v_3_1 = params.batching_challenge_v[3][1]; + const auto& v_3_2 = params.batching_challenge_v[3][2]; + const auto& v_3_3 = params.batching_challenge_v[3][3]; + const auto& v_3_4 = params.batching_challenge_v[3][4]; - // Limbs of batching challenge v - const auto& v_0 = params.batching_challenge_v[0][0]; - const auto& v_1 = params.batching_challenge_v[0][1]; - const auto& v_2 = params.batching_challenge_v[0][2]; - const auto& v_3 = params.batching_challenge_v[0][3]; - const auto& v_4 = params.batching_challenge_v[0][4]; - - // Limbs of batching challenge vΒ² - const auto& v_sqr_0 = params.batching_challenge_v[1][0]; - const auto& v_sqr_1 = params.batching_challenge_v[1][1]; - const auto& v_sqr_2 = params.batching_challenge_v[1][2]; - const auto& v_sqr_3 = params.batching_challenge_v[1][3]; - const auto& v_sqr_4 = params.batching_challenge_v[1][4]; - - // Limbs of batching challenge vΒ³ - const auto& v_cube_0 = params.batching_challenge_v[2][0]; - const auto& v_cube_1 = params.batching_challenge_v[2][1]; - const auto& v_cube_2 = params.batching_challenge_v[2][2]; - const auto& v_cube_3 = params.batching_challenge_v[2][3]; - const auto& v_cube_4 = params.batching_challenge_v[2][4]; - - // Limbs of batching challenge v⁴ - const auto& v_quad_0 = params.batching_challenge_v[3][0]; - const auto& v_quad_1 = params.batching_challenge_v[3][1]; - const auto& v_quad_2 = params.batching_challenge_v[3][2]; - const auto& v_quad_3 = params.batching_challenge_v[3][3]; - const auto& v_quad_4 = params.batching_challenge_v[3][4]; - - // Fetch witness values - // Pβ‚“ = (Pβ‚“,₃ || Pβ‚“,β‚‚ || Pβ‚“,₁ || Pβ‚“,β‚€) - // Pα΅§ = (Pα΅§,₃ || Pα΅§,β‚‚ || Pα΅§,₁ || Pα΅§,β‚€) - // z₁ = (z₁,₁ || z₁,β‚€) - // zβ‚‚ = (zβ‚‚,₁ || zβ‚‚,β‚€) - // Q = (q₃ || qβ‚‚ || q₁ || qβ‚€) const auto& op = View(in.op); - const auto& p_x_limb_0 = View(in.p_x_low_limbs); - const auto& p_y_limb_0 = View(in.p_y_low_limbs); - const auto& p_x_limb_2 = View(in.p_x_high_limbs); - const auto& p_y_limb_2 = View(in.p_y_high_limbs); + const auto& p_x_low_limbs = View(in.p_x_low_limbs); + const auto& p_y_low_limbs = View(in.p_y_low_limbs); + const auto& p_x_high_limbs = View(in.p_x_high_limbs); + const auto& p_y_high_limbs = View(in.p_y_high_limbs); const auto& accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); const auto& accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); const auto& accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); const auto& accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); - const auto& z_1_limb_0 = View(in.z_low_limbs); - const auto& z_1_limb_1 = View(in.z_high_limbs); - const auto& quotient_binary_limbs_0 = View(in.quotient_low_binary_limbs); - const auto& quotient_binary_limbs_1 = View(in.quotient_high_binary_limbs); - const auto& p_x_limb_1 = View(in.p_x_low_limbs_shift); - const auto& p_y_limb_1 = View(in.p_y_low_limbs_shift); - const auto& p_x_limb_3 = View(in.p_x_high_limbs_shift); - const auto& p_y_limb_3 = View(in.p_y_high_limbs_shift); - const auto& prev_accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0_shift); - const auto& prev_accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1_shift); - const auto& prev_accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2_shift); - const auto& prev_accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3_shift); - const auto& z_2_limb_0 = View(in.z_low_limbs_shift); - const auto& z_2_limb_1 = View(in.z_high_limbs_shift); - const auto& quotient_binary_limbs_2 = View(in.quotient_low_binary_limbs_shift); - const auto& quotient_binary_limbs_3 = View(in.quotient_high_binary_limbs_shift); - const auto& relation_wide_limbs_lo = View(in.relation_wide_limbs); - const auto& relation_wide_limbs_hi = View(in.relation_wide_limbs_shift); + const auto& z_low_limbs = View(in.z_low_limbs); + const auto& z_high_limbs = View(in.z_high_limbs); + const auto& quotient_low_binary_limbs = View(in.quotient_low_binary_limbs); + const auto& quotient_high_binary_limbs = View(in.quotient_high_binary_limbs); + const auto& p_x_low_limbs_shift = View(in.p_x_low_limbs_shift); + const auto& p_y_low_limbs_shift = View(in.p_y_low_limbs_shift); + const auto& p_x_high_limbs_shift = View(in.p_x_high_limbs_shift); + const auto& p_y_high_limbs_shift = View(in.p_y_high_limbs_shift); + const auto& accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); + const auto& accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); + const auto& accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); + const auto& accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); + const auto& z_low_limbs_shift = View(in.z_low_limbs_shift); + const auto& z_high_limbs_shift = View(in.z_high_limbs_shift); + const auto& quotient_low_binary_limbs_shift = View(in.quotient_low_binary_limbs_shift); + const auto& quotient_high_binary_limbs_shift = View(in.quotient_high_binary_limbs_shift); + const auto& relation_wide_limbs = View(in.relation_wide_limbs); + const auto& relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); const auto& lagrange_even_in_minicircuit = View(in.lagrange_even_in_minicircuit); - /** - * Contribution (1): Subrelation 1 - Lower Mod 2¹³⁢ Check - * - * Proves that the accumulation formula holds for the lower 136 bits (limbs 0 and 1). - * Computes: Tβ‚€ + 2⁢⁸·T₁ - 2¹³⁢·c_lo = 0 - * where Tβ‚€ and T₁ are linear combinations of limb-0 and limb-1 products respectively, - * and c_lo is the carry to the higher 136 bits. - */ + // Contribution (1) Computing the mod 2²⁷² relation over lower 136 bits // clang-format off - // Tβ‚€: Limb 0 contribution (all products contributing at weight 2⁰) - auto tmp = prev_accumulators_binary_limbs_0 * evaluation_input_x_0 + // the index-0 limb + auto tmp = accumulators_binary_limbs_0_shift * evaluation_input_x_0 + op - + p_x_limb_0 * v_0 - + p_y_limb_0 * v_sqr_0 - + z_1_limb_0 * v_cube_0 - + z_2_limb_0 * v_quad_0 - + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[0] + + p_x_low_limbs * v_0_0 + + p_y_low_limbs * v_1_0 + + z_low_limbs * v_2_0 + + z_low_limbs_shift * v_3_0 + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0; - // T₁: Limb 1 contribution (all cross-products contributing at weight 2⁢⁸) - tmp += (prev_accumulators_binary_limbs_1 * evaluation_input_x_0 - + prev_accumulators_binary_limbs_0 * evaluation_input_x_1 - + p_x_limb_0 * v_1 - + p_x_limb_1 * v_0 - + p_y_limb_0 * v_sqr_1 - + p_y_limb_1 * v_sqr_0 - + z_1_limb_0 * v_cube_1 - + z_1_limb_1 * v_cube_0 - + z_2_limb_0 * v_quad_1 - + z_2_limb_1 * v_quad_0 - + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[1] - + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[0] + // the index-1 limb + tmp += (accumulators_binary_limbs_1_shift * evaluation_input_x_0 + + accumulators_binary_limbs_0_shift * evaluation_input_x_1 + + p_x_low_limbs * v_0_1 + + p_x_low_limbs_shift * v_0_0 + + p_y_low_limbs * v_1_1 + + p_y_low_limbs_shift * v_1_0 + + z_low_limbs * v_2_1 + + z_high_limbs * v_2_0 + + z_low_limbs_shift * v_3_1 + + z_high_limbs_shift * v_3_0 + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_1) * shift ; // clang-format on - // Subtract 2¹³⁢·c_lo: if the result is zero, lower 136 bits are correct - tmp -= relation_wide_limbs_lo * shiftx2; + // subtract large value; vanishing shows the desired relation holds on low 136-bit limb + tmp -= relation_wide_limbs * shiftx2; tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<0>(accumulators) += tmp; - /** - * Contribution (2): Subrelation 2 - Higher Mod 2¹³⁢ Check - * - * Proves that the accumulation formula holds for the higher 136 bits (limbs 2 and 3). - * Computes: Tβ‚‚ + 2⁢⁸·T₃ - 2¹³⁢·c_hi = 0 - * where Tβ‚‚ includes the carry c_lo from subrelation 1, T₃ contains limb-3 products, - * and c_hi is the overflow carry (should be range-constrained to ensure soundness). - * Together with Subrelation 1, this proves the relation holds mod 2²⁷². - */ + // Contribution (2) Computing the 2²⁷² relation over higher 136 bits + // why declare another temporary? // clang-format off - // Tβ‚‚: Limb 2 contribution (with carry from lower 136 bits) - tmp = relation_wide_limbs_lo - + prev_accumulators_binary_limbs_2 * evaluation_input_x_0 - + prev_accumulators_binary_limbs_1 * evaluation_input_x_1 - + prev_accumulators_binary_limbs_0 * evaluation_input_x_2 - + p_x_limb_2 * v_0 - + p_x_limb_1 * v_1 - + p_x_limb_0 * v_2 - + p_y_limb_2 * v_sqr_0 - + p_y_limb_1 * v_sqr_1 - + p_y_limb_0 * v_sqr_2 - + z_1_limb_1 * v_cube_1 - + z_1_limb_0 * v_cube_2 - + z_2_limb_1 * v_quad_1 - + z_2_limb_0 * v_quad_2 - + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[0] - + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[1] - + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[2] + // the index-2 limb, with a carry from the previous calculation + tmp = relation_wide_limbs + + accumulators_binary_limbs_2_shift * evaluation_input_x_0 + + accumulators_binary_limbs_1_shift * evaluation_input_x_1 + + accumulators_binary_limbs_0_shift * evaluation_input_x_2 + + p_x_high_limbs * v_0_0 + + p_x_low_limbs_shift * v_0_1 + + p_x_low_limbs * v_0_2 + + p_y_high_limbs * v_1_0 + + p_y_low_limbs_shift * v_1_1 + + p_y_low_limbs * v_1_2 + + z_high_limbs * v_2_1 + + z_low_limbs * v_2_2 + + z_high_limbs_shift * v_3_1 + + z_low_limbs_shift * v_3_2 + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] - accumulators_binary_limbs_2; - // T₃: Limb 3 contribution (all cross-products contributing at weight 2²⁰⁴) - tmp += (prev_accumulators_binary_limbs_3 * evaluation_input_x_0 - + prev_accumulators_binary_limbs_2 * evaluation_input_x_1 - + prev_accumulators_binary_limbs_1 * evaluation_input_x_2 - + prev_accumulators_binary_limbs_0 * evaluation_input_x_3 - + p_x_limb_3 * v_0 - + p_x_limb_2 * v_1 - + p_x_limb_1 * v_2 - + p_x_limb_0 * v_3 - + p_y_limb_3 * v_sqr_0 - + p_y_limb_2 * v_sqr_1 - + p_y_limb_1 * v_sqr_2 - + p_y_limb_0 * v_sqr_3 - + z_1_limb_1 * v_cube_2 - + z_1_limb_0 * v_cube_3 - + z_2_limb_1 * v_quad_2 - + z_2_limb_0 * v_quad_3 - + quotient_binary_limbs_3 * NEGATIVE_MODULUS_LIMBS[0] - + quotient_binary_limbs_2 * NEGATIVE_MODULUS_LIMBS[1] - + quotient_binary_limbs_1 * NEGATIVE_MODULUS_LIMBS[2] - + quotient_binary_limbs_0 * NEGATIVE_MODULUS_LIMBS[3] + // the index-2 limb + tmp += (accumulators_binary_limbs_3_shift * evaluation_input_x_0 + + accumulators_binary_limbs_2_shift * evaluation_input_x_1 + + accumulators_binary_limbs_1_shift * evaluation_input_x_2 + + accumulators_binary_limbs_0_shift * evaluation_input_x_3 + + p_x_high_limbs_shift * v_0_0 + + p_x_high_limbs * v_0_1 + + p_x_low_limbs_shift * v_0_2 + + p_x_low_limbs * v_0_3 + + p_y_high_limbs_shift * v_1_0 + + p_y_high_limbs * v_1_1 + + p_y_low_limbs_shift * v_1_2 + + p_y_low_limbs * v_1_3 + + z_high_limbs * v_2_2 + + z_low_limbs * v_2_3 + + z_high_limbs_shift * v_3_2 + + z_low_limbs_shift * v_3_3 + + quotient_high_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[2] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[3] - accumulators_binary_limbs_3) * shift; // clang-format on - // Subtract 2¹³⁢·c_hi: if the result is zero, higher 136 bits are correct - tmp -= relation_wide_limbs_hi * shiftx2; + // subtract large value; vanishing shows the desired relation holds on high 136-bit limb + tmp -= relation_wide_limbs_shift * shiftx2; tmp *= lagrange_even_in_minicircuit * op; tmp *= scaling_factor; std::get<1>(accumulators) += tmp; - // Helper functions to reconstruct field elements from limbs const auto reconstruct_from_two = [](const auto& l0, const auto& l1) { return l0 + l1 * shift; }; const auto reconstruct_from_four = [](const auto& l0, const auto& l1, const auto& l2, const auto& l3) { return l0 + l1 * shift + l2 * shiftx2 + l3 * shiftx3; }; - // Reconstruct native 𝔽ᡣ representations from binary limbs - auto reconstructed_p_x = reconstruct_from_four(p_x_limb_0, p_x_limb_1, p_x_limb_2, p_x_limb_3); - auto reconstructed_p_y = reconstruct_from_four(p_y_limb_0, p_y_limb_1, p_y_limb_2, p_y_limb_3); - auto reconstructed_previous_accumulator = reconstruct_from_four(prev_accumulators_binary_limbs_0, - prev_accumulators_binary_limbs_1, - prev_accumulators_binary_limbs_2, - prev_accumulators_binary_limbs_3); + // Reconstructing native versions of values + auto reconstructed_p_x = + reconstruct_from_four(p_x_low_limbs, p_x_low_limbs_shift, p_x_high_limbs, p_x_high_limbs_shift); + auto reconstructed_p_y = + reconstruct_from_four(p_y_low_limbs, p_y_low_limbs_shift, p_y_high_limbs, p_y_high_limbs_shift); + auto reconstructed_previous_accumulator = reconstruct_from_four(accumulators_binary_limbs_0_shift, + accumulators_binary_limbs_1_shift, + accumulators_binary_limbs_2_shift, + accumulators_binary_limbs_3_shift); auto reconstructed_current_accumulator = reconstruct_from_four(accumulators_binary_limbs_0, accumulators_binary_limbs_1, accumulators_binary_limbs_2, accumulators_binary_limbs_3); - auto reconstructed_z1 = reconstruct_from_two(z_1_limb_0, z_1_limb_1); - auto reconstructed_z2 = reconstruct_from_two(z_2_limb_0, z_2_limb_1); - auto reconstructed_quotient = reconstruct_from_four( - quotient_binary_limbs_0, quotient_binary_limbs_1, quotient_binary_limbs_2, quotient_binary_limbs_3); + auto reconstructed_z1 = reconstruct_from_two(z_low_limbs, z_high_limbs); + auto reconstructed_z2 = reconstruct_from_two(z_low_limbs_shift, z_high_limbs_shift); + auto reconstructed_quotient = reconstruct_from_four(quotient_low_binary_limbs, + quotient_low_binary_limbs_shift, + quotient_high_binary_limbs, + quotient_high_binary_limbs_shift); - /** - * Contribution (3): Subrelation 3 - Native Field Check - * - * Proves the accumulation formula holds when computed directly in 𝔽ᡣ. - * Uses reconstructed native field representations (tilde notation in docs). - * Combined with mod 2²⁷² checks (Subrelations 1 & 2), this proves the relation - * holds in integers via Chinese Remainder Theorem, which implies it holds mod q. - */ + // Contribution (3). Evaluating integer relation over native field // clang-format off - // Compute accumulation formula using native 𝔽ᡣ arithmetic (limb index 4) + // the native limb index is 4 tmp = reconstructed_previous_accumulator * evaluation_input_x_4 + op - + reconstructed_p_x * v_4 - + reconstructed_p_y * v_sqr_4 - + reconstructed_z1 * v_cube_4 - + reconstructed_z2 * v_quad_4 + + reconstructed_p_x * v_0_4 + + reconstructed_p_y * v_1_4 + + reconstructed_z1 * v_2_4 + + reconstructed_z2 * v_3_4 + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator; // clang-format on diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index 8f3bf9f1907e..a9bb94292d5d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -96,7 +96,7 @@ void TranslatorProvingKey::compute_translator_range_constraint_ordered_polynomia // ordered_range_constraint_i up to the given capacity and the remaining elements to the last range constraint. // Sorting is done by converting the elements to uint for efficiency. auto ordering_function = [&](size_t i) { - const auto& group = to_be_interleaved_groups[i]; + auto group = to_be_interleaved_groups[i]; std::vector ordered_vectors_uint(dyadic_circuit_size_without_masking); // Calculate how much space there is for values from the group polynomials given we also need to append the @@ -193,12 +193,13 @@ void TranslatorProvingKey::split_interleaved_random_coefficients_to_ordered() const size_t num_random_values_per_ordered = total_num_random_values / num_ordered_polynomials; const size_t remaining_random_values = total_num_random_values % num_ordered_polynomials; - std::array random_values = {}; + std::array + random_values = {}; // Add the random values from all interleaved polynomials to an array parallel_for(Flavor::NUM_INTERLEAVED_WIRES, [&](size_t i) { size_t idx = i * num_random_values_per_interleaved; - const auto& current_interleaved = interleaved[i]; + auto current_interleaved = interleaved[i]; for (size_t j = dyadic_circuit_size_without_masking; j < current_interleaved.end_index(); j++) { random_values[idx] = current_interleaved.at(j); idx++; From 5388417849f82963de5fb07c795d9d4a86ff9fb6 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Sat, 20 Dec 2025 13:07:22 +0000 Subject: [PATCH 20/29] fixes. --- .../src/barretenberg/translator_vm/README.md | 162 +++++++++--------- 1 file changed, 79 insertions(+), 83 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 9bf40f6c3b24..fc1b08a80ce2 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -74,29 +74,35 @@ Specifically, for each accumulation step (every 2 rows), prove: $$\text{acc}_{\text{curr}} = \text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 \pmod{q}$$ -**Method:** Since we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic (as $q \neq r$), we use non-native field arithmetic. Similar to the technique in [bigfield](../stdlib/primitives/bigfield/README.md), we prove the equation holds in integers: +Note that we process the `EccOpQueue` in reverse order while computing the accumulator in steps: -$$\text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \text{quotient} \cdot q - \text{acc}_{\text{curr}} = 0$$ +$$ +\begin{aligned} +\textcolor{orange}{\text{acc}_0} &= \textcolor{lightgrey}{0} \cdot x + \text{op}_{n-1} + P_x^{(n-1)} \cdot v + P_y^{(n-1)} \cdot v^2 + z_1^{(n-1)} \cdot v^3 + z_2^{(n-1)} \cdot v^4 \\ +\textcolor{lightgreen}{\text{acc}_1} &= \textcolor{orange}{\text{acc}_0} \cdot x + \text{op}_{n-2} + P_x^{(n-2)} \cdot v + P_y^{(n-2)} \cdot v^2 + z_1^{(n-2)} \cdot v^3 + z_2^{(n-2)} \cdot v^4 \\ +\textcolor{skyblue}{\text{acc}_2} &= \textcolor{lightgreen}{\text{acc}_1} \cdot x + \text{op}_{n-3} + P_x^{(n-3)} \cdot v + P_y^{(n-3)} \cdot v^2 + z_1^{(n-3)} \cdot v^3 + z_2^{(n-3)} \cdot v^4 \\ +&\ \ \vdots \\ +\textcolor{brown}{\text{acc}_{n-2}} &= \textcolor{grey}{\text{acc}_{n-3}} \cdot x + \text{op}_1 + P_x^{(1)} \cdot v + P_y^{(1)} \cdot v^2 + z_1^{(1)} \cdot v^3 + z_2^{(1)} \cdot v^4 \\ +\textcolor{violet}{\text{acc}_{n-1}} &= \textcolor{brown}{\text{acc}_{n-2}} \cdot x + \text{op}_0 + P_x^{(0)} \cdot v + P_y^{(0)} \cdot v^2 + z_1^{(0)} \cdot v^3 + z_2^{(0)} \cdot v^4 \\ +\end{aligned} +$$ -We verify this by proving the equation holds: +The final accumulator value $\textcolor{violet}{\text{acc}_{n-1}}$ is what we need to verify against the ECCVM's output. +Note that the "previous" accumulator in the _last_ step must be 0. -1. **modulo $2^{272}$** (via 68-bit limb arithmetic split into two 136-bit checks) -2. **modulo $r$** (natively in $\mathbb{F}_r$) -3. with **range constraints** on all limbs (prevents overflow/underflow) +**Method:** Since we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic (as $q \neq r$, and in fact $q > r$), we use non-native field arithmetic. Similar to the technique in [bigfield](../stdlib/primitives/bigfield/README.md), we prove the equation holds in integers: -By the Chinese Remainder Theorem, since $2^{272} \cdot r > 2^{514}$ exceeds the maximum possible value, the equation must hold in integers, and thus modulo $q$. +$$\text{acc}_{\text{prev}} \cdot x + \text{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4 - \text{quotient} \cdot q - \text{acc}_{\text{curr}} = 0$$ -## Architecture and Constants +We verify this by proving the equation holds: -#### Circuit Size Parameters +1. modulo $2^{272}$ (via 68-bit limb arithmetic split into two 136-bit checks) +2. modulo $r$ (natively in $\mathbb{F}_r$) +3. with range constraints on all limbs (prevents overflow/underflow) -```cpp -CONST_TRANSLATOR_MINI_CIRCUIT_LOG_SIZE = 13 // Mini-circuit: 2^13 = 8,192 rows (logβ‚‚ of size) -INTERLEAVING_GROUP_SIZE = 16 // Interleaving factor -CONST_TRANSLATOR_LOG_N = 13 + 4 = 17 // Full circuit: 2^17 = 131,072 rows (logβ‚‚ of size) -``` +By the Chinese Remainder Theorem, since $2^{272} \cdot r > 2^{514}$ exceeds the maximum possible value, the equation must hold in integers, and thus modulo $q$. -**Why interleaving?** Without interleaving, checking ~64 microlimb columns simultaneously would create a degree-65 polynomial in the permutation argument, making sumcheck impractical. Interleaving reduces this to degree 6-7 by spreading the checks across 16 segments (see [Interleaving section](#interleaving-the-key-optimization)). +### Constants #### Field Moduli @@ -110,7 +116,7 @@ r = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 β‰ˆ 2^254 ``` -**Key observation:** $q \neq r$ (they differ by $\approx 2^{47}$), so we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic. +**Key observation:** $q > r$ (they differ by $\approx 2^{47}$), so we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic. #### Limb Decomposition Constants @@ -131,18 +137,10 @@ NUM_MICRO_LIMBS = 6 // 68 / 14 β‰ˆ 5, plus 1 for tail #### Opcode Values -```cpp -Valid opcodes: {0, 1, 2, 3, 4, 8} -``` - -Encoding EC operations: - -- `0`: No-op / NULL -- `1`: Add -- `2`: Mul (scalar multiplication) -- `3`: Equality check -- `4`: Reset accumulator -- `8`: [Special operation] +- `0`: No-op +- `3`: Equality check and reset accumulator +- `4`: Scalar multiplication +- `8`: Point addition #### Range Constraint Constants @@ -155,38 +153,40 @@ SORTED_STEPS_COUNT = 2^14 / 3 + 1 // Number of "step" values inserted Each microlimb must be $≀ 2^{14} - 1 = 16383$. ---- - ## Witness Trace Structure -The Translator circuit has **81 witness columns**, organized into: +The Translator circuit has 81 witness columns, organized into: -- **4 columns**: EccOpQueue transcript (op, P.x, P.y, z₁, zβ‚‚ encoded across 2 rows) -- **13 columns**: Limb decompositions (68-bit limbs for non-native arithmetic) -- **64 columns**: Microlimb decompositions (14-bit microlimbs for range constraints) +- 4 columns: `EccOpQueue` transcript ($\texttt{op}, P_x, P_y, z_1, z_2$ encoded across 2 rows) +- 13 columns: Limb decompositions (68-bit limbs for non-native arithmetic) +- 64 columns: Microlimb decompositions (14-bit microlimbs for range constraints) -The circuit operates on a **2-row cycle structure**. Each EccOpQueue entry occupies exactly 2 rows: +The circuit operates on a 2-row cycle structure. Each `EccOpQueue` entry occupies exactly 2 rows: -- **Row $2i$ (Even rows)**: **Computation rows** where the non-native field relation is actively checked -- **Row $2i+1$ (Odd rows)**: **Data storage rows** that hold values accessed by the next even row via shifts +- Row $2i$ (Even rows): Computation rows where the non-native field relation is actively checked +- Row $2i+1$ (Odd rows): Data storage rows that hold values accessed via shifts -This architecture exists because of how polynomial commitments work in the KZG scheme: the "shifted" polynomial at index $i$ evaluates to the polynomial at index $i+1$. Thus: +While enforcing constraints on the even rows, we can access values from the "next" odd row using shifted column polynomials. +As hinted earlier, the "previous" accumulator value needed for computation is stored at odd row $(2i+1)$. +This value becomes the "current" accumulator for the next even row $(2i+2)$: -- Even row $2i$ performs computation using "current" values from its own row -- Even row $2i$ accesses "previous" values from odd row $2i+1$ via shift columns -- Odd row $2i+1$ stores the data that will become "previous" for the next computation at row $2i+2$ +| Op index | $0$ | $1$ | $\quad \dots \quad$ | $(n-2)$ | $(n-1)$ | +| -------------------- | -------------------------------------- | ------------------------------------- | ------------------- | ---------------------------------------- | ------------------------------------ | +| Current accumulator | $\textcolor{violet}{\text{acc}_{n-1}}$ | $\textcolor{brown}{\text{acc}_{n-2}}$ | $\quad \dots \quad$ | $\textcolor{lightgreen}{\text{acc}_{1}}$ | $\textcolor{orange}{\text{acc}_{0}}$ | +| Previous accumulator | $\textcolor{brown}{\text{acc}_{n-2}}$ | $\textcolor{grey}{\text{acc}_{n-3}}$ | $\quad \dots \quad$ | $\textcolor{orange}{\text{acc}_{0}}$ | $0$ | +| | | | | | | #### 1. EccOpQueue Transcript Columns (4 columns) These columns directly represent the EccOpQueue transcript: -| Column | Even Row (2i) | Odd Row (2i+1) | Description | -| ----------- | --------------------------------- | ---------------------------- | --------------------------------------------- | -| `OP` | $\texttt{op} \in \{0,1,2,3,4,8\}$ | 0 (no-op) | Opcode (the type of elliptic curve operation) | -| `X_LO_Y_HI` | $P_{x,\text{lo}}$ (136 bits) | $P_{y,\text{hi}}$ (118 bits) | Low 136 bits of P.x and High 118 bits of P.y | -| `X_HI_Z_1` | $P_{x,\text{hi}}$ (118 bits) | $z_1$ (128 bits) | High 118 bits of P.x and first scalar | -| `Y_LO_Z_2` | $P_{y,\text{lo}}$ (136 bits) | $z_2$ (128 bits) | Low 136 bits of P.y and second scalar | -| | | | | +| Column | Even Row $(2i)$ | Odd Row $(2i+1)$ | Description | +| ----------- | -------------------------------- | ---------------------------- | ------------------------------------------------------------------ | +| `OP` | $\texttt{op} \in \{0, 3, 4, 8\}$ | 0 (no-op) | Opcode (the type of elliptic curve operation) | +| `X_LO_Y_HI` | $P_{x,\text{lo}}$ (136 bits) | $P_{y,\text{hi}}$ (118 bits) | Low 136 bits of $x$-coordinate and high 118 bits of $y$-coordinate | +| `X_HI_Z_1` | $P_{x,\text{hi}}$ (118 bits) | $z_1$ (128 bits) | High 118 bits of $x$-coordinate and first scalar | +| `Y_LO_Z_2` | $P_{y,\text{lo}}$ (136 bits) | $z_2$ (128 bits) | Low 136 bits of $y$-coordinate and second scalar | +| | | | | **Encoding scheme**: Point coordinates $P_x$ and $P_y$ are each 254 bits, split as: @@ -197,12 +197,12 @@ These columns directly represent the EccOpQueue transcript: These columns store finer-grained limb decompositions for non-native arithmetic: -| Column Group | Even Row (2i) | Odd Row (2i+1) | Bits | Purpose | +| Column Group | Even Row $(2i)$ | Odd Row $(2i+1)$ | Bits | Purpose | | ----------------------------- | --------------------- | --------------------- | ------ | ---------------------------------------- | -| `P_X_LOW_LIMBS` | $P_{x,0}^{\text{lo}}$ | $P_{x,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{x,\text{lo}}$ | -| `P_X_HIGH_LIMBS` | $P_{x,0}^{\text{hi}}$ | $P_{x,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{x,\text{hi}}$ | -| `P_Y_LOW_LIMBS` | $P_{y,0}^{\text{lo}}$ | $P_{y,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{y,\text{lo}}$ | -| `P_Y_HIGH_LIMBS` | $P_{y,0}^{\text{hi}}$ | $P_{y,1}^{\text{hi}}$ | 68, 50 | Limbs 0 & 1 of $P_{y,\text{hi}}$ | +| `P_X_LOW_LIMBS` | $P_{x,0}^{\text{lo}}$ | $P_{x,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{x}$ | +| `P_X_HIGH_LIMBS` | $P_{x,0}^{\text{hi}}$ | $P_{x,1}^{\text{hi}}$ | 68, 50 | Limbs 2 & 3 of $P_{x}$ | +| `P_Y_LOW_LIMBS` | $P_{y,0}^{\text{lo}}$ | $P_{y,1}^{\text{lo}}$ | 68 | Limbs 0 & 1 of $P_{y}$ | +| `P_Y_HIGH_LIMBS` | $P_{y,0}^{\text{hi}}$ | $P_{y,1}^{\text{hi}}$ | 68, 50 | Limbs 2 & 3 of $P_{y}$ | | `Z_LOW_LIMBS` | $z_{1,0}$ | $z_{2,0}$ | 68 | Low limbs of $z_1$ and $z_2$ | | `Z_HIGH_LIMBS` | $z_{1,1}$ | $z_{2,1}$ | 60 | High limbs of $z_1$ and $z_2$ | | `ACCUMULATORS_BINARY_LIMBS_0` | $a_0^{\text{curr}}$ | $a_0^{\text{prev}}$ | 68 | Limb 0 of current/previous accumulator | @@ -221,9 +221,9 @@ These columns store finer-grained limb decompositions for non-native arithmetic: #### 3. Range Constraint Microlimb Columns (64 columns) -Each limb is further decomposed into **14-bit microlimbs** for range checking. Each 68-bit limb has 5 microlimbs (14 bits each) plus a "tail" microlimb that enforces tight range constraints. The columns are organized as follows: +Each limb is further decomposed into 14-bit microlimbs for range checking. Each 68-bit limb has 5 microlimbs (14 bits each) plus a "tail" microlimb that enforces tight range constraints. The columns are organized as follows: -| Column Group | Even Row (2i) | Odd Row (2i+1) | +| Column Group | Even Row $(2i)$ | Odd Row $(2i+1)$ | | ---------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------- | | Coordinate $P_x$ microlimbs | | | | `P_X_LOW_LIMBS_RANGE_CONSTRAINT_0` | $P_{x,0}[0]$ | $P_{x,1}[0]$ | @@ -258,7 +258,7 @@ Each limb is further decomposed into **14-bit microlimbs** for range checking. E | `Z_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,1}[2]$ | $z_{2,1}[2]$ | | `Z_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $z_{1,1}[3]$ | $z_{2,1}[3]$ | | `Z_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $z_{1,1}[4]$ | $z_{2,1}[4]$ | -| Accumulator microlimbs | | | +| Current and previous accumulator microlimbs | | | | `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0` | $a_{0}^{\text{curr}}[0]$ | $a_{1}^{\text{curr}}[0]$ | | `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_1` | $a_{0}^{\text{curr}}[1]$ | $a_{1}^{\text{curr}}[1]$ | | `ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_2` | $a_{0}^{\text{curr}}[2]$ | $a_{1}^{\text{curr}}[2]$ | @@ -311,43 +311,40 @@ Some columns are "virtual" and not explicitly stored in the witness trace. Inste ### Lagrange Polynomials (Precomputed) -The Translator circuit uses **ZERO selector polynomials** (`NUM_SELECTORS = 0`). +The Translator circuit uses ZERO selector polynomials (`NUM_SELECTORS = 0`). -Instead, the circuit uses **Lagrange polynomials** to control which constraints are active: +Instead, the circuit uses Lagrange polynomials to control which constraints are active: -| Polynomial | Description | Active Rows | -| ------------------------------ | ------------------------------- | ------------------------------------- | -| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in \{0, 2, 4, ..., 8190\}$ (mini) | -| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in \{1, 3, 5, ..., 8191\}$ (mini) | -| `lagrange_first` | First row | $i = 0$ | -| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | -| `lagrange_result_row` | Row containing final result | Specific row in trace | -| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | -| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | +| Polynomial | Description | Active Rows | +| ------------------------------ | ------------------------------- | ---------------------------------------------------------------------------- | +| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in \{0, 2, 4, ..., 8190\}$ (mini) | +| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in \{1, 3, 5, ..., 8191\}$ (mini) | +| `lagrange_first` | First row | $i = 0$ | +| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | +| `lagrange_result_row` | Row containing final result | $i = 8$ (mini, equals no of rows are to be left for random ops at the start) | +| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | +| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange polynomials, which are more efficient than custom selectors. ---- - ## Interleaving: The Key Optimization -The Translator must range-constrain approximately 64 different microlimb sets using permutation argument. The permutation argument's degree equals $1 + \text{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: +The Translator must range-constrain approximately 64 different microlimb sets using permutation argument (and the delta range constraint). The permutation argument's degree equals $1 + \textsf{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: $$ -z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \beta + \gamma) = -z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \beta + \gamma) +z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[j] + \gamma) = +z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \gamma) $$ -**The Problem:** Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. +The Problem: Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. -**The Solution:** Interleave 16 logical column groups into the same 5 physical wires across 16 circuit segments. Each segment performs an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree by 9Γ—. +The Solution: Interleave 16 logical columns into one virtual column, and create 4 such columns (plus 1 for the extra column). Each group can then perform an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree from 65 to 7. ### Circuit Structure ``` Mini-circuit size: 2^13 = 8,192 rows (actual computation) -Full circuit size: 2^17 = 131,072 rows (16Γ— larger for interleaving) -FULL_SIZE = MINI_SIZE Γ— INTERLEAVING_GROUP_SIZE = 8,192 Γ— 16 +Full circuit size: 2^13 x 16 = 2^17 = 131,072 rows (after interleaving) ``` To compute the interleaved polynomials, we group 16 polynomials together and interleave their coefficients. Consider the following 16 polynomials each of size $n=2^{13}$ in the mini-circuit: @@ -375,13 +372,12 @@ n-1 & \textcolor{skyblue}{a_{n-1}} & \textcolor{orange}{b_{n-1}} & \textcolor{li 0 & 1 & \textcolor{orange}{b_0} \\ 0 & 2 & \textcolor{lightgreen}{c_0} \\ \vdots & \vdots & \vdots \\[3pt] -1 & 15 & \textcolor{firebrick}{p_0} \\ \hline +0 & 15 & \textcolor{firebrick}{p_0} \\ \hline 1 & 4 & \textcolor{skyblue}{a_1} \\ 1 & 5 & \textcolor{orange}{b_1} \\ 1 & 6 & \textcolor{lightgreen}{c_1} \\ \vdots & \vdots & \vdots \\[3pt] 1 & 7 & \textcolor{firebrick}{p_1} \\ \hline -\vdots & \vdots & \vdots \\[5pt] \vdots & \vdots & \vdots \\ \hline n-1 & 4n-4 & \textcolor{skyblue}{a_{n-1}} \\ n-1 & 4n-3 & \textcolor{orange}{b_{n-1}} \\ @@ -393,13 +389,13 @@ n-1 & 4n-1 & \textcolor{firebrick}{p_{n-1}} \\ $$ The resulting interleaved polynomial has size $16n = 2^{17}$. -For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: +For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are not "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: -- **Numerator:** 4 interleaved wires + 1 extra = 5 terms -- **Denominator:** 5 ordered wires = 5 terms -- **Degree:** $1 + 5 = 6$ (or 7 with Lagrange) +- Numerator: 4 interleaved wires + 1 extra = 5 terms +- Denominator: 5 ordered wires = 5 terms +- Degree: $1 + 5 = 6$ (or 7 with Lagrange) -The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding (enforced by Relation 7). Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. +The permutation argument verifies that within each group, the interleaved values are a permutation of the ordered (sorted) values. Due to interleaving, the total circuit size increases 16Γ—, requiring more zero-padding. Interleaving trades circuit size (inexpensive) for relation degree (expensive). The 16Γ— size increase is acceptable given the 9Γ— degree reduction. > **Effect on Commitment Scheme**: For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: > $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ From 0a402cfde0d2b3b44d10eaffd34895647c1f1155 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Sat, 20 Dec 2025 13:08:33 +0000 Subject: [PATCH 21/29] get rid of constants. --- .../src/barretenberg/translator_vm/README.md | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index fc1b08a80ce2..109c0d37be1c 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -102,57 +102,6 @@ We verify this by proving the equation holds: By the Chinese Remainder Theorem, since $2^{272} \cdot r > 2^{514}$ exceeds the maximum possible value, the equation must hold in integers, and thus modulo $q$. -### Constants - -#### Field Moduli - -``` -BN254 Base Field (Fq): -q = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - β‰ˆ 2^254 - -BN254 Scalar Field (Fr): -r = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - β‰ˆ 2^254 -``` - -**Key observation:** $q > r$ (they differ by $\approx 2^{47}$), so we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic. - -#### Limb Decomposition Constants - -```cpp -NUM_LIMB_BITS = 68 // Each limb is 68 bits -NUM_LAST_LIMB_BITS = 50 // Top limb: 254 - 3*68 = 50 bits -NUM_BINARY_LIMBS = 4 // Total limbs per element - -NUM_Z_BITS = 128 // z₁ and zβ‚‚ are 128-bit -NUM_Z_LIMBS = 2 // z values use 2 limbs (68 + 60 bits) - -NUM_QUOTIENT_BITS = 256 // Quotient needs 256 bits -NUM_LAST_QUOTIENT_LIMB_BITS = 52 // 256 - 3*68 = 52 bits - -MICRO_LIMB_BITS = 14 // Range constraint granularity -NUM_MICRO_LIMBS = 6 // 68 / 14 β‰ˆ 5, plus 1 for tail -``` - -#### Opcode Values - -- `0`: No-op -- `3`: Equality check and reset accumulator -- `4`: Scalar multiplication -- `8`: Point addition - -#### Range Constraint Constants - -```cpp -SORT_STEP = 3 // Max delta between sorted values -NUM_RANGE_CONSTRAINT_WIRES = 5 // ordered_range_constraints_{0,1,2,3,4} -SORTED_STEPS_COUNT = 2^14 / 3 + 1 // Number of "step" values inserted - = 5462 steps -``` - -Each microlimb must be $≀ 2^{14} - 1 = 16383$. - ## Witness Trace Structure The Translator circuit has 81 witness columns, organized into: From df9afaf802f26b76b784c49e117338fae00504b5 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Sat, 20 Dec 2025 13:12:01 +0000 Subject: [PATCH 22/29] get rid of lag sentence. --- barretenberg/cpp/src/barretenberg/translator_vm/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 109c0d37be1c..55ff23c5190f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -274,8 +274,6 @@ Instead, the circuit uses Lagrange polynomials to control which constraints are | `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | | `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | -The circuit's regularity (2-row cycles, uniform structure) allows using Lagrange polynomials, which are more efficient than custom selectors. - ## Interleaving: The Key Optimization The Translator must range-constrain approximately 64 different microlimb sets using permutation argument (and the delta range constraint). The permutation argument's degree equals $1 + \textsf{NUM\_COLS}$, where NUM_COLS is the number of columns being permuted: From 6c4d7603dfdef1457b45495cdd2d7fe6aaee339b Mon Sep 17 00:00:00 2001 From: suyash67 Date: Mon, 5 Jan 2026 10:27:19 +0000 Subject: [PATCH 23/29] minor updates. --- .../src/barretenberg/translator_vm/README.md | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 55ff23c5190f..f80b8ab898e8 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -25,10 +25,10 @@ The Translator circuit is a critical component of the Goblin Plonk proving syste When proving recursive circuits with Mega circuit builder, we accumulate elliptic curve operations in an `EccOpQueue`. Proving these ECC operations is delegated to the ECCVM circuit, which operates over the Grumpkin curve. However, the same operations have different representations in the two circuits because: -- Mega circuit operates over the BN254 scalar field $\mathbb{F}_r$ so elements in $\mathbb{F}_q$ are non-native (i.e., they need to decomposed into limbs in $\mathbb{F}_r$) -- ECCVM operates over the Grumpkin scalar field $\mathbb{F}_q$ so elements in $\mathbb{F}_q$ are circuit native +- Mega circuit operates over the BN254 scalar field $\mathbb{F}_r$ so elements in $\mathbb{F}_q$ are non-native (i.e., since $q > r$ they need to be decomposed into limbs in $\mathbb{F}_r$) +- ECCVM operates over the Grumpkin scalar field $\mathbb{F}_q$ so elements in $\mathbb{F}_q$ (as well as $\mathbb{F}_r$) are circuit native -For example, consider the operation $(z \cdot P)$ where $P$ is a point on the curve and $z$ is a scalar. The ECCVM arithmetisation represents this operation (in 1 row) as: +For example, consider the operation $(z \cdot P)$ where $P \equiv (P_x, P_y) \in \mathbb{F}_q^2$ is a point on the curve and $z \in \mathbb{F}_r$ is a scalar. The ECCVM arithmetisation represents this operation (in 1 row) as: | Opcode | $x$-coordinate | $y$-coordinate | Scalar $z_1$ | Scalar $z_2$ | Full scalar $z$ | | ------ | -------------- | -------------- | ------------ | ------------ | --------------- | @@ -43,29 +43,25 @@ The Mega circuit arithmetisation represents the same operation (in 2 rows) as: | $0$ | $P_{y, \textsf{hi}}$ | $z_1$ | $z_2$ | | | | | | -where $P_x = (P_{x, \textsf{lo}} + 2^{136} \cdot P_{x, \textsf{hi}}), \ P_y = (P_{y, \textsf{lo}} + 2^{136} \cdot P_{y, \textsf{hi}})$ and the scalar $z = (z_1 + 2^{128} \cdot z_2)$. +where $P_x = (P_{x, \textsf{lo}} + 2^{136} \cdot P_{x, \textsf{hi}}), \ P_y = (P_{y, \textsf{lo}} + 2^{136} \cdot P_{y, \textsf{hi}})$ and the scalar $z = (z_1 + 2^{128} \cdot z_2)$. Note that the limbs $P_{x/y, \textsf{lo}}, P_{x/y, \textsf{hi}}$ are elements in $\mathbb{F}_r$. We need to prove that these two representations are consistent, i.e., that the polynomial evaluations computed in the ECCVM circuit (over $\mathbb{F}_q$) match those computed in the Mega circuit (over $\mathbb{F}_r$). - The Translator circuit is a custom circuit designed to solve this problem. It: 1. **Receives** the ECC op queue in Mega arithmetisation and the batched polynomial evaluation problem from ECCVM (operating over $\mathbb{F}_q$), 2. **Computes** the batched polynomial evaluation using non-native field arithmetic in $\mathbb{F}_r$ and, 3. **Verifies** that the result matches the evaluation provided by ECCVM. ---- - ## High-Level Statement The Translator proves that the ECCVM's batched polynomial evaluation of the ECC operations is computed correctly. - -**Given:** +Given: - A sequence of `UltraOp` operations from the `EccOpQueue` (each containing: $\text{op}, P_x, P_y, z_1, z_2$) - An evaluation challenge $x \in \mathbb{F}_q$ - A batching challenge $v \in \mathbb{F}_q$ -**Prove:** +Prove that: $$\boxed{\text{accumulator}_{\text{final}} = \sum_{i=0}^{n-1} x^{n-1-i} \cdot \left( \text{op}_i + v \cdot P_x^{(i)} + v^2 \cdot P_y^{(i)} + v^3 \cdot z_1^{(i)} + v^4 \cdot z_2^{(i)} \right) \pmod{q}}$$ The batching via powers of $v$ combines the 5 values per operation into a single field element, and the powers of $x$ combine all operations into a single accumulator. @@ -88,7 +84,7 @@ $$ $$ The final accumulator value $\textcolor{violet}{\text{acc}_{n-1}}$ is what we need to verify against the ECCVM's output. -Note that the "previous" accumulator in the _last_ step must be 0. +Note that the "previous" accumulator for the _last_ operation must be 0. **Method:** Since we cannot directly compute in $\mathbb{F}_q$ using $\mathbb{F}_r$ arithmetic (as $q \neq r$, and in fact $q > r$), we use non-native field arithmetic. Similar to the technique in [bigfield](../stdlib/primitives/bigfield/README.md), we prove the equation holds in integers: @@ -115,11 +111,11 @@ The circuit operates on a 2-row cycle structure. Each `EccOpQueue` entry occupie - Row $2i$ (Even rows): Computation rows where the non-native field relation is actively checked - Row $2i+1$ (Odd rows): Data storage rows that hold values accessed via shifts -While enforcing constraints on the even rows, we can access values from the "next" odd row using shifted column polynomials. +While enforcing constraints on the even rows, we can access values from the "next" row (which is odd) using shifted column polynomials. As hinted earlier, the "previous" accumulator value needed for computation is stored at odd row $(2i+1)$. This value becomes the "current" accumulator for the next even row $(2i+2)$: -| Op index | $0$ | $1$ | $\quad \dots \quad$ | $(n-2)$ | $(n-1)$ | +| Operation index | $0$ | $1$ | $\quad \dots \quad$ | $(n-2)$ | $(n-1)$ | | -------------------- | -------------------------------------- | ------------------------------------- | ------------------- | ---------------------------------------- | ------------------------------------ | | Current accumulator | $\textcolor{violet}{\text{acc}_{n-1}}$ | $\textcolor{brown}{\text{acc}_{n-2}}$ | $\quad \dots \quad$ | $\textcolor{lightgreen}{\text{acc}_{1}}$ | $\textcolor{orange}{\text{acc}_{0}}$ | | Previous accumulator | $\textcolor{brown}{\text{acc}_{n-2}}$ | $\textcolor{grey}{\text{acc}_{n-3}}$ | $\quad \dots \quad$ | $\textcolor{orange}{\text{acc}_{0}}$ | $0$ | @@ -129,7 +125,7 @@ This value becomes the "current" accumulator for the next even row $(2i+2)$: These columns directly represent the EccOpQueue transcript: -| Column | Even Row $(2i)$ | Odd Row $(2i+1)$ | Description | +| Column Name | Even Row $(2i)$ | Odd Row $(2i+1)$ | Description | | ----------- | -------------------------------- | ---------------------------- | ------------------------------------------------------------------ | | `OP` | $\texttt{op} \in \{0, 3, 4, 8\}$ | 0 (no-op) | Opcode (the type of elliptic curve operation) | | `X_LO_Y_HI` | $P_{x,\text{lo}}$ (136 bits) | $P_{y,\text{hi}}$ (118 bits) | Low 136 bits of $x$-coordinate and high 118 bits of $y$-coordinate | @@ -196,7 +192,7 @@ Each limb is further decomposed into 14-bit microlimbs for range checking. Each | `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_2` | $P_{y,2}[2]$ | $P_{y,3}[2]$ | | `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_3` | $P_{y,2}[3]$ | $P_{y,3}[3]$ | | `P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_4` | $P_{y,2}[4]$ | $\textcolor{yellow}{P_{y,3}[\textsf{tail}]}$ (reassigned) | -| Coordinate $z_1$ microlimbs | | | +| Coordinate $z_1$ and $z_2$ microlimbs | | | | `Z_LOW_LIMBS_RANGE_CONSTRAINT_0` | $z_{1,0}[0]$ | $z_{2,0}[0]$ | | `Z_LOW_LIMBS_RANGE_CONSTRAINT_1` | $z_{1,0}[1]$ | $z_{2,0}[1]$ | | `Z_LOW_LIMBS_RANGE_CONSTRAINT_2` | $z_{1,0}[2]$ | $z_{2,0}[2]$ | @@ -261,7 +257,6 @@ Some columns are "virtual" and not explicitly stored in the witness trace. Inste ### Lagrange Polynomials (Precomputed) The Translator circuit uses ZERO selector polynomials (`NUM_SELECTORS = 0`). - Instead, the circuit uses Lagrange polynomials to control which constraints are active: | Polynomial | Description | Active Rows | From 673d35428ee3b278d58e548136bd33fef808567d Mon Sep 17 00:00:00 2001 From: suyash67 Date: Mon, 5 Jan 2026 11:36:08 +0000 Subject: [PATCH 24/29] resolve further comments. --- .../src/barretenberg/translator_vm/README.md | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index f80b8ab898e8..8bbe09cdc670 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -278,7 +278,7 @@ z_{\textsf{perm}}[i+1] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{ordered}[ z_{\textsf{perm}}[i] \cdot \prod_{j=1}^{\textsf{NUM\_COLS}} (\textsf{interleaved}[j] + \gamma) $$ -The Problem: Permuting all ~64 microlimb columns simultaneously yields degree $1 + 64 = 65$, making sumcheck impractical. +The Problem: Permuting all ~64 microlimb columns simultaneously would require us to commit to all of them. Further, since the relation degree would be $1 + 64 = 65$, computing the sumcheck univariates could be a significant overhead for the prover. The prover would need to then commit to the univariates (instead of sending evaluations directly). The Solution: Interleave 16 logical columns into one virtual column, and create 4 such columns (plus 1 for the extra column). Each group can then perform an independent permutation check with degree $1 + 5 = 6$ (or 7 with Lagrange selector). This reduces the relation degree from 65 to 7. @@ -315,23 +315,22 @@ n-1 & \textcolor{skyblue}{a_{n-1}} & \textcolor{orange}{b_{n-1}} & \textcolor{li 0 & 2 & \textcolor{lightgreen}{c_0} \\ \vdots & \vdots & \vdots \\[3pt] 0 & 15 & \textcolor{firebrick}{p_0} \\ \hline -1 & 4 & \textcolor{skyblue}{a_1} \\ -1 & 5 & \textcolor{orange}{b_1} \\ -1 & 6 & \textcolor{lightgreen}{c_1} \\ +1 & 16 & \textcolor{skyblue}{a_1} \\ +1 & 17 & \textcolor{orange}{b_1} \\ +1 & 18 & \textcolor{lightgreen}{c_1} \\ \vdots & \vdots & \vdots \\[3pt] -1 & 7 & \textcolor{firebrick}{p_1} \\ \hline +1 & 31 & \textcolor{firebrick}{p_1} \\ \hline \vdots & \vdots & \vdots \\ \hline -n-1 & 4n-4 & \textcolor{skyblue}{a_{n-1}} \\ -n-1 & 4n-3 & \textcolor{orange}{b_{n-1}} \\ -n-1 & 4n-2 & \textcolor{lightgreen}{c_{n-1}} \\ +n-1 & 16n-16 & \textcolor{skyblue}{a_{n-1}} \\ +n-1 & 16n-15 & \textcolor{orange}{b_{n-1}} \\ +n-1 & 16n-14 & \textcolor{lightgreen}{c_{n-1}} \\ \vdots & \vdots & \vdots \\[3pt] -n-1 & 4n-1 & \textcolor{firebrick}{p_{n-1}} \\ +n-1 & 16n-1 & \textcolor{firebrick}{p_{n-1}} \\ \hline \end{array} $$ -The resulting interleaved polynomial has size $16n = 2^{17}$. -For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials. Note that the interleaved polynomials are not "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: +For 64 microlimb columns, we have 4 groups of 16 columns each, resulting in four interleaved polynomials each of size $16n = 2^{17}$. Note that the interleaved polynomials are not "physical" wires in the circuit trace: we refer to them as virtual polynomials. Each of these groups performs an independent permutation check: - Numerator: 4 interleaved wires + 1 extra = 5 terms - Denominator: 5 ordered wires = 5 terms @@ -341,9 +340,7 @@ The permutation argument verifies that within each group, the interleaved values > **Effect on Commitment Scheme**: For polynomials $p_0, \dots, p_{15}$ of size $n$, the interleaved polynomial of size $16n$ is: > $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ -> The interleaved polynomials do not require separate commitments because they can be derived from the original polynomials' commitments. In the Gemini PCS phase, the prover sends only two additional field element evaluations $P_+(r^{16})$ and $P_-(r^{16})$ where $r$ is the Gemini challenge: -> $$P_{\pm}(x) = \sum_{i=0}^{15} (\pm r)^i \cdot p_{i}(x)$$ -> The verifier reconstructs full batched polynomial evaluations as $A_0(r) = A_{0+}(r) + P_+(r^{16})$ and $A_0(-r) = A_{0-}(-r) + P_-(r^{16})$. Since $P_{\pm}(r^{16})$ relates to evaluations $p_i(r^{16})$ already in the Gemini protocol, no additional commitments are needed. +> The interleaved polynomials don't need to be committed explicitly; they can be opened (at, say $\gamma$) by using the commitments to the original polynomials and their evaluations (at $\gamma^{16}$). This is explained in more detail in the [Gemini](../commitment_schemes/gemini/README.md) documentation. --- From c038f88b435ff3c7ac3d49528597d321942fa8af Mon Sep 17 00:00:00 2001 From: suyash67 Date: Mon, 5 Jan 2026 13:00:12 +0000 Subject: [PATCH 25/29] minor edits. --- .../cpp/src/barretenberg/translator_vm/README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 8bbe09cdc670..57540fc61cee 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -342,8 +342,6 @@ The permutation argument verifies that within each group, the interleaved values > $$p_{\textsf{interleaved}}(x) = \sum_{i=0}^{15} x^i \cdot p_{i}(x^{16})$$ > The interleaved polynomials don't need to be committed explicitly; they can be opened (at, say $\gamma$) by using the commitments to the original polynomials and their evaluations (at $\gamma^{16}$). This is explained in more detail in the [Gemini](../commitment_schemes/gemini/README.md) documentation. ---- - ## Witness Generation and Proving Key Construction This section details how the Translator circuit's witness polynomials are populated and how zero-knowledge is achieved through masking. @@ -995,7 +993,7 @@ I_1 \quad I_2 \quad I_3 \quad I_4 \\ \end{array} }} \\ - \\[-10pt] + \\[-13pt] \textcolor{violet}{ \boxed{ \begin{array}{c} @@ -1158,7 +1156,7 @@ O_1 \quad O_2 \ \ O_3 \quad O_4 \\ \end{array} }} \\ - \\[-10pt] + \\[-12pt] \textcolor{lightgreen}{ \boxed{ \begin{array}{c} @@ -1166,7 +1164,7 @@ O_1 \quad O_2 \ \ O_3 \quad O_4 \\ \end{array} }} \\ - \\[-10pt] + \\[-13pt] \textcolor{violet}{ \boxed{ \begin{array}{c} @@ -1194,7 +1192,7 @@ O_1 \quad O_2 \ \ O_3 \quad O_4 \\ \end{array} $$ -> In our case, we have $m=4$ and $I_{\textsf{size}}=16$ which results in $(m \cdot I_{\textsf{size}}) = 64$ masked rows in each interleaved polynomials. Thus, each ordered polynomial will have at least $\left\lfloor\frac{4 \cdot 64}{5}\right\rfloor = 51$ masked rows. The remainder masked row is added to the first ordered polynomial. The masking rows in each ordered polynomial are padded with zero values to ensure the multiset equality holds. +> In our case, we have $m=4$ and $I_{\textsf{size}}=16$ which results in $(m \cdot I_{\textsf{size}}) = 64$ masked rows in each interleaved polynomials. Thus, each ordered polynomial will have at least $\left\lfloor\frac{4 \cdot 64}{5}\right\rfloor = 51$ masked rows. The remainder masked rows are added to the respective ordered polynomials. The masking rows in each ordered polynomial are padded with zero values to ensure the multiset equality holds. > > As illustrated, the two sets of interleaved and ordered polynomials satisfy the multiset equality: > $$\bigcup_{i=1}^5 I_i = \bigcup_{i=1}^5 O_i.$$ @@ -1231,7 +1229,7 @@ Some positions in the ordered masking region contain random values, others conta ### Step 8: Precomputed Polynomials -Several polynomials are **precomputed** and independent of the witness: +Several polynomials are precomputed and independent of the witness. #### Lagrange Polynomials @@ -1259,8 +1257,6 @@ This ensures the multisets balance: - **Numerator:** 4 interleaved + 1 extra (with 5 copies of each step value) - **Denominator:** 5 ordered (each with 1 copy of each step value) ---- - ## Translator Relations Constraints for the translator VM are specified in [RELATIONS.md](RELATIONS.md). From 19413f73a9f067a9d7decfa3327b013ce3f5d67a Mon Sep 17 00:00:00 2001 From: suyash67 Date: Mon, 5 Jan 2026 18:41:28 +0000 Subject: [PATCH 26/29] fix opcode relations. --- .../barretenberg/translator_vm/RELATIONS.md | 262 ++++++------------ 1 file changed, 89 insertions(+), 173 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index 7ff75dc1e57f..49da040b66a1 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -26,9 +26,10 @@ Lagrange selectors for activation: 3. [Decomposition Relation](#decomposition-relation) 4. [Permutation Relation](#permutation-relation) 5. [Delta Range Constraint Relation](#delta-range-constraint-relation) -6. [Opcode Constraint Relation](#opcode-constraint-relation) -7. [Accumulator Transfer Relation](#accumulator-transfer-relation) -8. [Zero Constraints Relation](#zero-constraints-relation) +6. [Extra Relations](#extra-relations) + - (a) [Opcode Constraint Relation](#opcode-constraint-relation) + - (b) [Accumulator Transfer Relation](#accumulator-transfer-relation) + - (c) [Zero Constraints Relation](#zero-constraints-relation) --- @@ -36,33 +37,33 @@ Lagrange selectors for activation: This table establishes all notation used in the relations: -| Value | Native (𝔽q) | Binary Limbs | Native (𝔽r) | -| ------------------------------- | -------------------- | ------------------------------------------------------------------------------------ | --------------- | +| Value | Description | Binary Limbs | Native $\mathbb{F}_r$ | +| ------------------------------- | -------------------- | ------------------------------------------------------------------------------------ | --------------------- | | **Evaluation challenge** | -| $x$ | Evaluation point | $x_0, x_1, x_2, x_3$ | $x_4$ | +| $x$ | Evaluation point | $x_0, x_1, x_2, x_3$ | $x_4$ | | **Batching challenges** | -| $v$ | Batching challenge | $v_0, v_1, v_2, v_3$ | $v_4$ | -| $v^2$ | v squared | $(v^2)_0, (v^2)_1, (v^2)_2, (v^2)_3$ | $(v^2)_4$ | -| $v^3$ | v cubed | $(v^3)_0, (v^3)_1, (v^3)_2, (v^3)_3$ | $(v^3)_4$ | -| $v^4$ | v to fourth | $(v^4)_0, (v^4)_1, (v^4)_2, (v^4)_3$ | $(v^4)_4$ | +| $v$ | Batching challenge | $v_0, v_1, v_2, v_3$ | $v_4$ | +| $v^2$ | v squared | $(v^2)_0, (v^2)_1, (v^2)_2, (v^2)_3$ | $(v^2)_4$ | +| $v^3$ | v cubed | $(v^3)_0, (v^3)_1, (v^3)_2, (v^3)_3$ | $(v^3)_4$ | +| $v^4$ | v to fourth | $(v^4)_0, (v^4)_1, (v^4)_2, (v^4)_3$ | $(v^4)_4$ | | **Point coordinates (witness)** | -| $P_x$ | Point x-coordinate | $P_{x,0}^{\text{lo}}, P_{x,1}^{\text{lo}}, P_{x,0}^{\text{hi}}, P_{x,1}^{\text{hi}}$ | (reconstructed) | -| $P_y$ | Point y-coordinate | $P_{y,0}^{\text{lo}}, P_{y,1}^{\text{lo}}, P_{y,0}^{\text{hi}}, P_{y,1}^{\text{hi}}$ | (reconstructed) | +| $P_x$ | Point x-coordinate | $P_{x,0}^{\text{lo}}, P_{x,1}^{\text{lo}}, P_{x,0}^{\text{hi}}, P_{x,1}^{\text{hi}}$ | (reconstructed) | +| $P_y$ | Point y-coordinate | $P_{y,0}^{\text{lo}}, P_{y,1}^{\text{lo}}, P_{y,0}^{\text{hi}}, P_{y,1}^{\text{hi}}$ | (reconstructed) | | **Z-values (witness, 128-bit)** | -| $z_1$ | 128-bit value | $z_{1,0}, z_{1,1}$ (only 2 limbs) | (reconstructed) | -| $z_2$ | 128-bit value | $z_{2,0}, z_{2,1}$ (only 2 limbs) | (reconstructed) | +| $z_1$ | 128-bit value | $z_{1,0}, z_{1,1}$ (only 2 limbs) | (reconstructed) | +| $z_2$ | 128-bit value | $z_{2,0}, z_{2,1}$ (only 2 limbs) | (reconstructed) | | **Accumulator (witness)** | -| $a^{\text{prev}}$ | Previous accumulator | $a_0^{\text{prev}}, a_1^{\text{prev}}, a_2^{\text{prev}}, a_3^{\text{prev}}$ | (reconstructed) | -| $a^{\text{curr}}$ | Current accumulator | $a_0^{\text{curr}}, a_1^{\text{curr}}, a_2^{\text{curr}}, a_3^{\text{curr}}$ | (reconstructed) | +| $a^{\text{prev}}$ | Previous accumulator | $a_0^{\text{prev}}, a_1^{\text{prev}}, a_2^{\text{prev}}, a_3^{\text{prev}}$ | (reconstructed) | +| $a^{\text{curr}}$ | Current accumulator | $a_0^{\text{curr}}, a_1^{\text{curr}}, a_2^{\text{curr}}, a_3^{\text{curr}}$ | (reconstructed) | | **Quotient (witness)** | -| $\mathcal{Q}$ | Division quotient | $q_0, q_1, q_2, q_3$ | (reconstructed) | +| $\mathcal{Q}$ | Division quotient | $q_0, q_1, q_2, q_3$ | (reconstructed) | | **Negative $q$ constant** | -| $\bar{q}$ | $-q \pmod{2^{272}}$ | $\bar{q}_0, \bar{q}_1, \bar{q}_2, \bar{q}_3$ | $\bar{q}_4$ | +| $\bar{q}$ | $-q \pmod{2^{272}}$ | $\bar{q}_0, \bar{q}_1, \bar{q}_2, \bar{q}_3$ | $\bar{q}_4$ | | **Carries (witness)** | -| $c^{\text{lo}}$ | Lower carry | (single 84-bit value) | - | -| $c^{\text{hi}}$ | Higher carry | (single 84-bit value) | - | +| $c^{\text{lo}}$ | Lower carry | (single 84-bit value) | - | +| $c^{\text{hi}}$ | Higher carry | (single 84-bit value) | - | | **Opcode (witness, small)** | -| $\texttt{op}$ | Operation code | (no decomposition, ≀ 8) | $\texttt{op}$ | +| $\texttt{op}$ | Operation code | (no decomposition, ≀ 8) | $\texttt{op}$ | #### Reconstruction Formula (General) @@ -111,20 +112,19 @@ If this equation holds: 2. Modulo $r$ (native $\mathbb{F}_r$ computation), and 3. All values are properly range-constrained -Using Chinese Remainder Theorem, then it holds in integers (since $2^{272} \cdot r > 2^{514}$ > max possible value), which implies it holds modulo $q$. See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. +then it must hold in integers. This is because the Chinese Remainder Theorem guarantees that if an equation holds modulo two coprime moduli whose product exceeds the maximum possible value of the equation, then it holds over the integers. Here, the maximum possible value of the left-hand side is less than $2^{514}$, while the moduli product is $2^{272} \cdot r > 2^{525} > 2^{514}$. +See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. The non-native field relation is enforced through three separate subrelations: -| Subrelation | Purpose | Modulus | Limbs checked | -| ----------- | -------------------------- | --------- | ------------------------------------- | -| 1 | Lower mod $2^{272}$ check | $2^{136}$ | Limbs 0, 1 | -| 2 | Higher mod $2^{272}$ check | $2^{136}$ | Limbs 2, 3 (with carry from subrel 1) | -| 3 | Native field check | $r$ | Full native reconstruction | +| Subrelation | Purpose | Modulus | Limbs checked | +| ----------- | -------------------------- | --------- | ------------------------------------------ | +| 1 | Lower mod $2^{272}$ check | $2^{136}$ | Limbs 0, 1 | +| 2 | Higher mod $2^{272}$ check | $2^{136}$ | Limbs 2, 3 (with carry from subrelation 1) | +| 3 | Native field check | $r$ | Full native reconstruction | Together, these prove the relation holds in integers. ---- - ### Subrelation 1: Lower Mod $2^{136}$ Check Prove that when we compute the accumulation formula using limbs 0 and 1, the result is a multiple of $2^{136}$. @@ -197,7 +197,7 @@ The limb 2 contribution (with carry) is: $$ \boxed{\begin{align*} -T_2 := &\; c^{\text{lo}} \quad \text{(carry from subrelation 1)} & \\ +T_2 := &\; c^{\text{lo}} \quad \textsf{(carry from subrelation 1)} & \\ &+ a_2^{\text{prev}} \cdot x_0 + a_1^{\text{prev}} \cdot x_1 + a_0^{\text{prev}} \cdot x_2 \\ &+ P_{x,0}^{\text{hi}} \cdot v_0 + P_{x,1}^{\text{lo}} \cdot v_1 + P_{x,0}^{\text{lo}} \cdot v_2 \\ &+ P_{y,0}^{\text{hi}} \cdot (v^2)_0 + P_{y,1}^{\text{lo}} \cdot (v^2)_1 + P_{y,0}^{\text{lo}} \cdot (v^2)_2 \\ @@ -238,7 +238,7 @@ Together with Subrelation 1: We've proven the relation holds modulo $2^{272}$. ### Subrelation 3: Native Field Check -Prove the accumulation formula holds when computed directly in 𝔽r (the native field). +Prove the accumulation formula holds when computed directly in $\mathbb{F}_r$ (the native field). First, reconstruct all values from their limbs: $$ @@ -253,7 +253,7 @@ $$ \end{align*} $$ -**Note:** The tilde indicates these are native field reconstructions in 𝔽r, not the original 𝔽q values. +**Note:** The tilde indicates these are native field reconstructions in $\mathbb{F}_r$, not the original $\mathbb{F}_q$ values. The subrelation 3 is then: @@ -289,13 +289,13 @@ The Decomposition Relation enforces the integrity of the limb decomposition syst | Category | No. of Subrelations | Note | | -------------------------------------- | ------------------- | --------------------------------------------------- | | Accumulator microlimb decomposition | 4 | Active when $L_{\text{even}} \cdot \texttt{op} = 1$ | -| Point & Scalar microlimb decomposition | 18 | Active when $L_{\text{even}} = 1$ | +| Point & scalar microlimb decomposition | 16 | Active when $L_{\text{even}} = 1$ | | Wide limb decomposition | 2 | Decompose 84-bit carry limbs | | Range constraint tightening | 20 | Enforce stricter bounds on highest microlimbs | -| Transcript composition | 6 | Prove 68-bit limbs reconstruct transcript values | +| Transcript decomposition | 6 | Prove 68-bit limbs reconstruct transcript values | | | | | -These work with the **Permutation Relation** and **Delta Range Constraint** which together prove each microlimb is in $[0, 2^{14})$. +These work with the Permutation Relation and Delta Range Constraint which together prove each microlimb is in $[0, 2^{14})$. --- @@ -431,8 +431,6 @@ The relation consists of 2 subrelations: 1. Grand product identity (degree 7) 2. Finalization check (degree 3) ---- - #### Interaction with the Delta Range Constraints The Permutation Relation works alongside the Delta Range Constraints to enforce microlimb ranges. We use a permutation argument to show that the multiset of microlimb values used in the circuit matches an ordered multiset containing all integers from $0$ to $2^{14} - 1 = 16383$. Instead of including all integers in the range $[0, 2^{14} - 1]$ explicitly, we use a "step" sequence with a fixed step size of 3: @@ -468,10 +466,11 @@ $$\boxed{\left( z_{\text{perm}} + L_{\text{first}} \right) \cdot \prod_{j=0}^{4} where: -- $L_{\text{first}}$: Lagrange polynomial for first row (initializes $z_{\text{perm}}[0] = 0$) -- $L_{\text{last}}$: Lagrange polynomial for last row (finalizes $z_{\text{perm}}[\text{last}] = 0$) +- $L_{\text{first}}$: Lagrange polynomial for first row ($z_{\text{perm}}[0] = 0$ is enforced implicitly) +- $L_{\text{last}}$: Lagrange polynomial for last row (we enforce $z_{\text{perm}}[\text{last}] = 0$ in subrelation 2) - $z_{\text{perm}}^{\text{shift}}$: Shifted grand product polynomial ($z_{\text{perm}}[i+1]$) +Note that $z_{\text{perm}}[0] = 0$ follows implicitly from the fact that we are opening $z_{\text{perm}}$ and $z_{\text{perm}}^{\text{shift}}$ both at the same challenge. If the two multisets are equal: 1. At each step, the products telescope: contributions cancel out @@ -480,7 +479,7 @@ If the two multisets are equal: Active when: All rows (both even and odd in the full interleaved circuit) -Degree: 6 (each side is degree 1 polynomial Γ— product of 5 degree-1 terms) +Degree: 6 (each side is linear polynomial Γ— product of 5 linear terms) --- @@ -500,8 +499,6 @@ Active when: Last row only ($L_{\text{last}} = 1$) Degree: 2 (Lagrange Γ— shifted polynomial) ---- - ## Delta Range Constraint Relation The Delta Range Constraint Relation works in tandem with the Permutation Relation to prove that the ordered (sorted) multiset is actually sorted and bounded correctly. @@ -550,7 +547,7 @@ Between these steps, actual microlimbs fill in the gaps. With $\Delta \in \{0, 1 - Every value $\leq 16383$ has a step value within distance 3 - Therefore, all values in range can be represented -Degree: 6 (product of 6 degree-1 polynomials: $(L_{\text{real\_last}} - 1) \cdot (L_{\text{mask}} - 1) \cdot \Delta \cdot (\Delta-1) \cdot (\Delta-2) \cdot (\Delta-3)$) +Degree: 6 (product of 6 linear polynomials) --- @@ -574,135 +571,91 @@ Active when: Last real row only ($L_{\text{real\_last}} = 1$) Degree: 2 (Lagrange Γ— difference) ---- - -## Opcode Constraint Relation +## Extra Relations -The Opcode Constraint Relation enforces that all operation codes (`op`) belong to the valid set: +To enforce the correctness of the opcodes and the accumulator lifecycle, we have a few additional relations. -$$\boxed{\texttt{op} \in \{0, 1, 2, 3, 4, 8\}}$$ +### Opcode Validity Check -Why needed: The `op` value is used in selector logic and potentially affects witness generation. Invalid opcodes could: +The Opcode Validity Check enforces that all operation codes (`op`) belong to the valid set: -- Inject arbitrary values into the accumulation formula -- Bypass range constraints (if `op = 0` has special handling) -- Break the integrity of the EccOpQueue transcript +$$\boxed{\texttt{op} \in \{0, 3, 4, 8\}}$$ Valid opcodes: -- `0`: NULL / No-op -- `1`: Point addition -- `2`: Scalar multiplication -- `3`: Equality check -- `4`: Reset accumulator -- `8`: [Special operation] +- `0`: No-op +- `3`: Equality and reset accumulator +- `4`: Scalar multiplication +- `8`: Point addition The constraint is expressed as a polynomial that has roots at the valid opcode values: -$$\boxed{\left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8) = 0}$$ - -The constraint is active when: +$$\boxed{\left( L_{\text{mini\_mask}} - 1 \right) \cdot \texttt{op} \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8) = 0}$$ -- $L_{\text{even}} = 1$ (even rows in mini-circuit), OR -- $L_{\text{mini\_mask}} = 1$ (masking rows in mini-circuit) +The constraint is active when $L_{\text{mini\_mask}} = 0$ (i.e., not a masking row in the mini-circuit). -When active: +Degree: 5 (degree-1 Lagrange Γ— degree-4 polynomial in `op`) -- If $\texttt{op} \in \{0, 1, 2, 3, 4, 8\}$, then $P(\texttt{op}) = 0$ βœ“ -- If $\texttt{op} \notin \{0, 1, 2, 3, 4, 8\}$, then $P(\texttt{op}) \neq 0$ βœ— (constraint fails) +--- -Active when: Even rows and mini-circuit masking rows +### Accumulator Consistency with No-op -Degree: 7 (degree-1 Lagrange Γ— degree-6 polynomial in `op`) +These subrelations ensure that when the opcode is `0` (no-op), the accumulator remains unchanged between even rows. +For the other opcodes (`3`, `4`, `8`), this constraint does not apply and must be skipped. +Thus, for each accumulator limb $i \in \{0, 1, 2, 3\}$, we must enforce: -Implementation as 5 Subrelations: For efficiency in the sumcheck protocol, the constraint is split into 5 subrelations: +$$\boxed{L_{\text{even}} \cdot (\texttt{op} - 3) \cdot (\texttt{op} - 4) \cdot (\texttt{op} - 8) \cdot \left( a_i^{\text{current}} - a_i^{\text{shifted}} \right) = 0}$$ -$$ -\boxed{\begin{align*} -&\text{Subrel 1:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 2) = 0 \\ -&\text{Subrel 2:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 3) = 0 \\ -&\text{Subrel 3:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 1) \cdot (\texttt{op} - 4) = 0 \\ -&\text{Subrel 4:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 2) \cdot (\texttt{op} - 3) = 0 \\ -&\text{Subrel 5:} \quad \left( L_{\text{even}} + L_{\text{mini\_mask}} \right) \cdot \texttt{op} \cdot (\texttt{op} - 8) = 0 -\end{align*}} -$$ - -Why split? - -- Each subrelation has lower degree (3-4 instead of 7) -- More efficient in sumcheck univariate polynomial computation - -Together, these 5 subrelations are equivalent to the full polynomial constraint. +Degree: 5 --- -## Accumulator Transfer Relation +### Accumulator Transfer Relation The Accumulator Transfer Relation manages the lifecycle of the accumulator across the circuit: 1. Initialization: Start with zero accumulator -2. Propagation: Copy accumulator from even rows to odd rows (data storage) -3. Computation: Update accumulator on even rows (handled by Non-Native Field Relation) -4. Finalization: Verify final accumulator matches expected result +2. Propagation: Copy accumulator from each odd row to the next even row +3. Finalization: Verify final accumulator matches expected result The relation consists of 12 subrelations: -- 4 for odd row propagation (copy previous value) +- 4 for propagation - 4 for initialization (set to zero) - 4 for finalization (check against expected result) ---- - -### Accumulator Structure - -The accumulator is a 254-bit value decomposed into 4 limbs: - -$$a^{\text{curr}} = a_0^{\text{curr}} + 2^{68} \cdot a_1^{\text{curr}} + 2^{136} \cdot a_2^{\text{curr}} + 2^{204} \cdot a_3^{\text{curr}}$$ - -Row-by-row behavior: - -- Even row $2i$: Accumulator updated via Non-Native Field Relation (computation) -- Odd row $2i+1$: Accumulator copied from even row $2i$ (storage for next cycle) - -### Subrelations 1-4: Odd Row Propagation - -Ensure accumulator does not change on odd rows (data storage rows). - -For each limb $i \in \{0, 1, 2, 3\}$: +#### Subrelations 1-4: Odd Row Propagation -$$\boxed{L_{\text{odd}} \cdot \left( a_i^{\text{curr}} - a_i^{\text{shift}} \right) = 0}$$ +Ensure that we correctly copy the accumulator from each odd row to the next even row. +This is because the previous accumulator value (in this iteration) becomes the "current" value on the next iteration. +Refer to the [Witness Trace Structure](../translator_vm/README.md#witness-trace-structure) for details on how we compute the accumulator iteratively. -This creates the "storage" pattern: +Thus, for each limb $i \in \{0, 1, 2, 3\}$: -- Even row $2i$: Computes new accumulator value -- Odd row $2i+1$: Stores this value unchanged -- Even row $2i+2$: Accesses odd row $2i+1$ via shift to get "previous" value +$$\boxed{L_{\text{odd}} \cdot (L_{\text{real\_last}} - 1) \cdot \left( a_i^{\text{current}} - a_i^{\text{shifted}} \right) = 0}$$ -Active when: Odd rows only ($L_{\text{odd}} = 1$) +This correctly "propagates" the accumulator value in computing the final accumulator. -Degree: 2 (Lagrange Γ— difference) +Active when: Odd rows only except the last real row in the mini-circuit (before masking). -### Subrelations 5-8: Initialization +Degree: 3 -Ensure the accumulator starts at zero at the beginning of the circuit. +#### Subrelations 5-8: Initialization -For each limb $i \in \{0, 1, 2, 3\}$: +Ensure the accumulator starts at zero at the beginning of the computation. Recall that we process the opcodes in reverse order, so the first "previous" accumulator corresponds to the last opcode processed. Thus, for each limb $i \in \{0, 1, 2, 3\}$: -$$\boxed{L_{\text{first}} \cdot a_i^{\text{curr}} = 0}$$ +$$\boxed{L_{\text{real\_last}} \cdot a_i^{\text{current}} = 0}$$ -This implies that at the first row, all limbs of the accumulator are zero, ensuring the accumulator starts at 0. +This implies that at the last real row (before masking), all limbs of the accumulator are zero, ensuring the accumulator starts at 0. -Active when: First row only ($L_{\text{first}} = 1$) +Degree: 2 (Lagrange Γ— limb) -Degree: 2 (Lagrange Γ— limb value) - -### Subrelations 9-12: Finalization +#### Subrelations 9-12: Finalization Verify the final accumulator value matches the expected result from ECCVM. - For each limb $i \in \{0, 1, 2, 3\}$: -$$\boxed{L_{\text{result}} \cdot \left( a_i^{\text{curr}} - a_i^{\text{expected}} \right) = 0}$$ +$$\boxed{L_{\text{result}} \cdot \left( a_i^{\text{current}} - a_i^{\text{expected}} \right) = 0}$$ where $a_i^{\text{expected}}$ is provided as a relation parameter (derived from ECCVM output). The ECCVM circuit computes the batched evaluation: @@ -710,63 +663,26 @@ $$a^{\text{expected}} = \sum_{j=0}^{n-1} x^{n-1-j} \cdot \left( \texttt{op}_j + The Translator must prove it computed the same value. The finalization check ensures that Translator's computation matches ECCVM's computation -Active when: Result row only ($L_{\text{result}} = 1$) +Active when: Result row only ($L_{\text{result}} = 1$), this row corresponds to the first real opcode in the mini-circuit. Degree: 2 (Lagrange Γ— difference) -## Zero Constraints Relation +--- + +### Zero Constraints Relation -The Zero Constraints Relation enforces that all witness wires are zero outside the mini-circuit. +The Zero Constraints Relation enforces that certain witness wires are zero outside the mini-circuit. Due to interleaving, the full circuit is 16Γ— larger than the mini-circuit: - Mini-circuit: $2^{13} = 8,192$ rows (actual computation) - Full circuit: $2^{17} = 131,072$ rows (for interleaving optimization) -Rows outside the mini-circuit (rows 8,192 to 131,071) must be zero. The relation consists of **68 subrelations**: - -Range constraint microlimb wires (64 total): - -- All `*_RANGE_CONSTRAINT_*` columns (see [Witness Trace Structure](#witness-trace-structure)) -- These hold 14-bit microlimbs for decomposition -- Must be zero outside mini-circuit to avoid polluting the permutation - -Transcript wires (4 total): - -- `OP`: Opcode -- `X_LO_Y_HI`: Encodes $P_{x,\text{lo}}$ / $P_{y,\text{hi}}$ -- `X_HI_Z_1`: Encodes $P_{x,\text{hi}}$ / $z_1$ -- `Y_LO_Z_2`: Encodes $P_{y,\text{lo}}$ / $z_2$ - -### Subrelations 1-68: Zero Outside Mini-Circuit - -General pattern for each wire $w$: +Rows outside the mini-circuit (rows 8,192 to 131,071) must be zero. All the range constraint microlimb wires and transcript wires should be zero outside the mini-circuit. Thus, for each such wire $w$, we enforce: -$$\boxed{\neg \left( L_{\text{in\_mini}} \lor L_{\text{mask}} \right) \implies w = 0}$$ +$$\boxed{\left( L_{\text{even}} + L_{\text{odd}} - 1 \right) \cdot (L_{\text{mini\_mask}} - 1) \cdot w = 0}$$ -Equivalently (using De Morgan's law and constraint form): +Note that the Lagrange product is $0$ in the mini-circuit and $-1$ outside the mini-circuit, so this forces $w = 0$ there. -$$\boxed{\left( 1 - L_{\text{even}} - L_{\text{odd}} - L_{\text{mini\_mask}} + \text{products} \right) \cdot w = 0}$$ +Degree: 3 (Lagrange product Γ— wire) -where: - -- $L_{\text{even}}$: Lagrange for even rows in mini-circuit -- $L_{\text{odd}}$: Lagrange for odd rows in mini-circuit -- $L_{\text{mini\_mask}}$: Lagrange for masking rows in mini-circuit - -Active when: All rows outside the mini-circuit - -Degree: 2 (Lagrange polynomial products Γ— wire value) - -### Special Case: No-Op Rows - -When `op = 0` (no-op) on even rows, additional constraints force range wires to zero even within the mini-circuit. - -No-op rows don't contribute to the accumulation, so their witness values should be zero. - -$$\boxed{L_{\text{even}} \cdot (1 - \texttt{op}) \cdot w = 0}$$ - -Active when: Even rows with `op = 0` - -Degree: 3 - -Additional no-op constraints: All range wires also zero when `op = 0` on even rows. +--- From ce85cbbd3a669f17b3a6b7362e3cabfd775d65e6 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Wed, 7 Jan 2026 14:26:43 +0000 Subject: [PATCH 27/29] add mini circuit layout. --- .../src/barretenberg/translator_vm/README.md | 168 ++++++++++++++++-- 1 file changed, 156 insertions(+), 12 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 57540fc61cee..210867645d79 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -254,20 +254,164 @@ Some columns are "virtual" and not explicitly stored in the witness trace. Inste - Interleaved columns for range constraint microlimbs (computed from the physical microlimb columns) - Sorted (ordered) columns for range constraint microlimbs (computed by sorting the physical microlimb columns) +### Mini-Circuit Layout + +The mini-circuit layout is illustrated below: + +- The first 4 columns represent the `EccOpQueue` transcript +- The next 13 columns represent limb decompositions +- The last 64 columns represent microlimb decompositions +- Let $n$ = total number of rows in the mini-circuit +- Let $m_{\textsf{start}}$ = number of rows for randomness at start +- Let $m$ = number of rows for randomness at the end +- Let $z_1$ = number of initial no-op rows (to ensure column polynomials are shiftable) + +The purple boxes represent zero values while the grey boxes represent randomness values (in the op queue only). The orange boxes represent the main op queue rows where the actual ECC operations are processed. + +$$ +\begin{array}{rlllll} +z_1 +& +\overbrace{ + \textcolor{violet}{ + \boxed{ + \hspace{0.95cm} + } + } +}^{4} +& +\textsf{\scriptsize $\longleftarrow$ initial no-op} +& +\overbrace{ +\textcolor{violet}{ + \boxed{ + \hspace{1.45cm} + } +} +}^{13} +& +\overbrace{ +\textcolor{violet}{ + \boxed{ + \hspace{3.85cm} + } +} +}^{64} +\\[2pt] +m_{\textsf{start}} +& +\textcolor{grey}{ + \boxed{ + \begin{array}{c} + \hspace{0.6cm} + \\ + \end{array} + } +} +& +\textsf{\scriptsize $\longleftarrow$ start randomness} +& +\textcolor{violet}{ + \boxed{ + \begin{array}{c} + \hspace{1.1cm} + \\ + \end{array} + } +} +& +\textcolor{violet}{ + \boxed{ + \begin{array}{c} + \hspace{3.5cm} + \\ + \end{array} + } +} +\\ \\[-10pt] +n - m_{\textsf{start}} - m - z_1 & +\textcolor{orange}{ + \boxed{ + \begin{array}{c} + \hspace{0.6cm} + \\ \\ \\ \\ \\ \\ \\ + \end{array} + } +} +& +\textsf{\scriptsize $\longleftarrow$ main ops} +& +\textcolor{orange}{ + \boxed{ + \begin{array}{c} + \hspace{1.1cm} + \\ \\ \\ \\ \\ \\ \\ + \end{array} + } +} +& +\textcolor{orange}{ + \boxed{ + \begin{array}{c} + \hspace{3.5cm} + \\ \\ \\ \\ \\ \\ \\ + \end{array} + } +} +\\ \\[-10pt] +m +& +\textcolor{grey}{ + \boxed{ + \begin{array}{c} + \hspace{0.6cm} + \\ + \end{array} + } +} +& +\textsf{\scriptsize $\longleftarrow$ end randomness} +& +\textcolor{violet}{ + \boxed{ + \begin{array}{c} + \hspace{1.1cm} + \\ + \end{array} + } +} +& +\textcolor{violet}{ + \boxed{ + \begin{array}{c} + \hspace{3.5cm} + \\ + \end{array} + } +} +\end{array} +$$ + +In our implementation, mini-circuit size is $n = 2^{13}$. We have $z_1 = 2$ (one no-op at the start to ensure shiftability), $m_{\textsf{start}} = 6$ (rows for three random ops at start), and $m = 4$ (rows for two random ops at end). Thus, the number of main operation rows is $n - m_{\textsf{start}} - m - z_1 = 8180$. + +> **Note:** The randomness rows at the start are due to the blinding required for the tail kernel, for which the ECC ops are prepended. The randomness rows at the end are for the blinding of the hiding kernel, for which the ECC ops are appended. See [MERGE protocol documentation](../goblin/MERGE_PROTOCOL.md#zk-considerations) for more details. + ### Lagrange Polynomials (Precomputed) -The Translator circuit uses ZERO selector polynomials (`NUM_SELECTORS = 0`). -Instead, the circuit uses Lagrange polynomials to control which constraints are active: - -| Polynomial | Description | Active Rows | -| ------------------------------ | ------------------------------- | ---------------------------------------------------------------------------- | -| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in \{0, 2, 4, ..., 8190\}$ (mini) | -| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in \{1, 3, 5, ..., 8191\}$ (mini) | -| `lagrange_first` | First row | $i = 0$ | -| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | -| `lagrange_result_row` | Row containing final result | $i = 8$ (mini, equals no of rows are to be left for random ops at the start) | -| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | -| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | +The circuit uses Lagrange polynomials to control which constraints are active: + +| Polynomial | Description | Active Rows | +| ------------------------------ | ----------------------------------------- | ---------------------------------------------------------------------------- | +| `lagrange_first` | First row | $i = 0$ | +| `lagrange_real_last` | Last row in full circuit (before masking) | $i = 2^{17} - m \cdot I_{\text{size}} - 1$ | +| `lagrange_last` | Last row in full circuit | $i = 2^{17} - 1$ | +| `lagrange_masking` | Masking rows in full circuit | $i \in \{2^{17} - m \cdot I_{\text{size}}, \ldots, 2^{17} - 1\}$ | +| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in \{0, 2, 4, ..., 8190\}$ (mini) | +| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in \{1, 3, 5, ..., 8191\}$ (mini) | +| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | +| `lagrange_result_row` | Row containing final result | $i = 8$ (mini, equals no of rows are to be left for random ops at the start) | +| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | +| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | ## Interleaving: The Key Optimization From 6a0ca82415be13d9601b327b7eab747755a7a12a Mon Sep 17 00:00:00 2001 From: suyash67 Date: Wed, 7 Jan 2026 19:58:46 +0000 Subject: [PATCH 28/29] upd lagrange. --- .../src/barretenberg/translator_vm/README.md | 88 ++++++++++++++----- 1 file changed, 64 insertions(+), 24 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index 210867645d79..e563bdcc4730 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -262,11 +262,20 @@ The mini-circuit layout is illustrated below: - The next 13 columns represent limb decompositions - The last 64 columns represent microlimb decompositions - Let $n$ = total number of rows in the mini-circuit -- Let $m_{\textsf{start}}$ = number of rows for randomness at start -- Let $m$ = number of rows for randomness at the end +- Let $r_{\textsf{start}}$ = number of rows for randomness at start +- Let $r_{\textsf{end}}$ = number of rows for randomness at the end - Let $z_1$ = number of initial no-op rows (to ensure column polynomials are shiftable) -The purple boxes represent zero values while the grey boxes represent randomness values (in the op queue only). The orange boxes represent the main op queue rows where the actual ECC operations are processed. +Color coding in the diagram: + +- Purple boxes ($\textcolor{violet}{\textsf{purple}}$): Zero values or initial values + - For all columns: initial no-op row contains zeros + - For non-OP columns (13 limb + 64 microlimb): end randomness region initially contain zeros, later overwritten with random values for ZK sumcheck +- Grey boxes ($\textcolor{grey}{\textsf{grey}}$): Random values (no-op) in the 4 OP queue columns only + - These remain as random values from the random op processing + - Serve Merge Protocol ZK hiding +- Orange boxes ($\textcolor{orange}{\textsf{orange}}$): Main operation rows + - Contains actual ECC operation data for circuit computation $$ \begin{array}{rlllll} @@ -298,7 +307,7 @@ z_1 } }^{64} \\[2pt] -m_{\textsf{start}} +r_{\textsf{start}} & \textcolor{grey}{ \boxed{ @@ -329,7 +338,7 @@ m_{\textsf{start}} } } \\ \\[-10pt] -n - m_{\textsf{start}} - m - z_1 & +n - r_{\textsf{start}} - r_{\textsf{end}} - z_1 & \textcolor{orange}{ \boxed{ \begin{array}{c} @@ -359,7 +368,7 @@ n - m_{\textsf{start}} - m - z_1 & } } \\ \\[-10pt] -m +r_{\textsf{end}} & \textcolor{grey}{ \boxed{ @@ -392,26 +401,43 @@ m \end{array} $$ -In our implementation, mini-circuit size is $n = 2^{13}$. We have $z_1 = 2$ (one no-op at the start to ensure shiftability), $m_{\textsf{start}} = 6$ (rows for three random ops at start), and $m = 4$ (rows for two random ops at end). Thus, the number of main operation rows is $n - m_{\textsf{start}} - m - z_1 = 8180$. +In our implementation, mini-circuit size is $n = 2^{13}$. We have $z_1 = 2$ (one no-op at the start to ensure shiftability), $r_{\textsf{start}} = 6$ (rows for three random ops at start), and $r_{\textsf{end}} = 4$ (rows for two random ops at end). Thus, the number of main operation rows is $n - r_{\textsf{start}} - r_{\textsf{end}} - z_1 = 8180$. + +The random ops serve dual purposes for zero-knowledge: + +**1. Merge Protocol ZK** (Grey boxes in 4 OP columns): + +- The 3 random ops at start add random values to the 4 ECC op queue columns (tail kernel blinding, ops prepended) +- The 2 random ops at end add random values to the 4 ECC op queue columns (hiding kernel blinding, ops appended) +- Together these contribute 40 random coefficients (10 per wire) to hide merge protocol evaluations +- See [MERGE_PROTOCOL.md](../goblin/MERGE_PROTOCOL.md#zk-considerations) for the degree-of-freedom analysis + +**2. ZK Sumcheck Masking** (Initially purple, then filled with random for non-OP columns): -> **Note:** The randomness rows at the start are due to the blinding required for the tail kernel, for which the ECC ops are prepended. The randomness rows at the end are for the blinding of the hiding kernel, for which the ECC ops are appended. See [MERGE protocol documentation](../goblin/MERGE_PROTOCOL.md#zk-considerations) for more details. +- The last $r_{\textsf{end}} = 4$ rows align exactly with `NUM_DISABLED_ROWS_IN_SUMCHECK = 4` (denoted as $m$ in the Lagrange table below) +- For the 4 OP queue columns: random values remain from the random ops +- For the remaining 77 columns (13 limb + 64 microlimb): + - Initially filled with zeros during random op processing + - These zeros are overwritten with random field elements during proving key construction + - This masking hides polynomial evaluations in ZK sumcheck ### Lagrange Polynomials (Precomputed) -The circuit uses Lagrange polynomials to control which constraints are active: - -| Polynomial | Description | Active Rows | -| ------------------------------ | ----------------------------------------- | ---------------------------------------------------------------------------- | -| `lagrange_first` | First row | $i = 0$ | -| `lagrange_real_last` | Last row in full circuit (before masking) | $i = 2^{17} - m \cdot I_{\text{size}} - 1$ | -| `lagrange_last` | Last row in full circuit | $i = 2^{17} - 1$ | -| `lagrange_masking` | Masking rows in full circuit | $i \in \{2^{17} - m \cdot I_{\text{size}}, \ldots, 2^{17} - 1\}$ | -| `lagrange_even_in_minicircuit` | Even indices in mini-circuit | $i \in \{0, 2, 4, ..., 8190\}$ (mini) | -| `lagrange_odd_in_minicircuit` | Odd indices in mini-circuit | $i \in \{1, 3, 5, ..., 8191\}$ (mini) | -| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | -| `lagrange_result_row` | Row containing final result | $i = 8$ (mini, equals no of rows are to be left for random ops at the start) | -| `lagrange_masking` | Masking rows for zero-knowledge | Last few rows | -| `lagrange_mini_masking` | Masking within mini-circuit | Last rows of mini-circuit | +The circuit uses Lagrange polynomials to control which constraints are active: ($I_{\text{size}} = 16$ is the number of columns interleaved together) + +| Polynomial | Description | Active Rows | +| ------------------------------ | ----------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `lagrange_first` | First row | $i = 0$ | +| `lagrange_real_last` | Last row in full circuit (before masking) | $i = 2^{17} - m \cdot I_{\text{size}} - 1$ | +| `lagrange_last` | Last row in full circuit | $i = 2^{17} - 1$ | +| `lagrange_masking` | Masking rows in full circuit | $i \in [2^{17} - m \cdot I_{\text{size}}, \ 2^{17})$ | +| `lagrange_mini_masking` | Masking rows in mini circuit | $i \in [z_1, \ z_1 + r_{\textsf{start}}) \cup [n - r_{\textsf{end}}, \ n)$ | +| `lagrange_even_in_minicircuit` | Even indices in real mini-circuit | $i \in \{u \ \| \ u \ \% \ 2 = 0, \ (z_1 + r_{\textsf{start}}) \leq u < n - r_{\textsf{end}}\}$ | +| `lagrange_odd_in_minicircuit` | Odd indices in real mini-circuit | $i \in \{u \ \| \ u \ \% \ 2 = 1, \ (z_1 + r_{\textsf{start}}) \leq u < n - r_{\textsf{end}}\}$ | +| `lagrange_last_in_minicircuit` | Last row in mini-circuit | $i = 8191$ (mini) | +| `lagrange_result_row` | Row containing final accumulator result | $i = (z_1 + r_{\textsf{start}})$ | +| `lagrange_last_in_minicircuit` | Last real row in mini-circuit | $i = (n - r_{\textsf{end}}) - 1$ | +| | | | ## Interleaving: The Key Optimization @@ -1343,8 +1369,20 @@ $$ ### Step 7: Zero-Knowledge Masking -To achieve zero-knowledge, the prover adds random values to the end of polynomials. -For each of the witness polynomials, the masking region is defined as the last $m$ rows of the mini-circuit size, indexed as: +To achieve zero-knowledge, the translator uses two independent masking mechanisms: + +#### ZK Sumcheck Masking (Non-OP-Queue Wires) + +To hide polynomial evaluations used in ZK sumcheck, random values are added to the last $m = r_{\textsf{end}} = 4$ rows of the mini-circuit for all non-OP-queue wires (13 limb decomposition columns, 64 microlimb columns). + +1. During random op processing, these columns are initially filled with zeros +2. During proving key construction, these zeros are overwritten with random field elements +3. The Lagrange polynomial `lagrange_mini_masking` marks these last 4 rows as masked + +#### Permutation Argument Masking (Ordered Polynomials) + +For the permutation argument over microlimbs, a separate masking mechanism is used. +For each of the witness polynomials, the masking region is defined as the last $m = r_{\textsf{end}}$ rows of the mini-circuit size, indexed as: $$[n - m, \ n).$$ @@ -1352,6 +1390,8 @@ After interleaving, the 4 interleaved polynomials have random values at position $$[N - m \cdot I_{\textsf{size}}, \ N).$$ +Where $m = r_{\textsf{end}} = 4$ (the same 4 rows used for ZK sumcheck masking). + #### Redistributing Randomness to Ordered Polynomials The ordered polynomials must be committed (unlike interleaved polynomials, which are virtual). To maintain zero-knowledge, the prover redistributes the random values from the 4 interleaved to the 5 ordered polynomials. As illustrated above, each ordered polynomial receives approximately an equal share of the randomness from the interleaved polynomials. The total number of random values in the interleaved polynomials: From 6018850ad72787aa64fee2f3fc9150b0e4122440 Mon Sep 17 00:00:00 2001 From: suyash67 Date: Thu, 8 Jan 2026 09:07:13 +0000 Subject: [PATCH 29/29] address comments. --- .../src/barretenberg/translator_vm/README.md | 2 +- .../barretenberg/translator_vm/RELATIONS.md | 35 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/README.md b/barretenberg/cpp/src/barretenberg/translator_vm/README.md index e563bdcc4730..2255dec4ddd9 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/README.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/README.md @@ -96,7 +96,7 @@ We verify this by proving the equation holds: 2. modulo $r$ (natively in $\mathbb{F}_r$) 3. with range constraints on all limbs (prevents overflow/underflow) -By the Chinese Remainder Theorem, since $2^{272} \cdot r > 2^{514}$ exceeds the maximum possible value, the equation must hold in integers, and thus modulo $q$. +By the Chinese Remainder Theorem, since $2^{272} \cdot r > 2^{514}$ exceeds the maximum possible value, the equation must hold in integers, and thus modulo $q$. More details on this relation are in [RELATIONS.md](RELATIONS.md#non-native-field-relations). ## Witness Trace Structure diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md index 49da040b66a1..6f6f5e5472de 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md +++ b/barretenberg/cpp/src/barretenberg/translator_vm/RELATIONS.md @@ -4,15 +4,15 @@ The translator VM enforces several relations/constraints to ensure the correctne Since we follow a two-row trace structure, some relations are only active on even rows, while others are only active on odd rows. Below is a summary of the relations and their activation patterns. -| Constraint | No of subtrelations | Active on even rows | Active on odd rows | -| ----------------------------- | ------------------- | ------------------- | ------------------ | -| Non-Native Field Relation | 3 | βœ“ | βœ— | -| Decomposition Relation | 48 | βœ“ | βœ“ | -| Permutation Relation | 2 | βœ“ | βœ“ | -| Delta Range Constraint | 10 | βœ“ | βœ“ | -| Opcode Constraint Relation | 5 | βœ“ | βœ“ | -| Accumulator Transfer Relation | 12 | βœ— | βœ“ (propagation) | -| Zero Constraints Relation | 68 | βœ“ | βœ“ | +| Constraint | No of subrelations | Active on even rows | Active on odd rows | +| ----------------------------- | ------------------ | ------------------- | ------------------ | +| Non-Native Field Relation | 3 | βœ“ | βœ— | +| Decomposition Relation | 48 | βœ“ | βœ“ | +| Permutation Relation | 2 | βœ“ | βœ“ | +| Delta Range Constraint | 10 | βœ“ | βœ“ | +| Opcode Constraint Relation | 5 | βœ“ | βœ“ | +| Accumulator Transfer Relation | 12 | βœ— | βœ“ (propagation) | +| Zero Constraints Relation | 68 | βœ“ | βœ“ | Lagrange selectors for activation: @@ -112,8 +112,19 @@ If this equation holds: 2. Modulo $r$ (native $\mathbb{F}_r$ computation), and 3. All values are properly range-constrained -then it must hold in integers. This is because the Chinese Remainder Theorem guarantees that if an equation holds modulo two coprime moduli whose product exceeds the maximum possible value of the equation, then it holds over the integers. Here, the maximum possible value of the left-hand side is less than $2^{514}$, while the moduli product is $2^{272} \cdot r > 2^{525} > 2^{514}$. -See [bigfield documentation](barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. +then it must hold in integers. This is because the Chinese Remainder Theorem guarantees that if an equation holds modulo two coprime moduli whose product exceeds the maximum possible value of the equation, then it holds over the integers. +Since all values are in $\mathbb{F}_q$, i.e., they are less than $q$, we have: + +$$ +\begin{aligned} +\textsf{max}(a^{\text{prev}} \cdot x + \texttt{op} + P_x \cdot v + P_y \cdot v^2 + z_1 \cdot v^3 + z_2 \cdot v^4) &< 5q^2 < 5 \cdot (2^{254})^2 < 2^{511} +\\ +\textsf{max}(\mathcal{Q} \cdot q) &< q^2 < (2^{254})^2 < 2^{508} +\end{aligned} +$$ + +Therefore, the maximum possible value of the left-hand side is less than $2^{511}$, while the moduli product is $2^{272} \cdot r > 2^{525} > 2^{511}$. +See [bigfield documentation](../stdlib/primitives/bigfield/README.md) for more details on non-native field arithmetic. The non-native field relation is enforced through three separate subrelations: @@ -388,7 +399,7 @@ Subrelations 22-41 apply this pattern to: | Quotient | 4 | 12, 12, 12, 10 bits | | | | | -### Category 5: Transcript Value Composition (Subrelations 42-47) +### Category 5: Transcript Value Reconstruction (Subrelations 42-47) These prove that 68-bit limbs correctly reconstruct EccOpQueue transcript values. General pattern for composing two limbs into a transcript value: