diff --git a/.gitignore b/.gitignore index 86e14db85..6fecada04 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ scripts/__pycache__/ scripts/tests/__pycache__/ .cursor/ +crates/akita-types/src/sis/generated_l2_sis_table/audit.csv diff --git a/Cargo.lock b/Cargo.lock index 20bffb2d4..8a2dc4965 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,7 @@ dependencies = [ "akita-field", "akita-schedules", "akita-types", + "libm", ] [[package]] @@ -195,6 +196,7 @@ dependencies = [ "num-bigint", "num-traits", "rayon", + "sha2", "sha3 0.10.9", "thiserror", ] @@ -248,6 +250,7 @@ dependencies = [ "akita-challenges", "akita-config", "akita-field", + "akita-prover", "akita-serialization", "akita-sumcheck", "akita-transcript", diff --git a/book/src/how/configuration.md b/book/src/how/configuration.md index 89623f975..57ab8ddd8 100644 --- a/book/src/how/configuration.md +++ b/book/src/how/configuration.md @@ -1,7 +1,5 @@ # Configuration and planning -> **Status:** stub. Part of the initial Akita Book scaffold. - How a preset turns into a concrete recursion schedule: the single `CommitmentConfig` trait, the `LevelParams` it produces, and the planner that selects (or searches for) the schedule and prices its proof size. @@ -20,7 +18,7 @@ claims live in a proper extension (`EXT_DEGREE > 1`, `fp32` / `fp64`), never on field bit-width. See [Fold path and field geometry](./proving/fold-path.md). -**Sources to fold in** +**Implementation map** - `crates/akita-config/src/lib.rs:54-120`. - `crates/akita-config/src/proof_optimized/`. @@ -32,7 +30,7 @@ What a schedule fixes per level (decomposition depth and ring/ext degrees), the `LevelParams` representation, and the invariants the verifier re-derives rather than trusts. -**Sources to fold in** +**Implementation map** - `crates/akita-types/src/layout/params.rs:41-97`. - `crates/akita-types/src/schedule.rs` (`FoldStep`, `TerminalWitnessPlan`, `Schedule`). @@ -46,11 +44,93 @@ expansion, and the schedule-search DP fallback (verifier-reachable, so it must reject malformed input, never panic). The feature-gated `akita-schedules` crate owns shipped table data. The verifier-reachable proof-size formula. -**Sources to fold in** +**Implementation map** - [`crates/akita-planner/README.md`](../../../crates/akita-planner/README.md) for the current planner overview, search model, generated tables, and supported features. -- `crates/akita-planner/src/` (`resolve.rs`, `planner.rs`, `generated/`). +- `crates/akita-planner/src/` owns search and emission. Runtime catalog + expansion and audit live in `crates/akita-schedules/src/`. - `crates/akita-types/src/proof_size.rs` and `crates/akita-types/src/layout/proof_size.rs` (`level_proof_bytes`, planned witness sizing). - Paper §3.11 `sec:akita-planner` (objective/constraints, the dynamic program, generated schedules). -- `crates/akita-config/src/generated_families.rs`, `crates/akita-schedules/src/generated/`, `crates/akita-planner/src/resolve.rs` (`resolve_schedule`). +- `crates/akita-planner/src/generated_families.rs`, + `crates/akita-schedules/src/generated/`, and + `crates/akita-config/src/lib.rs` (`resolve_schedule`). - `book/src/usage/profiling.md` and `.github/workflows/profile-bench.yml`. + +### Selective L2 candidates + +The coefficient `L∞` route remains available at every fold. A production +preset may also enable the typed `L2` response model. Every shipped +fp32, fp64, and fp128 dense and one-hot family enables it. This includes each +generated multi-chunk and recursive companion. + +The planner always retains its ordinary L infinity candidate. From level 3 +onward, an enabled family also evaluates the same canonical block split with +an L2 A matrix for response bases 16 and above. Basis 8 is not admitted because +it caused deterministic stage-2 folded-oracle consistency failures in two D64 +production profiles. That geometry remains unsupported until the protocol cause +is fixed and validated. The planner keeps an eligible alternative only when it +lowers the A rank. This adds at most one modeled L2 alternative per basis and +dimension state, which keeps the suffix search bounded. + +The planner estimates the squared norm of the actual recursive witness. It +applies the following rules. + +* A dense root uses the centered digit second moment for every field digit + plane. A one-hot root uses the exact number of unit entries. +* The Z part uses the centered residues of a rounded normal variable. Its + variance comes from the previous source energy and the challenge energy. +* The E, T, and R parts use the centered field digit moment for every live + scalar. The final digit plane uses its actual remaining field width. +* Negative binary compression contributes one half unit of expected energy per + coefficient. +* Extension tensor packing multiplies the logical energy by `(2K - 1) / K`, + where `K` is the extension degree. + +The planner rounds each source estimate upward while retaining seven leading +bits. This adds less than `1/64` relative error and keeps the suffix search +small. It then multiplies the source estimate by the challenge squared energy, +a 1.03 model envelope, and a 1.06 response allowance. The combined factor is +1.0918. If the model envelope bounds the conditional mean, Markov's inequality +gives at least `3/53` acceptance probability on each independent attempt. The +protocol permits 4096 attempts. + +The 1.03 factor covers approximations in the normal, field digit, challenge +covariance, and finite mixing models. It is an empirical completeness margin, +not a soundness claim. In cross-profile validation proofs, the aggregate source +estimate ranged from 0.20 percent below to 8.95 percent above the measured +source energy. Across 52 selected L2 responses in 14 profile modes, every proof +passed both verifier modes. Frozen cap slack ranged from 6.90 to 18.18 percent. +One response used nonce one, while the other 51 used nonce zero. + +The field digit model is exact for uniform power of two residues, apart from +the negligible pseudo-Mersenne boundary. Recursive setup values can retain +correlation. This usually lowers their E and T energy, so the model is +conservative. The widest observed E and T overestimates were about 33.5 percent +in one recursive multi-group W8 setup state. Its aggregate cap still had 18.18 +percent slack. + +The suffix comparison includes the norm proof, A payload, next witness, later +folds, and terminal response. A smaller A rank can reduce the next witness +enough to remove a fold, but the planner keeps `L∞` when the extra norm proof +costs more than the suffix saves. + +This model affects completeness and schedule selection only. Once the planner +selects a route, its concrete cap is frozen into the generated schedule. The +prover rejection samples against that cap and the verifier enforces the same +value. The SIS calculation therefore still uses the public accepted cap and +does not trust the statistical model. + +If the typed model is disabled, the geometry is ineligible, no Euclidean SIS +row exists, or the L2 route does not lower the A rank, the planner keeps the L +infinity candidate. +Runtime expansion never reruns the model. It only checks the frozen schedule. + +A clear terminal L2 candidate has no recursive norm proof. The verifier checks +the decoded response norm directly. The planner may use the certified energy +to estimate a smaller Golomb payload for candidate comparison. The scheduled +Golomb byte cap and the payload grind remain unchanged. + +Generated schedule identity includes the cap policy and the separate L2 table +digest. Runtime expansion derives the route, cap, proof shape, and A rank from +that identity. A mismatch between the preset policy and generated catalog is +an error. diff --git a/book/src/how/proving/sumcheck-stages.md b/book/src/how/proving/sumcheck-stages.md index f66672e23..97a2de481 100644 --- a/book/src/how/proving/sumcheck-stages.md +++ b/book/src/how/proving/sumcheck-stages.md @@ -5,6 +5,8 @@ witness: 1. **Stage 1 — digit range check.** Proves that every witness entry is a valid balanced digit and outputs one evaluation of the virtual range-image table. + A fold on the `L2` route also proves the complete physical response norm in + the final Stage 1 substage. 2. **Stage 2 — fused relation sumcheck.** Proves the ring-switched fold relation and binds both Stage 1's virtual range-image value and the opening claim carried into the fold to the committed witness; the resulting witness @@ -12,10 +14,10 @@ witness: 3. **Stage 3 — setup product sumcheck.** Optionally carries a recursive setup contribution together with the next opening. -This chapter explains the Stage-1 range protocol and the Stage-2 fused -relation protocol in detail. Stage 3 is summarized at the end. The terminal -fold, which runs none of these sumchecks, is covered in -[The proving protocol](./proving.md). +This chapter explains the Stage 1 range protocol and the Stage 2 fused relation +protocol in detail. Stage 3 is summarized at the end. The terminal fold runs +none of these sumchecks. When it uses an L2 route, the verifier computes the +clear response norm directly. See [The proving protocol](./proving.md). ## Stage 1: digit range check @@ -317,6 +319,34 @@ vertices. The proof therefore carries the independent `range_image_evaluation` field ([`AkitaStage1Proof`](https://github.com/LayerZero-Labs/akita/blob/main/crates/akita-types/src/proof/levels.rs)). +### Optional physical norm term + +An `L2` selected fold proves the squared norm of the complete physical folded +response. The physical response domain contains every live Z coefficient once +and assigns zero to padding addresses. `WitnessLayout` defines this domain for +the prover, verifier, and proof size code. + +For a large field, the final Stage 1 substage batches the range leaf with + +$$ +S = \sum_x z(x)^2. +$$ + +The proof carries the public integer value $S$, one additional coefficient in +each final sumcheck round, and the final virtual evaluation of $z$. The verifier +checks $S$ against the cap stored in the schedule. + +For a small field, the allowed digit range may make the full square sum wrap +the base field. The schedule then divides the physical domain into fixed +blocks and proves bounded limb inner products. Each subclaim has a unique +centered integer lift because its public bound is below half the modulus. The +verifier reconstructs $S$ with checked integer arithmetic and rejects a wrong +subclaim count, an overflow, or a value above the cap. + +The proof stream has no route header. The schedule determines whether the norm +proof exists and gives its exact shape. An `L∞` fold uses the ordinary Stage 1 +shape and carries no norm values. + ### Domain and challenge order Stage 1 views the digits as one flat Boolean table. The live witness occupies a @@ -343,7 +373,7 @@ tie that virtual value to the committed witness. ## Stage 2: fused relation sumcheck -Stage 2 proves three statements about the same committed digit witness $w$: +Stage 2 always proves three statements about the same committed digit witness $w$: 1. $w$ satisfies the ring-switched fold relation; 2. Stage 1's virtual range-image value is correctly derived from $w(w+1)$; and @@ -353,6 +383,14 @@ The protocol fuses all three statements into one sumcheck. We first isolate the fold-relation term to make its matrix-row dimension explicit, then incorporate the range-image and opening-consistency terms. +When Stage 1 also proves a physical norm, Stage 2 adds the Z virtualization +relation derived from the schedule. It proves that each final physical response +or limb evaluation is the balanced basis recomposition of the committed Z digit +plane evaluations at the same point. The transcript samples the batching +challenge after it has absorbed all Stage 1 claims, including the ordinary +range image. This order prevents one false virtual relation from canceling +another. + ### Start with the ring relation Let $w_j(X)$ be the $j$-th ring element encoded by the digit witness, and let diff --git a/book/src/how/security.md b/book/src/how/security.md index 4cfcc3f02..221ec228d 100644 --- a/book/src/how/security.md +++ b/book/src/how/security.md @@ -1,7 +1,5 @@ # Security model -> **Status:** stub. Part of the initial Akita Book scaffold. - One canonical security narrative: the hardness assumption, how Ajtai ranks connect to security bits, the weak-binding fold price, and the current SIS table model. Keep the marketing claim separate from audited reality. See @@ -41,10 +39,15 @@ successor witnesses, cutoff kind, cap provenance, and role provenance. These are audit inputs, not verifier-visible state. The shared table digest commits to the compact runtime table and its policy audit files together. -The planner derives role bounds as coefficient-`L∞` values because those are the -values enforced by the protocol. It does not convert production role bounds -through a Euclidean `d * B^2` key. The Euclidean estimator code remains an -offline comparison path. +The planner has two production tables for the committed A role. The default +table uses a coefficient `L∞` bound. A separate Euclidean table is available +only when the selected fold proves a complete physical squared `L2` norm. Both +tables use the 128 bit quantum ADPS16 policy and have separate digests. + +For the Euclidean table, the scalar SIS dimensions are `n = rank * D` and +`m = width * D`. The length bound is the square root of the complete collision +norm. The complete norm already includes every scalar coordinate, so the +planner does not multiply it by the matrix width again. The production lookup is table-only. Verifier-reachable code must reject a missing table row or unsupported floor with `AkitaError`; it must not run the @@ -60,9 +63,10 @@ The complete decision, assumptions, claim language, certificates, and implementation acceptance criteria live in [`specs/sis-quantum128-scalar-n-table.md`](../../../specs/sis-quantum128-scalar-n-table.md). -**Sources to fold in** +**Implementation map** -- `crates/akita-types/src/sis/mod.rs`, `ajtai_key.rs`, `generated_sis_table/`, `norm_bound.rs`. +- `crates/akita-types/src/sis/mod.rs`, `ajtai_key.rs`, `l2_table.rs`, + `physical_l2.rs`, `generated_sis_table/`, and `norm_bound.rs`. - Paper §2.2 `def:msis`, §3.12 `sec:batched-soundness` ("MSIS targets", "Two norm models"). - `docs/security-posture.md`, `specs/sis-quantum128-scalar-n-table.md`. - `crates/akita-types/src/sis/generated_sis_table/policy_audit.csv` (canonical @@ -70,13 +74,69 @@ implementation acceptance criteria live in ## Norm bounds and weak binding -The fold-response bounds, the committed-fold price as relaxed binding, the -batched weak-opening definition, and why range checks do not lower the binding -norm. Keep the fold-reprice correction explicit. +Every committed level records one A role security route. The coefficient +`L∞` route is always available. Every production profile also enables the typed +`L2` response model from level 3 onward. The root and early folds do not use the +`L2` route. A clear terminal response may use the route because the verifier +computes its complete integer norm directly. + +Let `kappa_1` be the maximum physical coefficient `L1` norm of the fold +challenge. Let `gamma` be the bound used for challenge multiplication. This is +either `kappa_1`, or a verifier enforced operator norm threshold. Let `Z_inf` +be the accepted physical coefficient bound on the response, and let `S` be the +accepted squared norm of the complete physical response. The two collision +bounds are -**Sources to fold in** +```text +C_inf = 8 * kappa_1 * Z_inf +C_2_sq = 64 * gamma^2 * S. +``` -- `crates/akita-types/src/sis/norm_bound.rs`, `layout/digit_math.rs` (`optimal_block_geometry_split`). +These formulas use the physical ring coefficients that enter the A role +Module SIS kernel. The small field extension embedding has already produced +those coefficients. Applying the Hachi logical to physical conversion at this +point would count that conversion twice. + +An `L∞` schedule carries no norm proof. An `L2` schedule binds its cap and +integer proof shape into the schedule descriptor. The verifier proves the norm +of the same physical Z coefficients used by the security calculation and then +checks the public cap. The existing digit range proof remains mandatory. For a +clear terminal response, the verifier decodes every coefficient, computes the +integer square sum, and checks the same cap without a sumcheck. + +The D64 and D128 L2 routes use transcript replayed operator norm rejection. +D64 uses the `(31, 11)` signed shell, a certified true threshold of 18, and a +strict fixed point threshold of 19. D128 reuses the production `(31, 0)` shell, +a certified true threshold of 13, and a strict threshold of 14. The strict +predicate only accepts when its integer interval calculation proves the bound. +Exact accepted support certificates show that each rejected family retains at +least 128 bits. + +The response model is an honest prover model, not a security assumption. An +eligible source carries a modeled squared norm through the typed Z, E, T, R, +compression, and extension packing operations. The planner rounds that source +estimate upward, adds a 3 percent model envelope, and permits a response up to +1.06 times the resulting conditional mean. Markov's inequality gives a +distribution free grinding bound if the 3 percent envelope covers the source +model error. The planner freezes the resulting cap into the schedule. The +verifier enforces that exact cap. A model error can make proving fail more +often, but it cannot make the verifier accept a response above the cap. + +The challenge response identity is exact when the accepted challenge has +scalar covariance. The fixed point operator norm filter is not assumed to have +perfect symmetry. Five million sampled orbit comparisons at D64 and D128 had no +acceptance mismatches. Full orbit tests also had no mixed outcomes. The measured +covariance defect was about 0.07 percent, and explicit orbit randomization did +not improve it. The protocol therefore keeps the existing challenge sampler. + +**Implementation map** + +- `crates/akita-types/src/sis/norm_bound.rs` owns the two physical collision + formulas. `crates/akita-types/src/proof/relation_range_image.rs` owns the + physical response map. `crates/akita-prover/src/protocol/sumcheck/physical_l2_norm.rs` + and `crates/akita-verifier/src/stages/physical_l2_norm.rs` own proof and replay. - Paper §3.12 `sec:batched-soundness` (`def:batched-weak-opening`, `lem:batched-weak-binding`, `prop:committed-fold-price`). -- `specs/weak-binding-norm-fix.md` (fold reprice — keep the correction section). +- `specs/archive/2026-Q3/weak-binding-norm-fix.md` records the earlier fold reprice. - `specs/fold-linf-rejection.md` (fold digit-count tightening). +- `specs/selective-l2-fold-security-sizing.md` (implemented physical norm correction + and optional L2 route). diff --git a/book/src/how/verification.md b/book/src/how/verification.md index c84aa89c7..7cf296357 100644 --- a/book/src/how/verification.md +++ b/book/src/how/verification.md @@ -82,7 +82,9 @@ At a high level: every recursive fold, using the schedule-selected `LevelParams`. 4. **Check the terminal witness directly** against its predecessor-bound `t` state. The terminal relation is `consistency | A`; it has no outer `u`, B - block, D block, or quotient sumcheck. + block, D block, or quotient sumcheck. If the terminal A matrix uses an L2 + route, the verifier also computes the decoded response's exact integer + squared norm and compares it with the scheduled cap. At each nonterminal fold, the verifier checks fixed 128-byte `p_H` and `p_F` payload shapes, reconstructs the B, D, F, and H relation right hand sides, and @@ -91,6 +93,12 @@ the negative-binary support from `WitnessLayout` and evaluates the stage-1 equality table restricted to those intervals; compression roles never enlarge or shrink the ordinary A/B/D common address block. +An L2 fold at D64 or D128 also replays operator norm rejection from the +transcript. The schedule fixes the sparse challenge family and both the true +subset threshold and strict integer threshold. A challenge is accepted only +when the integer interval calculation proves that every spectral magnitude is +within the strict threshold. + Root replay reads each commitment group's point directly from `PolynomialGroupClaims`. The verifier prepares the per-group relation and extension-opening factors from @@ -138,7 +146,7 @@ replay, it: canonical security table, role, modulus, rank, width, bound, and ring dimension; 5. checks root, recursive, setup-prefix, challenge, witness-partition, terminal - response, and full terminal infinity-norm-cap geometry; + response, and full terminal norm cap geometry; 6. checks that the schedule fits the setup field capacity; and only then 7. binds the instance descriptor and replays the proof. diff --git a/crates/akita-algebra/src/eq_poly.rs b/crates/akita-algebra/src/eq_poly.rs index 3093a6843..bea878187 100644 --- a/crates/akita-algebra/src/eq_poly.rs +++ b/crates/akita-algebra/src/eq_poly.rs @@ -142,6 +142,38 @@ impl EqPolynomial { (0..len).map(|index| split.eval_at(index)).collect() } + /// Sum the first `len` entries of the little-endian equality table without + /// materializing them. + /// + /// This is the multilinear analogue of a binary prefix probability. It + /// scans the upper-bound bits from most to least significant and costs one + /// field operation per coordinate instead of one per table entry. + pub fn prefix_sum(r: &[E], len: usize) -> Result { + let table_len = Self::table_len(r.len())?; + if len > table_len { + return Err(AkitaError::InvalidSize { + expected: table_len, + actual: len, + }); + } + if len == table_len { + return Ok(E::one()); + } + + let mut below = E::zero(); + let mut equal_prefix = E::one(); + for bit in (0..r.len()).rev() { + let (left, right) = Self::split_lagrange_parent(equal_prefix, r[bit]); + if (len >> bit) & 1 == 1 { + below += left; + equal_prefix = right; + } else { + equal_prefix = left; + } + } + Ok(below) + } + /// Compute the full evaluation table with optional scaling: /// `scaling_factor · eq(r, x)` for all `x ∈ {0,1}^n`. /// @@ -380,6 +412,23 @@ mod tests { } } + #[test] + fn prefix_sum_matches_materialized_prefixes() { + let mut rng = StdRng::seed_from_u64(0xC0DF); + for n in 0..9 { + let r: Vec = (0..n).map(|_| F::random(&mut rng)).collect(); + let table = EqPolynomial::evals(&r).unwrap(); + let mut expected = F::zero(); + for len in 0..=table.len() { + assert_eq!(EqPolynomial::prefix_sum(&r, len).unwrap(), expected); + if let Some(value) = table.get(len) { + expected += *value; + } + } + assert!(EqPolynomial::prefix_sum(&r, table.len() + 1).is_err()); + } + } + #[test] fn split_eq_evals_factorizes_full_table() { let mut rng = StdRng::seed_from_u64(0x5917); diff --git a/crates/akita-challenges/src/config.rs b/crates/akita-challenges/src/config.rs index 0f4eb3c19..74ac05125 100644 --- a/crates/akita-challenges/src/config.rs +++ b/crates/akita-challenges/src/config.rs @@ -17,6 +17,118 @@ pub const D64_PRODUCTION_PM1_COUNT: usize = 31; /// Production D=64 signed sparse ±2 count (LaBRADOR-aligned). pub const D64_PRODUCTION_PM2_COUNT: usize = 10; +/// D=64 exact shell used by the selective-L2 operator-norm route. +/// +/// The raw family has about 130.15 bits of support. The independently checked +/// `Gamma <= 18` certificate retains about 128.06 bits; the runtime predicate +/// uses threshold 19 so its strict fixed-point enclosure provably contains +/// that certified subset. +pub const D64_L2_OP_NORM_PM1_COUNT: usize = 31; +pub const D64_L2_OP_NORM_PM2_COUNT: usize = 11; + +/// D=128 selective-L2 route reuses the production `(31, 0)` shell. +pub const D128_L2_OP_NORM_PM1_COUNT: usize = 31; +pub const D128_L2_OP_NORM_PM2_COUNT: usize = 0; + +/// Verifier-enforced operator-norm rejection policy for selective L2 folds. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct OperatorNormRejection { + /// Strict certified predicate threshold used by prover and verifier. + pub threshold: u32, + /// Mathematical threshold whose accepted-support floor was certified. + pub certified_subset_threshold: u32, +} + +impl OperatorNormRejection { + /// D=64 selective-L2 policy. Its support certificate is + /// `cert_d64_a31_b11_gamma18.json` from the Akita paper artifacts. + pub const D64_SELECTIVE_L2: Self = Self { + threshold: 19, + certified_subset_threshold: 18, + }; + + /// D=128 selective-L2 policy. Its support certificate is + /// `scripts/operator_norm/d128/cert_d128_w31_gamma13.json`. + pub const D128_SELECTIVE_L2: Self = Self { + threshold: 14, + certified_subset_threshold: 13, + }; + + /// Validate the exact challenge family covered by the support certificate. + pub fn validate( + self, + ring_d: usize, + config: &SparseChallengeConfig, + ) -> Result<(), &'static str> { + let covered = match self { + Self::D64_SELECTIVE_L2 => { + ring_d == 64 + && config.count_pm1 == D64_L2_OP_NORM_PM1_COUNT + && config.count_pm2 == D64_L2_OP_NORM_PM2_COUNT + } + Self::D128_SELECTIVE_L2 => { + ring_d == 128 + && config.count_pm1 == D128_L2_OP_NORM_PM1_COUNT + && config.count_pm2 == D128_L2_OP_NORM_PM2_COUNT + } + _ => false, + }; + if !covered { + return Err("unsupported operator-norm rejection policy or challenge family"); + } + Ok(()) + } + + /// Canonical transcript-domain bytes for this rejection policy. + pub fn domain_separator_bytes(self) -> [u8; 9] { + let mut out = [0u8; 9]; + out[0] = 1; + out[1..5].copy_from_slice(&self.threshold.to_le_bytes()); + out[5..9].copy_from_slice(&self.certified_subset_threshold.to_le_bytes()); + out + } +} + +/// Exact challenge config paired with +/// [`OperatorNormRejection::D64_SELECTIVE_L2`]. +pub const D64_SELECTIVE_L2_CHALLENGE_CONFIG: SparseChallengeConfig = SparseChallengeConfig { + count_pm1: D64_L2_OP_NORM_PM1_COUNT, + count_pm2: D64_L2_OP_NORM_PM2_COUNT, +}; + +/// Exact challenge config paired with +/// [`OperatorNormRejection::D128_SELECTIVE_L2`]. +pub const D128_SELECTIVE_L2_CHALLENGE_CONFIG: SparseChallengeConfig = SparseChallengeConfig { + count_pm1: D128_L2_OP_NORM_PM1_COUNT, + count_pm2: D128_L2_OP_NORM_PM2_COUNT, +}; + +/// Challenge family selected by a certified selective-L2 route. +#[inline] +#[must_use] +pub fn selective_l2_challenge_config(ring_d: usize) -> Option { + match ring_d { + 64 => Some(D64_SELECTIVE_L2_CHALLENGE_CONFIG), + 128 => Some(D128_SELECTIVE_L2_CHALLENGE_CONFIG), + _ => None, + } +} + +/// Rejection policy selected by a certified selective-L2 schedule, if any. +#[inline] +#[must_use] +pub fn selective_l2_operator_norm_rejection( + ring_d: usize, + config: &SparseChallengeConfig, +) -> Option { + let policy = match ring_d { + 64 => OperatorNormRejection::D64_SELECTIVE_L2, + 128 => OperatorNormRejection::D128_SELECTIVE_L2, + _ => return None, + }; + policy.validate(ring_d, config).is_ok().then_some(policy) +} + /// Ring degrees with a production fold-challenge ladder entry. macro_rules! production_fold_challenge_ring_dims { ($($dim:literal),+ $(,)?) => { @@ -321,4 +433,26 @@ mod entropy_tests { } } } + + #[test] + fn selective_l2_operator_norm_policies_are_dimension_and_family_typed() { + let d64 = D64_SELECTIVE_L2_CHALLENGE_CONFIG; + let d128 = D128_SELECTIVE_L2_CHALLENGE_CONFIG; + assert_eq!(selective_l2_challenge_config(64), Some(d64)); + assert_eq!(selective_l2_challenge_config(128), Some(d128)); + assert_eq!(selective_l2_challenge_config(256), None); + assert_eq!( + selective_l2_operator_norm_rejection(64, &d64), + Some(OperatorNormRejection::D64_SELECTIVE_L2) + ); + assert_eq!( + selective_l2_operator_norm_rejection(128, &d128), + Some(OperatorNormRejection::D128_SELECTIVE_L2) + ); + assert!(selective_l2_operator_norm_rejection(64, &d128).is_none()); + assert!(selective_l2_operator_norm_rejection(128, &d64).is_none()); + assert!(OperatorNormRejection::D128_SELECTIVE_L2 + .validate(128, &SparseChallengeConfig::pm1_only(30)) + .is_err()); + } } diff --git a/crates/akita-challenges/src/fold_draw.rs b/crates/akita-challenges/src/fold_draw.rs index b3d6bb73e..5c4c018fd 100644 --- a/crates/akita-challenges/src/fold_draw.rs +++ b/crates/akita-challenges/src/fold_draw.rs @@ -1,7 +1,7 @@ //! Fold-challenge preview drawing for prover-side Fiat–Shamir grinding. -use crate::sampler::{SignedSparseScratch, XofCursor, MAX_STACK_RING_DIM}; -use crate::{Challenges, SparseChallengeConfig}; +use crate::sampler::{XofCursor, MAX_STACK_RING_DIM}; +use crate::{Challenges, OperatorNormRejection, SparseChallengeConfig}; use akita_field::{AkitaError, CanonicalField, FieldCore}; use akita_transcript::labels::{ABSORB_SPARSE_CHALLENGE, CHALLENGE_SPARSE_CHALLENGE}; use akita_transcript::{FoldChallengeSeedPreview, Transcript, FOLD_CHALLENGE_SEED_LEN}; @@ -50,6 +50,28 @@ pub trait FoldDraw { num_claims: usize, cfg: &SparseChallengeConfig, grind_nonce: u32, + ) -> Result { + self.draw_folding_challenges_with_rejection( + ring_d, + group_index, + num_live_blocks, + num_claims, + cfg, + grind_nonce, + None, + ) + } + + #[allow(clippy::too_many_arguments)] + fn draw_folding_challenges_with_rejection( + &mut self, + ring_d: usize, + group_index: usize, + num_live_blocks: usize, + num_claims: usize, + cfg: &SparseChallengeConfig, + grind_nonce: u32, + rejection: Option, ) -> Result { if ring_d > MAX_STACK_RING_DIM { return Err(AkitaError::InvalidInput(format!( @@ -59,6 +81,11 @@ pub trait FoldDraw { cfg.validate_dyn(ring_d).map_err(|e| { AkitaError::InvalidInput(format!("invalid sparse challenge config: {e}")) })?; + if let Some(rejection) = rejection { + rejection + .validate(ring_d, cfg) + .map_err(|error| AkitaError::InvalidInput(error.into()))?; + } if num_live_blocks == 0 || num_claims == 0 { return Err(AkitaError::InvalidInput( "fold challenges require positive num_live_blocks and claims".to_string(), @@ -76,9 +103,18 @@ pub trait FoldDraw { absorb_buf.extend_from_slice(&(ring_d as u64).to_le_bytes()); absorb_buf.extend_from_slice(&domain_sep); absorb_buf.extend_from_slice(&grind_nonce.to_le_bytes()); + if let Some(rejection) = rejection { + absorb_buf.extend_from_slice(&rejection.domain_separator_bytes()); + } let seed = self.absorb_and_squeeze(ABSORB_SPARSE_CHALLENGE, &absorb_buf); let mut cursor = XofCursor::from_seed(&seed); - let challenges = SignedSparseScratch::sample_challenges(&mut cursor, ring_d, total, cfg)?; + let challenges = crate::sampler::sample_challenges_from_xof_cursor( + &mut cursor, + ring_d, + total, + cfg, + rejection, + )?; Challenges::from_sparse(challenges, num_live_blocks, num_claims) } } diff --git a/crates/akita-challenges/src/lib.rs b/crates/akita-challenges/src/lib.rs index de2faad70..2356bfe1f 100644 --- a/crates/akita-challenges/src/lib.rs +++ b/crates/akita-challenges/src/lib.rs @@ -28,7 +28,10 @@ pub use challenge::{ }; pub use challenges::Challenges; pub use config::{ - SparseChallengeConfig, D64_PRODUCTION_PM1_COUNT, D64_PRODUCTION_PM2_COUNT, + selective_l2_challenge_config, selective_l2_operator_norm_rejection, OperatorNormRejection, + SparseChallengeConfig, D128_L2_OP_NORM_PM1_COUNT, D128_L2_OP_NORM_PM2_COUNT, + D128_SELECTIVE_L2_CHALLENGE_CONFIG, D64_L2_OP_NORM_PM1_COUNT, D64_L2_OP_NORM_PM2_COUNT, + D64_PRODUCTION_PM1_COUNT, D64_PRODUCTION_PM2_COUNT, D64_SELECTIVE_L2_CHALLENGE_CONFIG, MIN_FOLD_CHALLENGE_ENTROPY_BITS, PRODUCTION_FOLD_CHALLENGE_RING_DIMS, }; pub use fold_draw::{fold_challenge_sample_label, FoldDraw, LiveFoldDraw, PreviewFoldDraw}; diff --git a/crates/akita-challenges/src/sampler/mod.rs b/crates/akita-challenges/src/sampler/mod.rs index 13c1518e0..894ca8940 100644 --- a/crates/akita-challenges/src/sampler/mod.rs +++ b/crates/akita-challenges/src/sampler/mod.rs @@ -5,6 +5,8 @@ //! commitment. Every [`SparseChallengeConfig`] uses the signed-sparse sampler: //! `count_pm1` coefficients at ±1 and `count_pm2` at ±2. +mod op_norm; +mod op_norm_accumulate; mod position_sample; mod signed_sparse; mod xof; @@ -17,8 +19,103 @@ use akita_field::AkitaError; use akita_field::{CanonicalField, FieldCore}; use akita_transcript::labels::{ABSORB_SPARSE_CHALLENGE, CHALLENGE_SPARSE_CHALLENGE}; use akita_transcript::Transcript; +use std::sync::{Arc, LazyLock}; -use crate::{SparseChallenge, SparseChallengeConfig}; +use crate::{OperatorNormRejection, SparseChallenge, SparseChallengeConfig}; + +use op_norm::OpNormTable; + +const OP_NORM_PREDICATE_SCALE: u32 = 48; +const MAX_OP_NORM_ATTEMPTS: usize = 4096; +static D64_SELECTIVE_L2_OP_NORM_TABLE: LazyLock, &'static str>> = + LazyLock::new(|| { + let config = crate::D64_SELECTIVE_L2_CHALLENGE_CONFIG; + let policy = OperatorNormRejection::D64_SELECTIVE_L2; + let table = OpNormTable::new( + 64, + OP_NORM_PREDICATE_SCALE, + config.l1_norm() as u64, + u64::from(policy.threshold), + ) + .map_err(|_| "failed to initialize the D64 selective-L2 operator-norm table")?; + if !table.strict_threshold_contains_true_subset( + u64::from(policy.certified_subset_threshold), + u64::from(policy.threshold), + ) { + return Err("the D64 operator-norm table does not contain its certified subset"); + } + Ok(Arc::new(table)) + }); +static D128_SELECTIVE_L2_OP_NORM_TABLE: LazyLock, &'static str>> = + LazyLock::new(|| { + let config = crate::D128_SELECTIVE_L2_CHALLENGE_CONFIG; + let policy = OperatorNormRejection::D128_SELECTIVE_L2; + let table = OpNormTable::new( + 128, + OP_NORM_PREDICATE_SCALE, + config.l1_norm() as u64, + u64::from(policy.threshold), + ) + .map_err(|_| "failed to initialize the D128 selective-L2 operator-norm table")?; + if !table.strict_threshold_contains_true_subset( + u64::from(policy.certified_subset_threshold), + u64::from(policy.threshold), + ) { + return Err("the D128 operator-norm table does not contain its certified subset"); + } + Ok(Arc::new(table)) + }); + +pub(crate) fn sample_challenges_from_xof_cursor( + cursor: &mut XofCursor, + ring_d: usize, + n: usize, + cfg: &SparseChallengeConfig, + rejection: Option, +) -> Result, AkitaError> { + let Some(rejection) = rejection else { + return SignedSparseScratch::sample_challenges(cursor, ring_d, n, cfg); + }; + rejection + .validate(ring_d, cfg) + .map_err(|error| AkitaError::InvalidSetup(error.into()))?; + let table = match rejection { + OperatorNormRejection::D64_SELECTIVE_L2 => &*D64_SELECTIVE_L2_OP_NORM_TABLE, + OperatorNormRejection::D128_SELECTIVE_L2 => &*D128_SELECTIVE_L2_OP_NORM_TABLE, + _ => { + return Err(AkitaError::InvalidSetup( + "unsupported operator-norm rejection policy".into(), + )); + } + }; + let table = Arc::clone( + table + .as_ref() + .map_err(|message| AkitaError::InvalidSetup((*message).into()))?, + ); + let mut scratch = SignedSparseScratch::new(cfg.count_pm1, cfg.count_pm2); + let mut challenges = Vec::with_capacity(n); + for _ in 0..n { + let mut accepted = None; + for _ in 0..MAX_OP_NORM_ATTEMPTS { + scratch.sample(cursor, ring_d, cfg.count_pm1, cfg.count_pm2)?; + if table.accept_strict_parts( + scratch.positions(), + scratch.coeffs(), + u64::from(rejection.threshold), + )? { + accepted = Some(scratch.take_challenge()); + break; + } + } + challenges.push(accepted.ok_or_else(|| { + AkitaError::InvalidInput(format!( + "operator-norm rejection exceeded {MAX_OP_NORM_ATTEMPTS} attempts" + )) + })?); + } + Ok(challenges) +} /// Sample `n` sparse ring fold challenges from a transcript. /// @@ -57,7 +154,7 @@ where transcript.append_bytes(ABSORB_SPARSE_CHALLENGE, &absorb_buf); let seed = transcript.challenge_bytes(CHALLENGE_SPARSE_CHALLENGE, 32); let mut cursor = XofCursor::from_seed(&seed); - SignedSparseScratch::sample_challenges(&mut cursor, ring_d, n, cfg) + sample_challenges_from_xof_cursor(&mut cursor, ring_d, n, cfg, None) } #[cfg(test)] diff --git a/crates/akita-challenges/src/sampler/op_norm.rs b/crates/akita-challenges/src/sampler/op_norm.rs new file mode 100644 index 000000000..260f0faab --- /dev/null +++ b/crates/akita-challenges/src/sampler/op_norm.rs @@ -0,0 +1,949 @@ +//! Exact operator-norm acceptance predicate `gamma_D(c) <= T`. +//! +//! For `c in Z[X]/(X^D + 1)` the negacyclic convolution operator norm is +//! +//! ```text +//! gamma_D(c) = max_{0 <= k < D} |c_hat(k)|, +//! c_hat(k) = sum_{j} c_j * zeta_k^j, zeta_k = exp((2k + 1) * pi * i / D), +//! ``` +//! +//! and `accept(c) iff gamma_D(c) <= T iff max_k |c_hat(k)|^2 <= T^2`. +//! +//! Soundness contract (the only invariant callers depend on): a returned +//! [`Decision::Accept`] means `gamma_D(c) <= T` over the reals. Machine +//! floating-point FFTs cannot honor that contract (their rounding could turn a +//! just-over-threshold challenge into an unsound accept), so the decision is +//! integer-only: +//! +//! - The `2*D` distinct trig values `cos(pi*t/D), sin(pi*t/D)` are tabulated as +//! signed fixed-point integers at scale `2^q`, each carried with a *sound* +//! per-entry error bound `eps_root` (`|C[t] - 2^q cos(pi t/D)| <= eps_root`). +//! The table is built by interval Taylor evaluation over a rigorous rational +//! enclosure of `pi` (Machin series in `i128`); no floating point enters the +//! table or the decision. +//! - For each frequency the predicate forms integer accumulators `R_k, I_k`, +//! then the conservative upper bound +//! `upper_k = R_k^2 + I_k^2 + 2(|R_k| + |I_k|) r + 2 r^2` with `r = ||c||_1 * +//! eps_root`, which provably bounds `|2^q c_hat(k)|^2` from above. +//! [`Decision::Accept`] is returned only when every `upper_k <= T^2 2^{2q}`, +//! so acceptance is always sound. A frequency whose *lower* bound already +//! exceeds the threshold forces [`Decision::Reject`]; anything in between is +//! [`Decision::Indeterminate`]. Callers that fold the boundary band into a +//! reject (see [`OpNormTable::accept_strict_parts`]) stay sound, at the cost of a +//! slightly smaller accepted support. +//! +//! Only the `D/2` frequencies `k = 0..D/2` are scanned: `zeta_{D-1-k} = +//! conj(zeta_k)` and `c` is real, so `|c_hat(D-1-k)| = |c_hat(k)|`. +//! +//! This is the acceptance oracle for operator-norm rejection sampling of fold +//! challenges: [`crate::sample_sparse_challenges`] retains a sampled challenge +//! only if it passes [`OpNormTable::accept_strict_parts`] (see the rejection loop in +//! [`crate::sampler`]). + +use akita_field::AkitaError; + +use super::op_norm_accumulate; + +/// Internal fixed-point scale for the certified `pi` and trig interval math. +/// Chosen so that products of two scaled values stay within `i128` +/// (`2 * TRIG_SCALE < 127`). +const TRIG_SCALE: u32 = 61; +/// `1.0` at [`TRIG_SCALE`]. +const TRIG_ONE: i128 = 1i128 << TRIG_SCALE; +/// Taylor terms for the small-angle (`<= pi/4`) cos/sin enclosures. The first +/// omitted term is below `2^-29` at [`TRIG_SCALE`] for `phi <= pi/4`, and the +/// largest factorial used for the remainder bound (`26!`) fits `i128`. +const NTERMS: usize = 12; +/// Decision of the operator-norm acceptance predicate. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum Decision { + /// Proven `gamma_D(c) <= T`. + Accept, + /// Proven `gamma_D(c) > T`. + Reject, + /// Inside the certified uncertainty band; neither bound is decisive. + Indeterminate, +} + +/// Certified fixed-point cos/sin tables for one `(D, q)` plus the global sound +/// error bound `eps_root`, with accumulator overflow validated for a stated +/// `max_l1` / `max_t`. +#[derive(Debug, Clone)] +pub(crate) struct OpNormTable { + d: usize, + q: u32, + /// Certified `2^q cos/sin(pi t / D)` source tables, retained only for the + /// accuracy/reference unit tests; production reads `freq_*_at`. + #[cfg(test)] + base_cos: Vec, + #[cfg(test)] + base_sin: Vec, + /// Sound bound `|base_*[t] - 2^q trig(pi t / D)| <= eps_root`. + eps_root: i128, + /// Largest `||c||_1` the overflow validation covered. + max_l1: i128, + /// Largest threshold `t` the overflow validation covered. + max_t: i128, + /// Transposed rows `freq_cos_at[pos * half_d + k]` for fast accumulation, + /// the `i64` downcast of the certified `base_*` tables (`|entry| <= 2^q`). + freq_cos_at: Vec, + freq_sin_at: Vec, +} + +impl OpNormTable { + /// Build the certified table for ring degree `d` at fixed-point scale `q`, + /// validating that the predicate's `i128` accumulators cannot overflow for + /// any challenge with `||c||_1 <= max_l1` and any threshold `t <= max_t`. + /// + /// # Errors + /// + /// Returns [`AkitaError::InvalidSetup`] if `d` is not a positive multiple of + /// 4, if `q` is outside `1..=56`, or if the worst-case accumulator/square + /// bounds for `(max_l1, max_t)` do not fit `i128`. + #[doc(hidden)] + pub(crate) fn new(d: usize, q: u32, max_l1: u64, max_t: u64) -> Result { + if d < 4 || !d.is_multiple_of(4) { + return Err(AkitaError::InvalidSetup(format!( + "OpNormTable: ring degree d = {d} must be a positive multiple of 4" + ))); + } + if !(1..=56).contains(&q) { + return Err(AkitaError::InvalidSetup(format!( + "OpNormTable: scale q = {q} out of supported range 1..=56" + ))); + } + + let (base_cos, base_sin, eps_root) = build_tables(d, q); + + let max_l1 = i128::from(max_l1); + let max_t = i128::from(max_t); + validate_no_overflow(q, eps_root, max_l1, max_t)?; + validate_i64_accumulators(q, max_l1)?; + + let downcast = |table: &[i128], name: &str| -> Result, AkitaError> { + table + .iter() + .map(|&v| { + i64::try_from(v).map_err(|_| { + AkitaError::InvalidSetup(format!( + "OpNormTable: {name} entry does not fit i64 accumulator path" + )) + }) + }) + .collect() + }; + let base_cos_i64 = downcast(&base_cos, "base_cos")?; + let base_sin_i64 = downcast(&base_sin, "base_sin")?; + let (freq_cos_at, freq_sin_at) = + op_norm_accumulate::build_freq_at_tables(d, &base_cos_i64, &base_sin_i64); + + Ok(Self { + d, + q, + #[cfg(test)] + base_cos, + #[cfg(test)] + base_sin, + eps_root, + max_l1, + max_t, + freq_cos_at, + freq_sin_at, + }) + } + + /// `i64` downcast of `base_cos[idx]` (certified entry, `|entry| <= 2^q`). + #[cfg(test)] + #[inline] + pub(super) fn base_cos_i64(&self, idx: usize) -> i64 { + self.base_cos[idx] as i64 + } + + /// `i64` downcast of `base_sin[idx]`. + #[cfg(test)] + #[inline] + pub(super) fn base_sin_i64(&self, idx: usize) -> i64 { + self.base_sin[idx] as i64 + } + + #[inline] + pub(super) fn freq_row(&self, pos: usize, half_d: usize) -> (&[i64], &[i64]) { + let row = pos * half_d; + ( + &self.freq_cos_at[row..row + half_d], + &self.freq_sin_at[row..row + half_d], + ) + } + + /// Certified operator-norm predicate on stack-buffered `(positions, coeffs)` + /// slices, scanning the `D/2` distinct frequencies (`zeta_{D-1-k} = + /// conj(zeta_k)`) with the transposed `i64` accumulators. + pub(crate) fn decide_parts( + &self, + positions: &[u32], + coeffs: &[i8], + t: u64, + ) -> Result { + if positions.len() != coeffs.len() { + return Err(AkitaError::InvalidInput( + "operator-norm predicate: positions/coeffs length mismatch".to_string(), + )); + } + let mut l1: i128 = 0; + for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { + if pos as usize >= self.d { + return Err(AkitaError::InvalidInput(format!( + "operator-norm predicate: position {pos} out of range for D = {}", + self.d + ))); + } + l1 += i128::from(coeff.unsigned_abs()); + } + if l1 > self.max_l1 { + return Err(AkitaError::InvalidInput(format!( + "operator-norm predicate: ||c||_1 = {l1} exceeds validated max_l1 = {}", + self.max_l1 + ))); + } + // `threshold = t^2 << 2q` is only proven to fit `i128` for `t <= max_t` + // (the bound `new` validated). Reject larger thresholds rather than risk + // a debug-overflow panic or a release wrap that would corrupt the + // comparison. + if i128::from(t) > self.max_t { + return Err(AkitaError::InvalidInput(format!( + "operator-norm predicate: threshold t = {t} exceeds validated max_t = {}", + self.max_t + ))); + } + + let r = l1 * self.eps_root; + let two_r = 2 * r; + let two_r_sq = 2 * r * r; + let threshold = (i128::from(t) * i128::from(t)) << (2 * self.q); + decide_transposed_fused(self, positions, coeffs, r, two_r, two_r_sq, threshold) + } + + /// Slice form of the production (strict) predicate for stack-buffered rejection draws. + pub(crate) fn accept_strict_parts( + &self, + positions: &[u32], + coeffs: &[i8], + t: u64, + ) -> Result { + Ok(self.decide_parts(positions, coeffs, t)? == Decision::Accept) + } + + /// Prove that every challenge with true operator norm at most + /// `subset_t` is accepted by the strict fixed-point predicate at + /// `strict_t`. + /// + /// Each real/imaginary accumulator has error at most `r`. The predicate's + /// upper enclosure is therefore at most `(subset_t * 2^q + 2 sqrt(2) r)^2`. + /// The integer inequality below proves that this fits below + /// `(strict_t * 2^q)^2` without using floating point. + pub(crate) fn strict_threshold_contains_true_subset( + &self, + subset_t: u64, + strict_t: u64, + ) -> bool { + let Some(gap) = strict_t.checked_sub(subset_t).map(i128::from) else { + return false; + }; + let r = self.max_l1 * self.eps_root; + let scale = 1i128 << self.q; + 8i128 + .checked_mul(r) + .and_then(|value| value.checked_mul(r)) + .zip( + gap.checked_mul(gap) + .and_then(|value| value.checked_mul(scale)) + .and_then(|value| value.checked_mul(scale)), + ) + .is_some_and(|(lhs, rhs)| lhs <= rhs) + } +} + +#[allow(clippy::too_many_arguments)] +fn decide_transposed_fused( + table: &OpNormTable, + positions: &[u32], + coeffs: &[i8], + r: i128, + two_r: i128, + two_r_sq: i128, + threshold: i128, +) -> Result { + let num_freqs = table.d / 2; + let mut indeterminate = false; + let mut start_k = 0; + while start_k < num_freqs { + let len = (num_freqs - start_k).min(op_norm_accumulate::FUSED_CHUNK_FREQS); + let (acc_re, acc_im) = op_norm_accumulate::accumulate_transposed_chunk( + table, positions, coeffs, start_k, len, num_freqs, + ); + for lane in 0..len { + let re = i128::from(acc_re[lane]); + let im = i128::from(acc_im[lane]); + let abs_re = re.abs(); + let abs_im = im.abs(); + if decide_frequency(abs_re, abs_im, re, im, r, two_r, two_r_sq, threshold)? { + return Ok(Decision::Reject); + } + if !frequency_accepts_upper(abs_re, abs_im, re, im, r, two_r, two_r_sq, threshold) { + indeterminate = true; + } + } + start_k += len; + } + if indeterminate { + Ok(Decision::Indeterminate) + } else { + Ok(Decision::Accept) + } +} + +#[allow(clippy::too_many_arguments)] +#[inline] +fn frequency_accepts_upper( + abs_re: i128, + abs_im: i128, + re: i128, + im: i128, + _r: i128, + two_r: i128, + two_r_sq: i128, + threshold: i128, +) -> bool { + let center = re * re + im * im; + let upper = center + two_r * (abs_re + abs_im) + two_r_sq; + upper <= threshold +} + +#[allow(clippy::too_many_arguments)] +#[inline] +fn decide_frequency( + abs_re: i128, + abs_im: i128, + re: i128, + im: i128, + r: i128, + two_r: i128, + two_r_sq: i128, + threshold: i128, +) -> Result { + if frequency_accepts_upper(abs_re, abs_im, re, im, r, two_r, two_r_sq, threshold) { + return Ok(false); + } + let low_re = (abs_re - r).max(0); + let low_im = (abs_im - r).max(0); + let lower = low_re * low_re + low_im * low_im; + Ok(lower > threshold) +} + +/// Validate worst-case `i64` accumulator magnitudes for the transposed path. +fn validate_i64_accumulators(q: u32, max_l1: i128) -> Result<(), AkitaError> { + let overflow = || { + AkitaError::InvalidSetup( + "OpNormTable: worst-case i64 accumulator does not fit i64".to_string(), + ) + }; + let max_acc = max_l1 + .checked_mul(1i128.checked_shl(q).ok_or_else(overflow)?) + .ok_or_else(overflow)?; + if max_acc > i128::from(i64::MAX) { + return Err(overflow()); + } + Ok(()) +} + +/// Validate the worst-case `i128` accumulator and square bounds for the +/// predicate, given a sound `eps_root` and the caller's `(max_l1, max_t)`. +fn validate_no_overflow( + q: u32, + eps_root: i128, + max_l1: i128, + max_t: i128, +) -> Result<(), AkitaError> { + let overflow = || { + AkitaError::InvalidSetup( + "OpNormTable: worst-case accumulator does not fit i128".to_string(), + ) + }; + // max |R_k| = max_l1 * 2^q (triangle bound over base_* in [-2^q, 2^q]). + let max_acc = max_l1 + .checked_mul(1i128.checked_shl(q).ok_or_else(overflow)?) + .ok_or_else(overflow)?; + let r = max_l1.checked_mul(eps_root).ok_or_else(overflow)?; + // upper_k = R^2 + I^2 + 2(|R| + |I|) r + 2 r^2, worst case |R| = |I| = max_acc. + let center = max_acc.checked_mul(max_acc).ok_or_else(overflow)?; + let center2 = center.checked_mul(2).ok_or_else(overflow)?; + let cross = max_acc + .checked_mul(4) + .and_then(|v| v.checked_mul(r)) + .ok_or_else(overflow)?; + let slack = r + .checked_mul(r) + .and_then(|v| v.checked_mul(2)) + .ok_or_else(overflow)?; + let upper = center2 + .checked_add(cross) + .and_then(|v| v.checked_add(slack)) + .ok_or_else(overflow)?; + // threshold = max_t^2 * 2^{2q}. + let threshold = max_t + .checked_mul(max_t) + .and_then(|v| v.checked_shl(2 * q)) + .ok_or_else(overflow)?; + let _ = upper.checked_add(threshold).ok_or_else(overflow)?; + Ok(()) +} + +/// Build `base_cos`, `base_sin` at scale `2^q` for `t in 0..2d`, returning the +/// sound global error bound `eps_root`. +fn build_tables(d: usize, q: u32) -> (Vec, Vec, i128) { + let two_d = 2 * d; + let (pi_lo, pi_hi) = pi_enclosure(); + let shift = TRIG_SCALE - q; + + let mut base_cos = vec![0i128; two_d]; + let mut base_sin = vec![0i128; two_d]; + let mut eps_root: i128 = 0; + + for t in 0..two_d { + let (r, swap, cos_sign, sin_sign) = octant_reduce(t, d); + // phi = pi * r / d, enclosed at TRIG_SCALE; phi in [0, pi/4]. + let phi_lo = fdiv(pi_lo * r as i128, d as i128); + let phi_hi = cdiv(pi_hi * r as i128, d as i128); + let cos_phi = taylor_cos((phi_lo, phi_hi)); + let sin_phi = taylor_sin((phi_lo, phi_hi)); + let (cos_a, sin_a) = if swap { + (sin_phi, cos_phi) + } else { + (cos_phi, sin_phi) + }; + let cos_a = apply_sign(cos_a, cos_sign); + let sin_a = apply_sign(sin_a, sin_sign); + + let (c_val, c_err) = downscale_round(cos_a, shift); + let (s_val, s_err) = downscale_round(sin_a, shift); + base_cos[t] = c_val; + base_sin[t] = s_val; + eps_root = eps_root.max(c_err).max(s_err); + } + (base_cos, base_sin, eps_root) +} + +/// Reduce angle index `t` (`angle = pi t / d`, period `2d`) to the first octant: +/// returns `(r, swap, cos_sign, sin_sign)` with `r in [0, d/4]` such that +/// `cos(angle) = cos_sign * (swap ? sin : cos)(pi r / d)` and likewise for sin. +fn octant_reduce(t: usize, d: usize) -> (usize, bool, i128, i128) { + let mut t = t % (2 * d); + let mut cos_sign = 1i128; + let mut sin_sign = 1i128; + if t > d { + // angle in (pi, 2pi): cos(2pi - a) = cos a, sin(2pi - a) = -sin a. + t = 2 * d - t; + sin_sign = -1; + } + if t > d / 2 { + // angle in (pi/2, pi]: cos(pi - a) = -cos a, sin(pi - a) = sin a. + t = d - t; + cos_sign = -cos_sign; + } + let swap = if t > d / 4 { + // angle in (pi/4, pi/2]: cos a = sin(pi/2 - a), sin a = cos(pi/2 - a). + t = d / 2 - t; + true + } else { + false + }; + (t, swap, cos_sign, sin_sign) +} + +/// `cos(phi)` enclosure at [`TRIG_SCALE`] for `phi in [0, pi/4]`. +fn taylor_cos(phi: (i128, i128)) -> (i128, i128) { + let phi2 = imul(phi, phi); + let mut sum = (TRIG_ONE, TRIG_ONE); + let mut pow = (TRIG_ONE, TRIG_ONE); // phi^{2n} + let mut fact: i128 = 1; // (2n)! + for n in 1..=NTERMS { + pow = imul(pow, phi2); + let two_n = 2 * n as i128; + fact = fact * (two_n - 1) * two_n; + let term = (fdiv(pow.0, fact), cdiv(pow.1, fact)); + sum = if n % 2 == 1 { + isub(sum, term) + } else { + iadd(sum, term) + }; + } + add_remainder(sum, phi2, pow, fact, 2 * NTERMS + 1) +} + +/// `sin(phi)` enclosure at [`TRIG_SCALE`] for `phi in [0, pi/4]`. +fn taylor_sin(phi: (i128, i128)) -> (i128, i128) { + let phi2 = imul(phi, phi); + let mut sum = phi; // n = 0 term: phi^1 / 1! + let mut pow = phi; // phi^{2n+1} + let mut fact: i128 = 1; // (2n+1)! + for n in 1..=NTERMS { + pow = imul(pow, phi2); + let two_n = 2 * n as i128; + fact = fact * two_n * (two_n + 1); + let term = (fdiv(pow.0, fact), cdiv(pow.1, fact)); + sum = if n % 2 == 1 { + isub(sum, term) + } else { + iadd(sum, term) + }; + } + add_remainder(sum, phi2, pow, fact, 2 * NTERMS + 2) +} + +/// Widen an alternating-series partial sum by the first omitted term magnitude, +/// a sound bound on the truncation error for a decreasing alternating series. +fn add_remainder( + sum: (i128, i128), + phi2: (i128, i128), + pow: (i128, i128), + fact: i128, + next_factor: usize, +) -> (i128, i128) { + let next_pow = imul(pow, phi2); + let next_fact = fact * (next_factor as i128) * (next_factor as i128 + 1); + let rem = cdiv(next_pow.1, next_fact); + (sum.0 - rem, sum.1 + rem) +} + +/// Negate / sign-apply an interval (`sign in {-1, +1}`). +fn apply_sign(v: (i128, i128), sign: i128) -> (i128, i128) { + if sign < 0 { + (-v.1, -v.0) + } else { + v + } +} + +/// Downscale an interval from [`TRIG_SCALE`] to scale `2^(TRIG_SCALE - shift)` +/// (i.e. to the table scale `2^q`), pick the midpoint integer entry, and return +/// `(entry, error_bound)` with `|entry - true_value| <= error_bound`. +fn downscale_round(v: (i128, i128), shift: u32) -> (i128, i128) { + let lo = fshr(v.0, shift); + let hi = cshr(v.1, shift); + let entry = fdiv(lo + hi, 2); + let err = (entry - lo).max(hi - entry); + (entry, err) +} + +/// Interval multiply at [`TRIG_SCALE`] for non-negative operands. +fn imul(a: (i128, i128), b: (i128, i128)) -> (i128, i128) { + debug_assert!(a.0 >= 0 && b.0 >= 0); + (fshr(a.0 * b.0, TRIG_SCALE), cshr(a.1 * b.1, TRIG_SCALE)) +} + +fn iadd(a: (i128, i128), b: (i128, i128)) -> (i128, i128) { + (a.0 + b.0, a.1 + b.1) +} + +fn isub(a: (i128, i128), b: (i128, i128)) -> (i128, i128) { + (a.0 - b.1, a.1 - b.0) +} + +/// Floor division (`b > 0`). +fn fdiv(a: i128, b: i128) -> i128 { + a.div_euclid(b) +} + +/// Ceil division (`b > 0`). +fn cdiv(a: i128, b: i128) -> i128 { + -((-a).div_euclid(b)) +} + +/// Arithmetic floor shift `floor(x / 2^sh)`. +fn fshr(x: i128, sh: u32) -> i128 { + x >> sh +} + +/// Ceil shift `ceil(x / 2^sh)`. +fn cshr(x: i128, sh: u32) -> i128 { + -((-x) >> sh) +} + +/// Rigorous rational enclosure of `pi` at [`TRIG_SCALE`] via Machin's formula +/// `pi = 16 arctan(1/5) - 4 arctan(1/239)`, all in `i128` fixed point. +fn pi_enclosure() -> (i128, i128) { + let a5 = arctan_inv(5); + let a239 = arctan_inv(239); + // pi = 16 a5 - 4 a239 (interval arithmetic, outward). + let lo = 16 * a5.0 - 4 * a239.1; + let hi = 16 * a5.1 - 4 * a239.0; + (lo, hi) +} + +/// Enclosure of `arctan(1/x)` at [`TRIG_SCALE`] from its alternating series +/// `sum_n (-1)^n / ((2n+1) x^{2n+1})`. Each scaled term is floor-divided, and +/// the result is widened by (terms summed + 1) ULPs to cover both the per-term +/// truncation and the alternating-series remainder. +fn arctan_inv(x: i128) -> (i128, i128) { + let mut sum: i128 = 0; + let mut x_pow = x; // x^{2n+1} + let x2 = x * x; + let mut count: i128 = 0; + let mut n: i128 = 0; + while let Some(denom) = (2 * n + 1).checked_mul(x_pow) { + let term = TRIG_ONE / denom; + if term == 0 { + break; + } + if n % 2 == 0 { + sum += term; + } else { + sum -= term; + } + count += 1; + n += 1; + match x_pow.checked_mul(x2) { + Some(v) => x_pow = v, + None => break, + } + } + let slack = count + 1; + (sum - slack, sum + slack) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::SparseChallenge; + use std::f64::consts::PI; + + const Q: u32 = 48; + + fn table(d: usize) -> OpNormTable { + // ||c||_1 <= 2 * D covers every shipping shell at D <= 128; T <= 64. + OpNormTable::new(d, Q, (2 * d) as u64, 64).unwrap() + } + + fn decide_ch( + table: &OpNormTable, + challenge: &SparseChallenge, + threshold: u64, + ) -> Result { + table.decide_parts(&challenge.positions, &challenge.coeffs, threshold) + } + + /// Test-only naive `k`-outer nested-`i128` reference over `num_freqs` + /// frequencies, mirroring the production conservative-interval decision but + /// without the transposed accumulation. Cross-checks the production `D/2` + /// scan and confirms it equals the full `D`-frequency spectrum. + fn decide_reference_nested( + table: &OpNormTable, + ch: &SparseChallenge, + t: u64, + num_freqs: usize, + ) -> Decision { + let two_d = 2 * table.d; + let l1: i128 = ch.coeffs.iter().map(|c| i128::from(c.unsigned_abs())).sum(); + let r = l1 * table.eps_root; + let two_r = 2 * r; + let two_r_sq = 2 * r * r; + let threshold = (i128::from(t) * i128::from(t)) << (2 * table.q); + let mut indeterminate = false; + for k in 0..num_freqs { + let mult = (2 * k + 1) % two_d; + let mut acc_re: i128 = 0; + let mut acc_im: i128 = 0; + for (&pos, &coeff) in ch.positions.iter().zip(ch.coeffs.iter()) { + let idx = (mult * pos as usize) % two_d; + let coeff = i128::from(coeff); + acc_re += coeff * table.base_cos[idx]; + acc_im += coeff * table.base_sin[idx]; + } + let (abs_re, abs_im) = (acc_re.abs(), acc_im.abs()); + if decide_frequency( + abs_re, abs_im, acc_re, acc_im, r, two_r, two_r_sq, threshold, + ) + .unwrap() + { + return Decision::Reject; + } + if !frequency_accepts_upper( + abs_re, abs_im, acc_re, acc_im, r, two_r, two_r_sq, threshold, + ) { + indeterminate = true; + } + } + if indeterminate { + Decision::Indeterminate + } else { + Decision::Accept + } + } + + /// f64 reference, used ONLY to sanity-check the certified integer path. + fn gamma_sq_f64(d: usize, ch: &SparseChallenge) -> f64 { + let mut max = 0.0f64; + for k in 0..d { + let base = (2 * k + 1) as f64 * PI / d as f64; + let mut re = 0.0; + let mut im = 0.0; + for (&pos, &coeff) in ch.positions.iter().zip(ch.coeffs.iter()) { + let theta = base * pos as f64; + re += coeff as f64 * theta.cos(); + im += coeff as f64 * theta.sin(); + } + max = max.max(re * re + im * im); + } + max + } + + #[test] + fn pi_encloses_pi() { + let (lo, hi) = pi_enclosure(); + let pi_scaled = PI * TRIG_ONE as f64; + assert!((lo as f64) <= pi_scaled && pi_scaled <= (hi as f64)); + // Enclosure should be tight (well under 2^-40 absolute). + assert!(hi - lo < (1i128 << (TRIG_SCALE - 40))); + } + + #[test] + fn table_entries_match_reference_within_eps() { + for &d in &[4usize, 32, 64, 128] { + let t = table(d); + for idx in 0..(2 * d) { + let angle = PI * idx as f64 / d as f64; + let ref_cos = (angle.cos() * (1i128 << Q) as f64).round() as i128; + let ref_sin = (angle.sin() * (1i128 << Q) as f64).round() as i128; + assert!( + (t.base_cos[idx] - ref_cos).abs() <= t.eps_root + 1, + "cos mismatch d={d} idx={idx}: {} vs {ref_cos} (eps={})", + t.base_cos[idx], + t.eps_root + ); + assert!( + (t.base_sin[idx] - ref_sin).abs() <= t.eps_root + 1, + "sin mismatch d={d} idx={idx}: {} vs {ref_sin} (eps={})", + t.base_sin[idx], + t.eps_root + ); + } + // eps_root stays tiny: a couple of units in 2^48. + assert!( + t.eps_root <= 4, + "eps_root too large for d={d}: {}", + t.eps_root + ); + } + } + + #[test] + fn pythagorean_identity_holds() { + let scale_sq = (1i128 << Q) * (1i128 << Q); + for &d in &[32usize, 64, 128] { + let t = table(d); + for idx in 0..(2 * d) { + let s = t.base_cos[idx] * t.base_cos[idx] + t.base_sin[idx] * t.base_sin[idx]; + let diff = (s - scale_sq).abs(); + // Each factor is within eps_root; product error is O(eps * 2^q). + assert!(diff <= (t.eps_root + 2) * (1i128 << (Q + 2))); + } + } + } + + #[test] + fn unit_coefficient_has_unit_norm() { + let d = 64; + let t = table(d); + let ch = SparseChallenge { + positions: vec![0].into(), + coeffs: vec![1].into(), + }; + // A single coefficient of magnitude m gives gamma = m exactly, so the + // predicate accepts strictly above, rejects strictly below, and reports + // the exact tie (T = m) as the indeterminate boundary band. + assert_eq!(decide_ch(&t, &ch, 0).unwrap(), Decision::Reject); + assert_eq!(decide_ch(&t, &ch, 1).unwrap(), Decision::Indeterminate); + assert_eq!(decide_ch(&t, &ch, 2).unwrap(), Decision::Accept); + assert_eq!(decide_ch(&t, &ch, 5).unwrap(), Decision::Accept); + } + + #[test] + fn large_single_coefficient_rejects() { + let d = 64; + let t = table(d); + // gamma = 5 exactly: reject below, indeterminate at the tie, accept above. + let ch = SparseChallenge { + positions: vec![3].into(), + coeffs: vec![5].into(), + }; + assert_eq!(decide_ch(&t, &ch, 4).unwrap(), Decision::Reject); + assert_eq!(decide_ch(&t, &ch, 5).unwrap(), Decision::Indeterminate); + assert_eq!(decide_ch(&t, &ch, 6).unwrap(), Decision::Accept); + } + + /// Tiny deterministic PRNG (xorshift) so the test is fully reproducible. + fn rng_next(state: &mut u64) -> u64 { + let mut x = *state; + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + *state = x; + x + } + + fn random_shell(state: &mut u64, d: usize, mag1: usize, mag2: usize) -> SparseChallenge { + let total = mag1 + mag2; + let mut positions = Vec::with_capacity(total); + while positions.len() < total { + let p = (rng_next(state) % d as u64) as u32; + if !positions.contains(&p) { + positions.push(p); + } + } + let mut coeffs = Vec::with_capacity(total); + for i in 0..total { + let sign = if rng_next(state) & 1 == 0 { 1i8 } else { -1 }; + let mag = if i < mag1 { 1 } else { 2 }; + coeffs.push(sign * mag); + } + SparseChallenge { + positions: positions.into(), + coeffs: coeffs.into(), + } + } + + #[test] + fn production_matches_reference_and_reduced_scan_matches_full_spectrum() { + let d = 64; + let t = table(d); + let mut state = 0x1234_5678_9abc_def0u64; + for _ in 0..2000 { + let ch = random_shell(&mut state, d, 31, 11); + // Production transposed `D/2` scan equals the naive `D/2` reference, + // which in turn equals the full `D`-frequency spectrum. + let production = decide_ch(&t, &ch, 16).unwrap(); + let reduced = decide_reference_nested(&t, &ch, 16, d / 2); + let full = decide_reference_nested(&t, &ch, 16, d); + assert_eq!(production, reduced, "challenge {ch:?}"); + assert_eq!(reduced, full, "challenge {ch:?}"); + } + } + + #[test] + fn accept_implies_sound_and_reject_implies_over() { + let d = 64; + let t = table(d); + let mut state = 0xfeed_face_dead_beefu64; + let threshold = 16u64; + let mut accepts = 0; + let mut rejects = 0; + for _ in 0..5000 { + let ch = random_shell(&mut state, d, 31, 11); + let g2 = gamma_sq_f64(d, &ch); + match decide_ch(&t, &ch, threshold).unwrap() { + Decision::Accept => { + accepts += 1; + assert!( + g2 <= (threshold * threshold) as f64 + 1e-3, + "unsound accept: gamma^2={g2} for {ch:?}" + ); + } + Decision::Reject => { + rejects += 1; + assert!( + g2 >= (threshold * threshold) as f64 - 1e-3, + "unsound reject: gamma^2={g2} for {ch:?}" + ); + } + Decision::Indeterminate => {} + } + } + // The (31, 11) shell at T = 16 should produce a healthy mix. + assert!(accepts > 0, "no accepts sampled"); + assert!(rejects > 0, "no rejects sampled"); + } + + #[test] + fn production_strict_threshold_contains_the_certified_subset() { + for &(d, mag1, mag2, subset, strict, min_numerator, denominator) in + &[(64, 31, 11, 18, 19, 1, 4), (128, 31, 0, 13, 14, 1, 2)] + { + let t = table(d); + assert!(t.strict_threshold_contains_true_subset(subset, strict)); + assert!(!t.strict_threshold_contains_true_subset(subset, subset)); + + let mut state = 0xface_cafe_beef_0001u64 ^ d as u64; + let samples = 10_000u64; + let mut accepts = 0u64; + for _ in 0..samples { + let ch = random_shell(&mut state, d, mag1, mag2); + if t.accept_strict_parts(&ch.positions, &ch.coeffs, strict) + .expect("strict predicate") + { + accepts += 1; + } + } + assert!( + accepts * denominator > samples * min_numerator, + "D{d} strict accept rate {accepts}/{samples} unexpectedly low", + ); + } + } + + #[test] + fn d128_production_matches_reference_and_full_spectrum() { + let d = 128; + let t = table(d); + let mut state = 0xd128_cafe_beef_0001u64; + for _ in 0..1000 { + let ch = random_shell(&mut state, d, 31, 0); + let production = decide_ch(&t, &ch, 14).unwrap(); + let reduced = decide_reference_nested(&t, &ch, 14, d / 2); + let full = decide_reference_nested(&t, &ch, 14, d); + assert_eq!(production, reduced, "challenge {ch:?}"); + assert_eq!(reduced, full, "challenge {ch:?}"); + + let gamma_sq = gamma_sq_f64(d, &ch); + if production == Decision::Accept { + assert!(gamma_sq <= 14.0f64.powi(2) + 1e-3); + } + if production == Decision::Reject { + assert!(gamma_sq >= 14.0f64.powi(2) - 1e-3); + } + } + } + + #[test] + fn rejects_oversized_l1() { + let d = 32; + let t = OpNormTable::new(d, Q, 4, 16).unwrap(); + let ch = SparseChallenge { + positions: vec![0, 1, 2, 3, 4].into(), + coeffs: vec![1, 1, 1, 1, 1].into(), + }; + assert!(decide_ch(&t, &ch, 8).is_err()); + } + + #[test] + fn rejects_oversized_threshold() { + let d = 32; + // `||c||_1` stays within `max_l1`, so the threshold guard (not the L1 + // guard) is what rejects a `t` above the validated `max_t = 16`. + let table = OpNormTable::new(d, Q, 64, 16).unwrap(); + let ch = SparseChallenge { + positions: vec![0, 1].into(), + coeffs: vec![1, 1].into(), + }; + assert!(decide_ch(&table, &ch, 17).is_err()); + assert!(decide_ch(&table, &ch, u64::MAX).is_err()); + // A threshold at the validated boundary is still accepted as input. + assert!(decide_ch(&table, &ch, 16).is_ok()); + } + + #[test] + fn construction_rejects_bad_params() { + assert!(OpNormTable::new(6, Q, 16, 16).is_err()); // not a multiple of 4 + assert!(OpNormTable::new(64, 60, 16, 16).is_err()); // q out of range + assert!(OpNormTable::new(64, Q, u64::MAX, u64::MAX).is_err()); // overflow + } +} diff --git a/crates/akita-challenges/src/sampler/op_norm_accumulate.rs b/crates/akita-challenges/src/sampler/op_norm_accumulate.rs new file mode 100644 index 000000000..aa3c1188f --- /dev/null +++ b/crates/akita-challenges/src/sampler/op_norm_accumulate.rs @@ -0,0 +1,354 @@ +//! Transposed frequency-row accumulation for the operator-norm predicate. +//! +//! Precomputes `cos_at[pos][k]`, `sin_at[pos][k]` so each nonzero updates all +//! `D/2` frequency accumulators from a contiguous row. On aarch64 the inner +//! row update uses NEON (`i64x2`). + +use crate::sampler::op_norm::OpNormTable; + +pub(super) const FUSED_CHUNK_FREQS: usize = 4; + +/// Build `freq_cos_at[pos * half_d + k]` and `freq_sin_at[...]` from the +/// certified base tables. +pub(super) fn build_freq_at_tables( + d: usize, + base_cos: &[i64], + base_sin: &[i64], +) -> (Vec, Vec) { + let half_d = d / 2; + let two_d = 2 * d; + let mut freq_cos = vec![0i64; d * half_d]; + let mut freq_sin = vec![0i64; d * half_d]; + for pos in 0..d { + let row = pos * half_d; + for k in 0..half_d { + let mult = (2 * k + 1) % two_d; + let idx = (mult * pos) % two_d; + freq_cos[row + k] = base_cos[idx]; + freq_sin[row + k] = base_sin[idx]; + } + } + (freq_cos, freq_sin) +} + +/// Accumulate a contiguous frequency chunk into register-sized arrays. +#[inline] +pub(super) fn accumulate_transposed_chunk( + table: &OpNormTable, + positions: &[u32], + coeffs: &[i8], + start_k: usize, + len: usize, + half_d: usize, +) -> ([i64; FUSED_CHUNK_FREQS], [i64; FUSED_CHUNK_FREQS]) { + debug_assert!(len <= FUSED_CHUNK_FREQS); + debug_assert!(start_k + len <= half_d); + + #[cfg(target_arch = "x86_64")] + { + if len == FUSED_CHUNK_FREQS && std::arch::is_x86_feature_detected!("avx2") { + return unsafe { + accumulate_transposed_chunk_avx2(table, positions, coeffs, start_k, half_d) + }; + } + } + #[cfg(target_arch = "aarch64")] + { + if len == FUSED_CHUNK_FREQS { + return unsafe { + accumulate_transposed_chunk_neon(table, positions, coeffs, start_k, half_d) + }; + } + } + + accumulate_transposed_chunk_scalar(table, positions, coeffs, start_k, len, half_d) +} + +#[inline] +pub(super) fn accumulate_transposed_chunk_scalar( + table: &OpNormTable, + positions: &[u32], + coeffs: &[i8], + start_k: usize, + len: usize, + half_d: usize, +) -> ([i64; FUSED_CHUNK_FREQS], [i64; FUSED_CHUNK_FREQS]) { + let mut acc_re = [0i64; FUSED_CHUNK_FREQS]; + let mut acc_im = [0i64; FUSED_CHUNK_FREQS]; + for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { + let coeff = i64::from(coeff); + let row = table.freq_row(pos as usize, half_d); + let (cos_row, sin_row) = row; + for lane in 0..len { + let k = start_k + lane; + acc_re[lane] += coeff * cos_row[k]; + acc_im[lane] += coeff * sin_row[k]; + } + } + (acc_re, acc_im) +} + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "avx2")] +unsafe fn accumulate_transposed_chunk_avx2( + table: &OpNormTable, + positions: &[u32], + coeffs: &[i8], + start_k: usize, + half_d: usize, +) -> ([i64; FUSED_CHUNK_FREQS], [i64; FUSED_CHUNK_FREQS]) { + use core::arch::x86_64::{ + __m256i, _mm256_add_epi64, _mm256_loadu_si256, _mm256_setzero_si256, _mm256_storeu_si256, + _mm256_sub_epi64, + }; + + let mut acc_re = _mm256_setzero_si256(); + let mut acc_im = _mm256_setzero_si256(); + for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { + let row = table.freq_row(pos as usize, half_d); + let (cos_row, sin_row) = row; + let cos_v = unsafe { _mm256_loadu_si256(cos_row.as_ptr().add(start_k).cast::<__m256i>()) }; + let sin_v = unsafe { _mm256_loadu_si256(sin_row.as_ptr().add(start_k).cast::<__m256i>()) }; + match coeff { + 1 => { + acc_re = _mm256_add_epi64(acc_re, cos_v); + acc_im = _mm256_add_epi64(acc_im, sin_v); + } + -1 => { + acc_re = _mm256_sub_epi64(acc_re, cos_v); + acc_im = _mm256_sub_epi64(acc_im, sin_v); + } + 2 => { + acc_re = _mm256_add_epi64(acc_re, _mm256_add_epi64(cos_v, cos_v)); + acc_im = _mm256_add_epi64(acc_im, _mm256_add_epi64(sin_v, sin_v)); + } + -2 => { + acc_re = _mm256_sub_epi64(acc_re, _mm256_add_epi64(cos_v, cos_v)); + acc_im = _mm256_sub_epi64(acc_im, _mm256_add_epi64(sin_v, sin_v)); + } + _ => { + return accumulate_transposed_chunk_scalar( + table, + positions, + coeffs, + start_k, + FUSED_CHUNK_FREQS, + half_d, + ); + } + } + } + + let mut re = [0i64; FUSED_CHUNK_FREQS]; + let mut im = [0i64; FUSED_CHUNK_FREQS]; + unsafe { + _mm256_storeu_si256(re.as_mut_ptr().cast::<__m256i>(), acc_re); + _mm256_storeu_si256(im.as_mut_ptr().cast::<__m256i>(), acc_im); + } + (re, im) +} + +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +unsafe fn accumulate_transposed_chunk_neon( + table: &OpNormTable, + positions: &[u32], + coeffs: &[i8], + start_k: usize, + half_d: usize, +) -> ([i64; FUSED_CHUNK_FREQS], [i64; FUSED_CHUNK_FREQS]) { + use core::arch::aarch64::{vaddq_s64, vdupq_n_s64, vld1q_s64, vst1q_s64, vsubq_s64}; + + let mut re0 = vdupq_n_s64(0); + let mut im0 = vdupq_n_s64(0); + let mut re1 = vdupq_n_s64(0); + let mut im1 = vdupq_n_s64(0); + for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { + let row = table.freq_row(pos as usize, half_d); + let (cos_row, sin_row) = row; + let cos0 = unsafe { vld1q_s64(cos_row.as_ptr().add(start_k)) }; + let sin0 = unsafe { vld1q_s64(sin_row.as_ptr().add(start_k)) }; + let cos1 = unsafe { vld1q_s64(cos_row.as_ptr().add(start_k + 2)) }; + let sin1 = unsafe { vld1q_s64(sin_row.as_ptr().add(start_k + 2)) }; + match coeff { + 1 => { + re0 = vaddq_s64(re0, cos0); + im0 = vaddq_s64(im0, sin0); + re1 = vaddq_s64(re1, cos1); + im1 = vaddq_s64(im1, sin1); + } + -1 => { + re0 = vsubq_s64(re0, cos0); + im0 = vsubq_s64(im0, sin0); + re1 = vsubq_s64(re1, cos1); + im1 = vsubq_s64(im1, sin1); + } + 2 => { + re0 = vaddq_s64(re0, vaddq_s64(cos0, cos0)); + im0 = vaddq_s64(im0, vaddq_s64(sin0, sin0)); + re1 = vaddq_s64(re1, vaddq_s64(cos1, cos1)); + im1 = vaddq_s64(im1, vaddq_s64(sin1, sin1)); + } + -2 => { + re0 = vsubq_s64(re0, vaddq_s64(cos0, cos0)); + im0 = vsubq_s64(im0, vaddq_s64(sin0, sin0)); + re1 = vsubq_s64(re1, vaddq_s64(cos1, cos1)); + im1 = vsubq_s64(im1, vaddq_s64(sin1, sin1)); + } + _ => { + return accumulate_transposed_chunk_scalar( + table, + positions, + coeffs, + start_k, + FUSED_CHUNK_FREQS, + half_d, + ); + } + } + } + + let mut re = [0i64; FUSED_CHUNK_FREQS]; + let mut im = [0i64; FUSED_CHUNK_FREQS]; + unsafe { + vst1q_s64(re.as_mut_ptr(), re0); + vst1q_s64(im.as_mut_ptr(), im0); + vst1q_s64(re.as_mut_ptr().add(2), re1); + vst1q_s64(im.as_mut_ptr().add(2), im1); + } + (re, im) +} + +#[inline] +#[cfg(test)] +pub(super) fn accumulate_transposed_scalar( + table: &OpNormTable, + positions: &[u32], + coeffs: &[i8], + acc_re: &mut [i64], + acc_im: &mut [i64], +) { + let half_d = acc_re.len(); + for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { + let coeff = i64::from(coeff); + let row = table.freq_row(pos as usize, half_d); + let (cos_row, sin_row) = row; + for k in 0..half_d { + acc_re[k] += coeff * cos_row[k]; + acc_im[k] += coeff * sin_row[k]; + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::sampler::op_norm::OpNormTable; + + fn table(d: usize) -> OpNormTable { + OpNormTable::new(d, 48, (2 * d) as u64, 64).unwrap() + } + + #[test] + fn transposed_scalar_matches_legacy_accumulation() { + let d = 64; + let t = table(d); + let half_d = d / 2; + let mut state = 0xC0FFEE_u64; + for _ in 0..500 { + state = state.wrapping_mul(6364136223846793005).wrapping_add(1); + let mut positions = Vec::new(); + let mut coeffs = Vec::new(); + let weight = 8 + (state as usize % 20); + for i in 0..weight { + let shift = (i as u32).min(63); + positions.push((state.wrapping_shr(shift * 3) as u32) % d as u32); + coeffs.push(if state.wrapping_shr(shift) & 1 == 0 { + 1 + } else { + -2 + }); + } + let mut legacy_re = vec![0i64; half_d]; + let mut legacy_im = vec![0i64; half_d]; + let two_d = 2 * d; + for k in 0..half_d { + let mult = (2 * k + 1) % two_d; + for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { + let idx = (mult * pos as usize) % two_d; + let coeff = i64::from(coeff); + legacy_re[k] += coeff * t.base_cos_i64(idx); + legacy_im[k] += coeff * t.base_sin_i64(idx); + } + } + let mut trans_re = vec![0i64; half_d]; + let mut trans_im = vec![0i64; half_d]; + accumulate_transposed_scalar(&t, &positions, &coeffs, &mut trans_re, &mut trans_im); + assert_eq!(legacy_re, trans_re); + assert_eq!(legacy_im, trans_im); + for start_k in (0..half_d).step_by(FUSED_CHUNK_FREQS) { + let len = (half_d - start_k).min(FUSED_CHUNK_FREQS); + let (chunk_re, chunk_im) = + accumulate_transposed_chunk(&t, &positions, &coeffs, start_k, len, half_d); + assert_eq!(&legacy_re[start_k..start_k + len], &chunk_re[..len]); + assert_eq!(&legacy_im[start_k..start_k + len], &chunk_im[..len]); + } + } + } + + #[test] + fn transposed_chunk_handles_generic_coefficients() { + let d = 64; + let t = table(d); + let half_d = d / 2; + let positions = [0, 7, 19, 42, 63]; + let coeffs = [3, -4, 1, -2, 5]; + let mut legacy_re = vec![0i64; half_d]; + let mut legacy_im = vec![0i64; half_d]; + let two_d = 2 * d; + for k in 0..half_d { + let mult = (2 * k + 1) % two_d; + for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { + let idx = (mult * pos as usize) % two_d; + let coeff = i64::from(coeff); + legacy_re[k] += coeff * t.base_cos_i64(idx); + legacy_im[k] += coeff * t.base_sin_i64(idx); + } + } + for start_k in (0..half_d).step_by(FUSED_CHUNK_FREQS) { + let len = (half_d - start_k).min(FUSED_CHUNK_FREQS); + let (chunk_re, chunk_im) = + accumulate_transposed_chunk(&t, &positions, &coeffs, start_k, len, half_d); + assert_eq!(&legacy_re[start_k..start_k + len], &chunk_re[..len]); + assert_eq!(&legacy_im[start_k..start_k + len], &chunk_im[..len]); + } + } + + #[cfg(target_arch = "x86_64")] + #[test] + fn transposed_chunk_avx2_matches_legacy_when_available() { + if !std::arch::is_x86_feature_detected!("avx2") { + return; + } + + let d = 64; + let t = table(d); + let half_d = d / 2; + let positions = [1, 5, 9, 17, 23, 31, 47, 58]; + let coeffs = [1, -1, 2, -2, 1, 2, -1, -2]; + for start_k in (0..half_d).step_by(FUSED_CHUNK_FREQS) { + let scalar = accumulate_transposed_chunk_scalar( + &t, + &positions, + &coeffs, + start_k, + FUSED_CHUNK_FREQS, + half_d, + ); + let avx2 = unsafe { + accumulate_transposed_chunk_avx2(&t, &positions, &coeffs, start_k, half_d) + }; + assert_eq!(scalar, avx2); + } + } +} diff --git a/crates/akita-challenges/src/sampler/signed_sparse.rs b/crates/akita-challenges/src/sampler/signed_sparse.rs index 01bbcbd7a..2816975b2 100644 --- a/crates/akita-challenges/src/sampler/signed_sparse.rs +++ b/crates/akita-challenges/src/sampler/signed_sparse.rs @@ -81,4 +81,12 @@ impl SignedSparseScratch { coeffs: self.coeffs.iter().copied().collect(), } } + + pub(crate) fn positions(&self) -> &[u32] { + &self.positions + } + + pub(crate) fn coeffs(&self) -> &[i8] { + &self.coeffs + } } diff --git a/crates/akita-config/src/lib.rs b/crates/akita-config/src/lib.rs index b7f32cca7..cc5e9094a 100644 --- a/crates/akita-config/src/lib.rs +++ b/crates/akita-config/src/lib.rs @@ -37,7 +37,6 @@ macro_rules! impl_multi_chunk_companion { const RING_DIMENSION_SCHEDULE_MODE: akita_schedules::RingDimensionScheduleMode = <$base as $crate::CommitmentConfig>::RING_DIMENSION_SCHEDULE_MODE; const EXT_DEGREE: usize = <$base as $crate::CommitmentConfig>::EXT_DEGREE; - fn decomposition() -> akita_types::DecompositionParams { <$base as $crate::CommitmentConfig>::decomposition() } @@ -52,9 +51,6 @@ macro_rules! impl_multi_chunk_companion { fn sis_modulus_profile() -> akita_types::SisModulusProfileId { <$base as $crate::CommitmentConfig>::sis_modulus_profile() } - fn ring_subfield_embedding_norm_bound() -> u32 { - <$base as $crate::CommitmentConfig>::ring_subfield_embedding_norm_bound() - } fn setup_matrix_capacity( max_num_vars: usize, max_num_batched_polys: usize, @@ -126,6 +122,8 @@ pub fn policy_of() -> PlannerPolicy { let recursive_setup_planning = Cfg::recursive_setup_planning(); PlannerPolicy { cost_model: akita_schedules::PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: + akita_schedules::SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: Cfg::selection_policy(), recursive_split_search_policy: akita_schedules::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, @@ -138,7 +136,7 @@ pub fn policy_of() -> PlannerPolicy { sis_modulus_profile: Cfg::sis_modulus_profile(), sis_security_policy: akita_types::DEFAULT_SIS_SECURITY_POLICY, sis_table_digest: akita_types::sis::SisTableDigest::CURRENT, - ring_subfield_norm_bound: Cfg::ring_subfield_embedding_norm_bound(), + sis_l2_table_digest: akita_types::SisL2TableDigest::CURRENT, claim_ext_degree: Cfg::EXT_DEGREE, chal_ext_degree: Cfg::EXT_DEGREE, inner_basis_range: Cfg::inner_basis_range(), @@ -244,21 +242,6 @@ pub trait CommitmentConfig: Clone + Send + Sync + 'static { } } - /// Infinity-norm expansion introduced when claim-field coordinates are - /// embedded into the ring subfield via `psi`. - /// - /// For the base-field path (`K=1`), `psi` is ordinary coefficient packing. - /// For the current small-field ring-subfield embeddings (`K>1`), one input - /// coefficient can contribute through paired ring lanes, so SIS A-role - /// collision pricing uses a conservative factor of two. - fn ring_subfield_embedding_norm_bound() -> u32 { - if Self::EXT_DEGREE == 1 { - 1 - } else { - 2 - } - } - /// Packed capacity envelope for the shared setup matrix. /// /// # Errors @@ -541,7 +524,7 @@ mod tests { #[cfg(test)] mod sis_schedule_width_audit { use super::*; - use akita_types::sis::min_secure_rank; + use akita_types::sis::{min_secure_l2_rank, min_secure_rank, InnerCommitSecurityRoute}; pub(super) fn assert_schedule_stays_within_audited_sis_widths( schedule: &FoldSchedule, @@ -558,10 +541,13 @@ mod sis_schedule_width_audit { { let d = u32::try_from(lp.d_a()).expect("ring dimension fits in u32"); - let a_rank = min_secure_rank( - lp.inner_commit_matrix.sis_table_key(), - u64::try_from(lp.inner_width()).expect("inner width should fit in u64"), - ) + let width = u64::try_from(lp.inner_width()).expect("inner width should fit in u64"); + let a_rank = match lp.inner_commit_matrix.security_route() { + InnerCommitSecurityRoute::Linf(key) => min_secure_rank(key, width), + InnerCommitSecurityRoute::L2 { table_key, .. } => { + min_secure_l2_rank(table_key, width) + } + } .unwrap_or_else(|| { panic!( "missing audited A-row SIS width for D={d}, num_vars={num_vars}, level={level_idx}, lb={}, width={}", @@ -682,31 +668,6 @@ mod fp128_policy_tests { assert_cfg_schedule_stays_within_audited_sis_widths::(CI_SIS_WIDTH_NUM_VARS); } - #[test] - fn small_field_sis_pricing_includes_psi_norm_bound() { - use super::proof_optimized::{fp128, fp32}; - - type SmallCfg = fp32::OneHot; - assert_eq!( - ::ring_subfield_embedding_norm_bound(), - 1 - ); - assert_eq!( - ::ring_subfield_embedding_norm_bound(), - 2 - ); - - let opening_batch = OpeningClaimsLayout::new(28, 1).expect("singleton opening batch"); - let schedule = - SmallCfg::get_params_for_prove(&opening_batch).expect("small-field schedule"); - let root_params = &schedule.root.params.final_group.commitment; - assert!( - root_params.inner_commit_matrix.coeff_linf_bound() - >= root_params.outer_commit_matrix.coeff_linf_bound() * 2, - "A-role L-infinity bound should include the psi norm bound" - ); - } - #[test] fn fp128_generated_singleton_plans_resolve() { let key = PolynomialGroupLayout::singleton(32); diff --git a/crates/akita-config/src/proof_optimized.rs b/crates/akita-config/src/proof_optimized.rs index 588b6e42b..2716d1e8b 100644 --- a/crates/akita-config/src/proof_optimized.rs +++ b/crates/akita-config/src/proof_optimized.rs @@ -47,7 +47,8 @@ const fn proof_optimized_inner_basis_range( /// Smaller/nonstandard chunking is represented by a separately named preset /// or application polynomial representation; it is never inferred as a /// fallback. -pub const STANDARD_ONEHOT_CHUNK_SIZE: usize = 256; +pub const STANDARD_ONEHOT_CHUNK_SIZE: usize = + akita_types::sis::DEFAULT_UNIT_ONEHOT_SOURCE_CHUNK_SIZE; /// Bound setup preprocessing work before schedule resolution. /// @@ -510,7 +511,6 @@ macro_rules! impl_proof_optimized_preset { type Field = $field; type ExtField = $ext_field; const D: usize = $d; - impl_proof_optimized_preset!(@options $($options)*); fn decomposition() -> akita_types::DecompositionParams { @@ -593,7 +593,6 @@ macro_rules! impl_proof_optimized_preset { type Field = $field; type ExtField = $ext_field; const D: usize = $d; - impl_proof_optimized_preset!(@options $($options)*); fn decomposition() -> akita_types::DecompositionParams { diff --git a/crates/akita-config/src/proof_optimized/tests.rs b/crates/akita-config/src/proof_optimized/tests.rs index 024bca214..f16d17a02 100644 --- a/crates/akita-config/src/proof_optimized/tests.rs +++ b/crates/akita-config/src/proof_optimized/tests.rs @@ -1,7 +1,7 @@ use super::*; #[cfg(feature = "schedules-default")] -use crate::proof_optimized::{fp128, fp32}; +use crate::proof_optimized::{fp128, fp32, fp64}; #[cfg(feature = "schedules-default")] use crate::CommitmentConfig; #[cfg(feature = "schedules-default")] @@ -45,6 +45,292 @@ fn generated_schedule_has_explicit_terminal_inner_only_topology() { ); } +#[cfg(feature = "schedules-default")] +#[test] +fn d64_selective_l2_binds_the_certified_operator_norm_family() { + let key = AkitaScheduleLookupKey::single(PolynomialGroupLayout::singleton(40)); + let schedule = + fp128::OneHot::runtime_schedule(key.clone()).expect("generated one-hot schedule"); + let (step, table_key, response_cap) = schedule + .recursive_folds + .iter() + .find_map( + |step| match step.params.witness.inner_commit_matrix.security_route() { + akita_types::InnerCommitSecurityRoute::Linf(_) => None, + akita_types::InnerCommitSecurityRoute::L2 { + table_key, + response_l2_sq_cap, + .. + } => Some((step, table_key, response_l2_sq_cap)), + }, + ) + .expect("shipped fp128 row must retain one L2 route"); + assert_eq!( + step.params.witness.fold_challenge_config, + akita_challenges::D64_SELECTIVE_L2_CHALLENGE_CONFIG, + ); + assert_eq!(step.params.witness.log_basis_open, 4); + assert_eq!(step.params.witness.num_digits_fold, 3); + assert_eq!( + step.params.witness.inner_commit_matrix.input_width() + * step.params.witness.inner_commit_matrix.ring_dimension(), + 65_536, + ); + assert_eq!(step.params.witness.inner_commit_matrix.output_rank(), 3); + assert_eq!(response_cap, 262_954_353); + let expected_collision = akita_types::sis::role_a_collision_l2_sq_for_response_bound( + u128::from(akita_challenges::OperatorNormRejection::D64_SELECTIVE_L2.threshold), + response_cap, + ) + .expect("collision bound"); + assert_eq!( + table_key.collision_l2_sq, + expected_collision.next_power_of_two() + ); + + let catalog = fp128::OneHot::schedule_catalog().expect("fp128 catalog"); + let entry = akita_schedules::generated::table_entry(catalog, &key).expect("catalog row"); + let proof_bytes = akita_schedules::estimate_proof_bytes( + entry, + &key, + &crate::policy_of::(), + fp128::OneHot::ring_challenge_config, + ) + .expect("proof estimate"); + let mut no_l2_policy = crate::policy_of::(); + no_l2_policy.selective_l2_response_model = + akita_schedules::SelectiveL2ResponseModelId::Disabled; + let no_l2_bytes = akita_planner::find_schedule( + &key, + fp128::OneHot::root_honest_fold_policy(), + &[], + &no_l2_policy, + fp128::OneHot::ring_challenge_config, + ) + .expect("Linf-only schedule") + .estimate + .estimated_proof_payload_bytes() + .expect("Linf-only proof estimate"); + assert!(proof_bytes < no_l2_bytes); +} + +#[cfg(feature = "schedules-default")] +#[test] +fn fp64_response_model_selects_globally_winning_l2_suffix() { + let key = AkitaScheduleLookupKey::single(PolynomialGroupLayout::singleton(28)); + let schedule = fp64::OneHot::runtime_schedule(key.clone()).expect("generated fp64 schedule"); + assert!(schedule.recursive_folds.iter().any(|step| matches!( + step.params.witness.inner_commit_matrix.security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ))); + let terminal = &schedule.terminal.params; + assert_eq!( + terminal.sparse_challenge_config, + akita_challenges::D64_SELECTIVE_L2_CHALLENGE_CONFIG, + ); + assert_eq!(terminal.witness.response_l2_sq_cap(), Some(2_618_810_696)); + assert_eq!(terminal.witness.inner_commit_matrix.output_rank(), 7); + + let catalog = fp64::OneHot::schedule_catalog().expect("fp64 catalog"); + let entry = akita_schedules::generated::table_entry(catalog, &key).expect("catalog row"); + let proof_bytes = akita_schedules::estimate_proof_bytes( + entry, + &key, + &crate::policy_of::(), + fp64::OneHot::ring_challenge_config, + ) + .expect("proof estimate"); + let mut linf_policy = crate::policy_of::(); + linf_policy.selective_l2_response_model = akita_schedules::SelectiveL2ResponseModelId::Disabled; + let linf_schedule = akita_planner::find_schedule( + &key, + fp64::OneHot::root_honest_fold_policy(), + &[], + &linf_policy, + fp64::OneHot::ring_challenge_config, + ) + .expect("fp64 Linf schedule"); + let linf_bytes = linf_schedule + .estimate + .estimated_proof_payload_bytes() + .expect("fp64 proof estimate"); + assert_eq!( + schedule.recursive_folds.len(), + linf_schedule.schedule.recursive_folds.len(), + "the modeled L2 suffix should improve bytes without adding a fold" + ); + assert!(proof_bytes < linf_bytes); +} + +#[cfg(feature = "schedules-default")] +#[test] +fn terminal_l2_preserves_its_own_fold_geometry() { + let key = AkitaScheduleLookupKey::single(PolynomialGroupLayout::singleton(28)); + let catalog = fp128::Dense::schedule_catalog().expect("fp128 dense catalog"); + let entry = akita_schedules::generated::table_entry(catalog, &key).expect("catalog row"); + assert_eq!( + ( + entry.terminal.fold_log_basis, + entry.terminal.fold_digit_count + ), + (6, 2) + ); + + let schedule = fp128::Dense::runtime_schedule(key).expect("generated dense schedule"); + let predecessor = &schedule + .recursive_folds + .last() + .expect("recursive predecessor") + .params + .witness; + assert_eq!( + (predecessor.log_basis_open, predecessor.num_digits_fold), + (5, 2) + ); + assert_eq!( + ( + schedule.terminal.params.witness.fold_log_basis, + schedule.terminal.params.witness.fold_digit_count, + ), + (6, 2) + ); + assert!(matches!( + schedule + .terminal + .params + .witness + .inner_commit_matrix + .security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + )); +} + +#[cfg(feature = "schedules-default")] +#[test] +fn response_model_reduces_planned_payload_in_every_field_profile() { + fn compare(num_vars: usize) { + let policy = crate::policy_of::(); + assert!( + matches!( + policy.selective_l2_response_model, + akita_schedules::SelectiveL2ResponseModelId::TypedProtocolMomentsV1 + ), + "{} must use the typed L2 response model", + std::any::type_name::() + ); + let key = AkitaScheduleLookupKey::single(PolynomialGroupLayout::singleton(num_vars)); + let catalog = Cfg::schedule_catalog().expect("generated catalog"); + let entry = + akita_schedules::generated::table_entry(catalog, &key).expect("generated schedule row"); + let schedule = Cfg::runtime_schedule(key.clone()).expect("generated runtime schedule"); + let recursive_l2 = schedule.recursive_folds.iter().any(|step| { + matches!( + step.params.witness.inner_commit_matrix.security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ) + }); + let terminal_l2 = matches!( + schedule + .terminal + .params + .witness + .inner_commit_matrix + .security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ); + assert!( + recursive_l2 || terminal_l2, + "{} must ship at least one selected L2 route", + std::any::type_name::() + ); + let modeled = akita_schedules::estimate_proof_bytes( + entry, + &key, + &crate::policy_of::(), + Cfg::ring_challenge_config, + ) + .expect("modeled proof estimate"); + let mut linf_policy = crate::policy_of::(); + linf_policy.selective_l2_response_model = + akita_schedules::SelectiveL2ResponseModelId::Disabled; + let linf = akita_planner::find_schedule( + &key, + Cfg::root_honest_fold_policy(), + &[], + &linf_policy, + Cfg::ring_challenge_config, + ) + .expect("L-infinity schedule") + .estimate + .estimated_proof_payload_bytes() + .expect("L-infinity proof estimate"); + assert!(modeled < linf); + } + + compare::(30); + compare::(26); + compare::(30); + compare::(26); + compare::(36); + compare::(28); + + #[cfg(feature = "all-schedules")] + compare::(16); +} + +#[cfg(feature = "all-schedules")] +#[test] +fn every_generated_profile_opts_in_and_ships_an_l2_route() { + fn assert_profile() { + let policy = crate::policy_of::(); + assert!( + matches!( + policy.selective_l2_response_model, + akita_schedules::SelectiveL2ResponseModelId::TypedProtocolMomentsV1 + ), + "{} must use the typed L2 response model", + std::any::type_name::() + ); + let catalog = Cfg::schedule_catalog().expect("generated catalog"); + let has_l2 = catalog.entries.iter().any(|entry| { + let schedule = Cfg::runtime_schedule(entry.to_runtime_lookup_key()) + .expect("generated schedule must expand"); + schedule.recursive_folds.iter().any(|step| { + matches!( + step.params.witness.inner_commit_matrix.security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ) + }) || matches!( + schedule + .terminal + .params + .witness + .inner_commit_matrix + .security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ) + }); + assert!( + has_l2, + "{} must ship at least one selected L2 route", + std::any::type_name::() + ); + } + + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::(); + assert_profile::>(); + assert_profile::>(); +} + #[cfg(feature = "schedules-default")] #[test] fn setup_capacity_includes_terminal_inner_matrix() { diff --git a/crates/akita-config/src/recursive_commitment.rs b/crates/akita-config/src/recursive_commitment.rs index b25847a86..d3f535350 100644 --- a/crates/akita-config/src/recursive_commitment.rs +++ b/crates/akita-config/src/recursive_commitment.rs @@ -25,7 +25,6 @@ impl CommitmentConfig for RecursiveCommitmentConfig const D: usize = Cfg::D; const RING_DIMENSION_SCHEDULE_MODE: akita_schedules::RingDimensionScheduleMode = Cfg::RING_DIMENSION_SCHEDULE_MODE; - fn decomposition() -> DecompositionParams { Cfg::decomposition() } @@ -38,10 +37,6 @@ impl CommitmentConfig for RecursiveCommitmentConfig Cfg::sis_modulus_profile() } - fn ring_subfield_embedding_norm_bound() -> u32 { - Cfg::ring_subfield_embedding_norm_bound() - } - fn setup_matrix_capacity( max_num_vars: usize, max_num_batched_polys: usize, diff --git a/crates/akita-config/tests/dense_inner_basis.rs b/crates/akita-config/tests/dense_inner_basis.rs index a22cda9a2..249b56943 100644 --- a/crates/akita-config/tests/dense_inner_basis.rs +++ b/crates/akita-config/tests/dense_inner_basis.rs @@ -78,21 +78,21 @@ fn dense_nv26_proof_first_winners_keep_inner_basis_independent() { assert_eq!( fp64, Snapshot { - inner_basis: 6, + inner_basis: 10, opening_basis: 3, positions: 512, blocks: 256, - inner_digits: 11, + inner_digits: 7, n_a: 2, n_b: 1, n_d: 1, - a_input_raw: 2_883_584, + a_input_raw: 1_835_008, a_output_raw: 1_024, b_input_raw: 5_767_168, b_output_raw: 256, d_input_raw: 2_883_584, d_output_raw: 256, - next_witness: 23_152_896, + next_witness: 19_745_024, } ); diff --git a/crates/akita-config/tests/generated_tables.rs b/crates/akita-config/tests/generated_tables.rs index d6f845bd2..591ffa44d 100644 --- a/crates/akita-config/tests/generated_tables.rs +++ b/crates/akita-config/tests/generated_tables.rs @@ -206,6 +206,11 @@ fn catalog_identity_rejects_planner_policy_changes() { let mut mutated = catalog; mutated.identity.min_offloaded_witness_contraction += 1; assert_rejected("offloaded witness contraction", mutated); + + let mut mutated = catalog; + mutated.identity.selective_l2_response_model = + akita_schedules::SelectiveL2ResponseModelId::Disabled; + assert_rejected("selective L2 response model", mutated); } #[cfg(feature = "all-schedules")] diff --git a/crates/akita-config/tests/runtime_fallback.rs b/crates/akita-config/tests/runtime_fallback.rs index c794af6d6..7f9bc118c 100644 --- a/crates/akita-config/tests/runtime_fallback.rs +++ b/crates/akita-config/tests/runtime_fallback.rs @@ -180,7 +180,7 @@ fn assert_mutated_row_is_rejected( } #[test] -fn resolved_row_audit_rejects_low_rank_root_d_and_terminal_a() { +fn resolved_row_audit_rejects_low_rank_root_d_and_a() { type Cfg = fp128::Dense; let catalog = Cfg::schedule_catalog().expect("dense schedule catalog"); @@ -217,26 +217,31 @@ fn resolved_row_audit_rejects_low_rank_root_d_and_terminal_a() { ); assert_mutated_row_is_rejected::(profiles.clone(), low_rank_d); - let mut low_rank_terminal = selected.schedule().clone(); - let matrix = &low_rank_terminal - .terminal + let mut low_rank_a = selected.schedule().clone(); + let matrix = &low_rank_a + .root .params - .witness + .final_group + .commitment .inner_commit_matrix; - low_rank_terminal - .terminal + let table_key = matrix + .sis_table_key() + .expect("root A matrix must use the L infinity route"); + low_rank_a + .root .params - .witness + .final_group + .commitment .inner_commit_matrix = akita_types::InnerCommitMatrixParams::new_unchecked( - matrix.security_policy(), - matrix.sis_table_key().table_digest, - matrix.sis_modulus_profile(), + table_key.policy, + table_key.table_digest, + table_key.modulus_profile, 0, matrix.input_width(), - matrix.coeff_linf_bound(), - matrix.ring_dimension(), + table_key.coeff_linf_bound, + table_key.ring_dimension as usize, ); - assert_mutated_row_is_rejected::(profiles, low_rank_terminal); + assert_mutated_row_is_rejected::(profiles, low_rank_a); } #[test] @@ -312,6 +317,8 @@ fn assert_policy_matches_cfg() { let policy = policy_of::(); let expected = PlannerPolicy { cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: + akita_schedules::SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: Cfg::selection_policy(), recursive_split_search_policy: akita_schedules::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, @@ -324,7 +331,7 @@ fn assert_policy_matches_cfg() { sis_modulus_profile: Cfg::sis_modulus_profile(), sis_security_policy: akita_types::DEFAULT_SIS_SECURITY_POLICY, sis_table_digest: akita_types::SisTableDigest::CURRENT, - ring_subfield_norm_bound: Cfg::ring_subfield_embedding_norm_bound(), + sis_l2_table_digest: akita_types::SisL2TableDigest::CURRENT, claim_ext_degree: Cfg::EXT_DEGREE, chal_ext_degree: Cfg::EXT_DEGREE, inner_basis_range: Cfg::inner_basis_range(), diff --git a/crates/akita-pcs/Cargo.toml b/crates/akita-pcs/Cargo.toml index a7957cc6d..53fcb1ce9 100644 --- a/crates/akita-pcs/Cargo.toml +++ b/crates/akita-pcs/Cargo.toml @@ -173,6 +173,10 @@ harness = false name = "root_kernels" harness = false +[[bench]] +name = "decompose_fold" +harness = false + [[bench]] name = "digit_range" harness = false diff --git a/crates/akita-pcs/benches/decompose_fold.rs b/crates/akita-pcs/benches/decompose_fold.rs new file mode 100644 index 000000000..3bed54462 --- /dev/null +++ b/crates/akita-pcs/benches/decompose_fold.rs @@ -0,0 +1,142 @@ +#![allow(missing_docs)] + +use akita_algebra::ring::cyclotomic::decompose_centering_threshold; +use akita_algebra::CyclotomicRing; +use akita_challenges::{SparseChallenge, SparseChallengeConfig}; +use akita_field::{CanonicalField, Prime128OffsetA7F7, Prime32Offset99, Prime64Offset59}; +use akita_prover::backend::poly_helpers::{ + balanced_ring_decompose_fold_partitioned, balanced_tight_digit_fold_partitioned, + DecomposeParams, +}; +use akita_types::sis::compute_num_digits_field_width; +use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; + +const FIELD_COEFFICIENTS: usize = 1 << 22; +const POSITIONS_PER_BLOCK: usize = 512; + +fn challenge(block: usize) -> SparseChallenge { + let config = SparseChallengeConfig::production_for_ring_dim(D).expect("production challenge"); + let weight = config.weight(); + let positions = (0..weight) + .map(|term| ((term * 37 + block * 13) % D) as u32) + .collect(); + let coeffs = (0..weight) + .map(|term| { + let magnitude = if term < config.count_pm1 { 1 } else { 2 }; + if (term + block).is_multiple_of(2) { + magnitude + } else { + -magnitude + } + }) + .collect(); + SparseChallenge { positions, coeffs } +} + +fn dense_rings() -> Vec> { + let num_rings = FIELD_COEFFICIENTS / D; + (0..num_rings) + .map(|ring| { + CyclotomicRing::from_coefficients(std::array::from_fn(|coefficient| { + let index = (ring * D + coefficient) as u128; + let mixed = index + .wrapping_mul(0x9e37_79b9_7f4a_7c15_6a09_e667_f3bc_c909) + .rotate_left(37) + ^ index.wrapping_mul(0xbf58_476d_1ce4_e5b9_94d0_49bb_1331_11eb); + F::from_canonical_u128_reduced(mixed) + })) + }) + .collect() +} + +fn dense_case( + c: &mut Criterion, + field_label: &str, + field_bits: u32, + log_basis: u32, +) { + let rings = dense_rings::(); + let blocks = rings.len().div_ceil(POSITIONS_PER_BLOCK); + let challenges = (0..blocks).map(challenge::).collect::>(); + let num_digits = compute_num_digits_field_width(field_bits, log_basis); + let q = (-F::one()).to_canonical_u128() + 1; + let threshold = decompose_centering_threshold(num_digits, log_basis, q); + let params = DecomposeParams { + threshold, + q, + mask: (1i128 << log_basis) - 1, + half_b: 1i128 << (log_basis - 1), + b_val: 1i128 << log_basis, + log_basis, + overflow_possible: q.saturating_sub(threshold) > i128::MAX as u128, + }; + + let mut group = c.benchmark_group(format!("decompose_fold/dense_{field_label}")); + group.throughput(Throughput::Elements(FIELD_COEFFICIENTS as u64)); + group.bench_function(format!("d{D}_b{log_basis}_digits{num_digits}"), |b| { + b.iter(|| { + black_box(balanced_ring_decompose_fold_partitioned( + black_box(&rings), + black_box(&challenges), + POSITIONS_PER_BLOCK, + num_digits, + ¶ms, + )) + }); + }); + group.finish(); +} + +fn suffix_case(c: &mut Criterion) { + let rings: Vec<[i8; D]> = (0..FIELD_COEFFICIENTS / D) + .map(|ring| { + std::array::from_fn(|coefficient| { + (((ring * D + coefficient) * 11 + ring * 3) % 7) as i8 - 3 + }) + }) + .collect::>(); + let blocks = rings.len().div_ceil(POSITIONS_PER_BLOCK); + let challenges = (0..blocks).map(challenge::).collect::>(); + + let mut group = c.benchmark_group("decompose_fold/tight_suffix"); + group.throughput(Throughput::Elements(FIELD_COEFFICIENTS as u64)); + group.bench_function(format!("d{D}"), |b| { + b.iter(|| { + black_box(balanced_tight_digit_fold_partitioned( + black_box(&rings), + black_box(&challenges), + POSITIONS_PER_BLOCK, + )) + }); + }); + group.finish(); +} + +fn bench_decompose_fold(c: &mut Criterion) { + dense_case::(c, "fp32", 32, 8); + dense_case::(c, "fp32", 32, 8); + dense_case::(c, "fp32", 32, 8); + dense_case::(c, "fp32", 32, 8); + dense_case::(c, "fp32", 32, 8); + dense_case::(c, "fp32", 32, 8); + + dense_case::(c, "fp64", 64, 6); + dense_case::(c, "fp64", 64, 6); + dense_case::(c, "fp64", 64, 6); + dense_case::(c, "fp64", 64, 6); + dense_case::(c, "fp64", 64, 6); + dense_case::(c, "fp64", 64, 6); + + dense_case::(c, "fp128", 128, 9); + dense_case::(c, "fp128", 128, 9); + dense_case::(c, "fp128", 128, 9); + dense_case::(c, "fp128", 128, 9); + dense_case::(c, "fp128", 128, 9); + dense_case::(c, "fp128", 128, 9); + + suffix_case::<64>(c); + suffix_case::<128>(c); +} + +criterion_group!(decompose_fold, bench_decompose_fold); +criterion_main!(decompose_fold); diff --git a/crates/akita-pcs/benches/digit_range.rs b/crates/akita-pcs/benches/digit_range.rs index 72ecb3d42..f98432e0a 100644 --- a/crates/akita-pcs/benches/digit_range.rs +++ b/crates/akita-pcs/benches/digit_range.rs @@ -48,7 +48,7 @@ fn bench_digit_range(c: &mut Criterion) { |(prover, mut transcript)| { black_box( prover - .prove(&mut transcript) + .prove(&mut transcript, None) .expect("benchmark proof succeeds"), ); }, @@ -71,7 +71,7 @@ fn bench_digit_range(c: &mut Criterion) { black_box( input .build() - .prove(&mut transcript) + .prove(&mut transcript, None) .expect("benchmark proof succeeds"), ); }, @@ -85,7 +85,7 @@ fn bench_digit_range(c: &mut Criterion) { let (proof, _) = case .prover_input() .build() - .prove(&mut prover_transcript) + .prove(&mut prover_transcript, None) .expect("benchmark reference proof"); group.bench_with_input( BenchmarkId::new("verify", &case_name), diff --git a/crates/akita-pcs/benches/setup_index_weight.rs b/crates/akita-pcs/benches/setup_index_weight.rs index a8a53312b..64e4c638e 100644 --- a/crates/akita-pcs/benches/setup_index_weight.rs +++ b/crates/akita-pcs/benches/setup_index_weight.rs @@ -96,6 +96,7 @@ fn make_case_with_shape( level_params .inner_commit_matrix .sis_table_key() + .expect("benchmark setup matrix is L infinity") .table_digest, level_params.inner_commit_matrix.sis_modulus_profile(), n_a, diff --git a/crates/akita-pcs/examples/profile/modes.rs b/crates/akita-pcs/examples/profile/modes.rs index 547eb4b22..b79b886b6 100644 --- a/crates/akita-pcs/examples/profile/modes.rs +++ b/crates/akita-pcs/examples/profile/modes.rs @@ -258,6 +258,10 @@ const PROFILE_ALL_MODES: &[ProfileMode] = &[ name: "dense_fp128", run: run_profile_dense_fp128, }, + ProfileMode { + name: "dense_fp128_multi_chunk_w8r2", + run: run_profile_dense_fp128_multi_chunk_w8r2, + }, ProfileMode { name: "onehot_fp128", run: run_profile_onehot_fp128, @@ -319,6 +323,7 @@ fn profile_modes() -> &'static [ProfileMode] { /// Modes registered for explicit `AKITA_MODE=…` runs but omitted from `all`. #[cfg(not(feature = "profile-onehot-fp128"))] const EXCLUDED_FROM_ALL_SWEEP: &[&str] = &[ + "dense_fp128_multi_chunk_w8r2", "onehot_fp128_multi_group", "onehot_fp128_multi_chunk_w2r2", "onehot_fp128_multi_chunk_w4r2", @@ -373,6 +378,20 @@ fn run_profile_dense_fp128(nv: usize, num_polys: usize) { ); } +fn run_profile_dense_fp128_multi_chunk_w8r2(nv: usize, num_polys: usize) { + type Cfg = fp128::DenseMultiChunk; + assert_eq!(nv, 16, "dense W8R2 profiles nv=16"); + assert_singleton_mode("dense_fp128_multi_chunk_w8r2", num_polys); + let prime = fp128_prime_label(); + run_dense_mode::<{ Cfg::D }, Cfg>( + "dense_fp128_multi_chunk_w8r2", + &format!( + "=== dense_fp128_multi_chunk_w8r2 (fp128, {prime}, adaptive ring dimensions, distributed chunked relation, num_chunks=8 x 2 leading levels) ===" + ), + nv, + ); +} + fn run_profile_onehot_fp128(nv: usize, num_polys: usize) { match profile_setup_contribution_mode() { SetupContributionMode::Direct => { @@ -396,8 +415,8 @@ fn run_profile_onehot_fp128_with_cfg< num_polys: usize, ) { assert!( - matches!(nv, 32 | 36), - "fp128 one-hot profile supports generated nv=32 and nv=36 rows" + matches!(nv, 32 | 36 | 40), + "fp128 one-hot profile supports generated nv=32, nv=36, and nv=40 rows" ); assert_singleton_mode(label, num_polys); diff --git a/crates/akita-pcs/examples/profile/report.rs b/crates/akita-pcs/examples/profile/report.rs index 7e9c530e7..f83f466fb 100644 --- a/crates/akita-pcs/examples/profile/report.rs +++ b/crates/akita-pcs/examples/profile/report.rs @@ -1,16 +1,14 @@ +use akita_challenges::SparseChallengeConfig; use akita_field::{CanonicalField, FieldCore}; use akita_prover::{PreparedCrtNttProfile, PreparedNttCacheMetric}; use akita_serialization::{AkitaSerialize, Compress}; use akita_types::{ - golomb_rice::{ - analyze_z_fold_golomb_encoding, golomb_rice_low_bits_sweep_payload_bytes, - golomb_rice_zigzag_width, rice_low_bits_for_cap, - }, + golomb_rice::{analyze_z_fold_golomb_encoding, golomb_rice_zigzag_width}, layout::proof_size::field_bytes, - sis::num_digits_for_bound, - AkitaBatchedProof, CommittedGroupParams, FoldLevelProof, FoldSchedule, NttTransformDomain, - OpenCommitMatrixParams, PolynomialGroupLayout, PrecommittedLevelParams, SetupSumcheckProof, - TerminalLevelProof, ZFoldEncodingStats, + sis::{compute_num_digits_field_width, num_digits_for_bound}, + AkitaBatchedProof, CommittedGroupParams, FoldLevelProof, FoldSchedule, + InnerCommitSecurityRoute, NttTransformDomain, OpenCommitMatrixParams, PolynomialGroupLayout, + PrecommittedLevelParams, SetupSumcheckProof, TerminalLevelProof, ZFoldEncodingStats, }; pub(crate) fn report_timing(label: &str, phase: &str, elapsed_s: f64) { @@ -150,9 +148,6 @@ pub(crate) fn emit_proof_tail_report( "[{label}] t: {t_bytes} B, field_coeffs={t_field_elems}, ring_elems={t_ring_elems}", ); assert_eq!(tail_bytes, z_wire_bytes + e_bytes + t_bytes); - if std::env::var("AKITA_Z_GOLOMB_SWEEP").ok().as_deref() == Some("1") { - emit_z_golomb_k_sweep(label, segment, schedule, field_bits, z_golomb_bytes); - } } } @@ -191,73 +186,6 @@ fn terminal_response_z_fold_stats( ) } -fn emit_z_golomb_k_sweep( - label: &str, - witness: &akita_types::TerminalResponse, - schedule: &FoldSchedule, - field_bits: u32, - actual_z_payload_bytes: usize, -) { - let Some(group) = witness.layout.groups.first() else { - return; - }; - let Ok(z_values) = akita_types::decode_terminal_z_golomb_payload( - witness - .z_payloads - .first() - .map(Vec::as_slice) - .unwrap_or_default(), - group, - ) else { - return; - }; - let z_values = z_values.into_iter().map(i64::from).collect::>(); - let Ok(stats) = terminal_response_z_fold_stats(witness, schedule, field_bits) else { - return; - }; - let low_bits_hi = stats - .rice_low_bits_cap - .saturating_add(4) - .max(stats.rice_low_bits_sample); - let Ok(sweep) = - golomb_rice_low_bits_sweep_payload_bytes(&z_values, stats.zigzag_w, low_bits_hi) - else { - return; - }; - let low_bits_observed = rice_low_bits_for_cap(u128::from(stats.observed_max_abs)); - eprintln!( - "[{label}] z_golomb_low_bits_sweep (coords={}):", - z_values.len() - ); - for &(rice_low_bits, bytes) in &sweep { - let marker = if rice_low_bits == stats.rice_low_bits_wire { - " <-- wire low bits" - } else if rice_low_bits == stats.rice_low_bits_cap { - " <-- cap low bits (planner reference)" - } else if rice_low_bits == stats.rice_low_bits_sample { - " <-- sample-optimal on this witness" - } else if rice_low_bits == low_bits_observed { - " <-- low bits from observed max only (NOT sound)" - } else { - "" - }; - let delta = bytes as i64 - actual_z_payload_bytes as i64; - eprintln!( - "[{label}] low_bits={rice_low_bits:2}: payload={bytes:6} B ({:.2} bits/coord, delta_vs_actual={delta:+}){marker}", - (bytes.saturating_mul(8)) as f64 / z_values.len().max(1) as f64, - ); - } - if let Some((rice_low_bits, bytes)) = sweep.iter().min_by_key(|(_, b)| *b) { - let save_vs_beta = actual_z_payload_bytes.saturating_sub(*bytes); - eprintln!( - "[{label}] z_golomb_sweep_summary: best low_bits={rice_low_bits} -> {bytes} B \ - (vs actual {actual_z_payload_bytes} B at wire_low_bits={}, delta {save_vs_beta} B; \ - wire low bits must be >= best for honest encodes)", - stats.rice_low_bits_wire, - ); - } -} - /// Surface the public setup prefix and every initialized exact NTT cache slot. pub(crate) fn report_setup_sizes( label: &str, @@ -350,6 +278,9 @@ struct PlannedGroupReport { d_a: usize, d_b: usize, d_d: usize, + a_width: usize, + b_width: usize, + d_width: usize, n_a: usize, n_b: usize, n_d: usize, @@ -361,14 +292,34 @@ struct PlannedGroupReport { num_digits_open: usize, num_digits_fold: usize, challenge_l1_mass: usize, + challenge_count_pm1: usize, + challenge_count_pm2: usize, + challenge_operator_norm_threshold: Option, num_live_ring_elements_per_claim: usize, num_live_blocks: usize, num_positions_per_block: usize, block_index_domain_size: usize, + security_route: akita_types::InnerCommitSecurityRoute, + response_l2_sq_cap: Option, + norm_proof_shape: Option, setup_prefix_natural_field_elements: usize, setup_prefix_padded_field_elements: usize, } +fn reported_operator_norm_threshold( + security_route: InnerCommitSecurityRoute, + ring_dimension: usize, + challenge: &SparseChallengeConfig, +) -> Option { + match security_route { + InnerCommitSecurityRoute::Linf(_) => None, + InnerCommitSecurityRoute::L2 { .. } => { + akita_challenges::selective_l2_operator_norm_rejection(ring_dimension, challenge) + .map(|policy| policy.threshold) + } + } +} + impl PlannedGroupReport { fn committed( group: String, @@ -379,6 +330,20 @@ impl PlannedGroupReport { params: &CommittedGroupParams, ) -> Self { let role_dims = params.role_dims(); + let security_route = params.inner_commit_matrix.security_route(); + let (response_l2_sq_cap, norm_proof_shape) = match security_route { + akita_types::InnerCommitSecurityRoute::Linf(_) => (None, None), + akita_types::InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, + norm_proof_shape, + .. + } => (Some(response_l2_sq_cap), Some(norm_proof_shape)), + }; + let challenge_operator_norm_threshold = reported_operator_norm_threshold( + security_route, + role_dims.d_a(), + ¶ms.fold_challenge_config, + ); let (public_num_vars, public_num_polynomials) = public_group .map(|layout| (layout.num_vars(), layout.num_polynomials())) .unwrap_or((0, 0)); @@ -392,6 +357,9 @@ impl PlannedGroupReport { d_a: role_dims.d_a(), d_b: role_dims.d_b(), d_d: role_dims.d_d(), + a_width: params.inner_commit_matrix.input_width(), + b_width: params.outer_commit_matrix.input_width(), + d_width: params.open_commit_matrix.input_width(), n_a: params.inner_commit_matrix.output_rank(), n_b: params.outer_commit_matrix.output_rank(), n_d: params.open_commit_matrix.output_rank(), @@ -403,10 +371,16 @@ impl PlannedGroupReport { num_digits_open: params.num_digits_open, num_digits_fold: params.num_digits_fold(), challenge_l1_mass: params.challenge_l1_mass(), + challenge_count_pm1: params.fold_challenge_config.count_pm1, + challenge_count_pm2: params.fold_challenge_config.count_pm2, + challenge_operator_norm_threshold, num_live_ring_elements_per_claim: params.num_live_ring_elements_per_claim, num_live_blocks: params.num_live_blocks, num_positions_per_block: params.num_positions_per_block, block_index_domain_size: params.block_index_domain_size().unwrap_or(0), + security_route, + response_l2_sq_cap, + norm_proof_shape, setup_prefix_natural_field_elements: 0, setup_prefix_padded_field_elements: 0, } @@ -428,6 +402,20 @@ impl PlannedGroupReport { let (public_num_vars, public_num_polynomials) = public_group .map(|layout| (layout.num_vars(), layout.num_polynomials())) .unwrap_or((0, 0)); + let security_route = layout.inner_commit_matrix.security_route(); + let (response_l2_sq_cap, norm_proof_shape) = match security_route { + akita_types::InnerCommitSecurityRoute::Linf(_) => (None, None), + akita_types::InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, + norm_proof_shape, + .. + } => (Some(response_l2_sq_cap), Some(norm_proof_shape)), + }; + let challenge_operator_norm_threshold = reported_operator_norm_threshold( + security_route, + role_dims.d_a(), + ¶ms.fold_challenge_config, + ); Self { group, group_role: if setup_prefix_lengths.is_some() { @@ -442,6 +430,9 @@ impl PlannedGroupReport { d_a: role_dims.d_a(), d_b: role_dims.d_b(), d_d: role_dims.d_d(), + a_width: layout.inner_commit_matrix.input_width(), + b_width: layout.outer_commit_matrix.input_width(), + d_width: shared_open.input_width(), n_a: layout.inner_commit_matrix.output_rank(), n_b: layout.outer_commit_matrix.output_rank(), n_d: shared_open.output_rank(), @@ -453,6 +444,9 @@ impl PlannedGroupReport { num_digits_open: params.num_digits_open, num_digits_fold: params.num_digits_fold, challenge_l1_mass: params.challenge_l1_mass(), + challenge_count_pm1: params.fold_challenge_config.count_pm1, + challenge_count_pm2: params.fold_challenge_config.count_pm2, + challenge_operator_norm_threshold, num_live_ring_elements_per_claim: layout.num_live_ring_elements_per_claim, num_live_blocks: layout.num_live_blocks, num_positions_per_block: layout.num_positions_per_block, @@ -460,12 +454,16 @@ impl PlannedGroupReport { .num_live_blocks .checked_next_power_of_two() .unwrap_or(0), + security_route, + response_l2_sq_cap, + norm_proof_shape, setup_prefix_natural_field_elements, setup_prefix_padded_field_elements, } } - fn emit(&self, label: &str, level: usize) { + fn emit(&self, label: &str, level: usize, field_bits: u32) { + let num_digits_quotient = compute_num_digits_field_width(field_bits, self.log_basis_open); tracing::info!( label, level, @@ -478,6 +476,9 @@ impl PlannedGroupReport { d_a = self.d_a, d_b = self.d_b, d_d = self.d_d, + a_width = self.a_width, + b_width = self.b_width, + d_width = self.d_width, n_a = self.n_a, n_b = self.n_b, n_d = self.n_d, @@ -488,11 +489,18 @@ impl PlannedGroupReport { num_digits_outer = self.num_digits_outer, num_digits_open = self.num_digits_open, num_digits_fold = self.num_digits_fold, + num_digits_quotient, challenge_l1_mass = self.challenge_l1_mass, + challenge_count_pm1 = self.challenge_count_pm1, + challenge_count_pm2 = self.challenge_count_pm2, + challenge_operator_norm_threshold = ?self.challenge_operator_norm_threshold, num_live_ring_elements_per_claim = self.num_live_ring_elements_per_claim, num_live_blocks = self.num_live_blocks, num_positions_per_block = self.num_positions_per_block, block_index_domain_size = self.block_index_domain_size, + security_route = ?self.security_route, + response_l2_sq_cap = ?self.response_l2_sq_cap, + norm_proof_shape = ?self.norm_proof_shape, setup_prefix_natural_field_elements = self.setup_prefix_natural_field_elements, setup_prefix_padded_field_elements = self.setup_prefix_padded_field_elements, "planned fold group" @@ -539,7 +547,7 @@ pub(crate) fn emit_runtime_schedule_summary( root_open, None, ) - .emit(label, 0); + .emit(label, 0, field_bits); } PlannedGroupReport::committed( "final".to_string(), @@ -549,7 +557,7 @@ pub(crate) fn emit_runtime_schedule_summary( Some(final_group), &schedule.root.params.final_group.commitment, ) - .emit(label, 0); + .emit(label, 0, field_bits); for (index, fold) in schedule.recursive_folds.iter().enumerate() { PlannedGroupReport::committed( "folded".to_string(), @@ -559,7 +567,7 @@ pub(crate) fn emit_runtime_schedule_summary( None, &fold.params.witness, ) - .emit(label, index + 1); + .emit(label, index + 1, field_bits); if let Some(prefix) = &fold.params.incoming_setup_prefix { PlannedGroupReport::precommitted( format!("setup_to_L{}", index + 1), @@ -570,7 +578,7 @@ pub(crate) fn emit_runtime_schedule_summary( &fold.params.open_commit_matrix, Some((prefix.natural_len, prefix.n_prefix().unwrap_or(0))), ) - .emit(label, index); + .emit(label, index, field_bits); } } let nonterminal = std::iter::once(( @@ -613,6 +621,20 @@ pub(crate) fn emit_runtime_schedule_summary( let b_output_raw_dimension = lp.outer_commit_matrix.raw_output_dimension(); let d_input_raw_dimension = lp.open_commit_matrix.raw_input_dimension(); let d_output_raw_dimension = lp.open_commit_matrix.raw_output_dimension(); + let security_route = lp.inner_commit_matrix.security_route(); + let (response_l2_sq_cap, norm_proof_shape) = match security_route { + akita_types::InnerCommitSecurityRoute::Linf(_) => (None, None), + akita_types::InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, + norm_proof_shape, + .. + } => (Some(response_l2_sq_cap), Some(norm_proof_shape)), + }; + let challenge_operator_norm_threshold = reported_operator_norm_threshold( + security_route, + role_dims.d_a(), + &lp.fold_challenge_config, + ); tracing::info!( label, level = level_idx, @@ -620,9 +642,15 @@ pub(crate) fn emit_runtime_schedule_summary( d_a = role_dims.d_a(), d_b = role_dims.d_b(), d_d = role_dims.d_d(), + a_width = lp.inner_commit_matrix.input_width(), + b_width = lp.outer_commit_matrix.input_width(), + d_width = lp.open_commit_matrix.input_width(), n_a = lp.inner_commit_matrix.output_rank(), n_b = lp.outer_commit_matrix.output_rank(), n_d = lp.open_commit_matrix.output_rank(), + security_route = ?security_route, + response_l2_sq_cap = ?response_l2_sq_cap, + norm_proof_shape = ?norm_proof_shape, ?a_input_raw_dimension, ?a_output_raw_dimension, ?b_input_raw_dimension, @@ -630,6 +658,9 @@ pub(crate) fn emit_runtime_schedule_summary( ?d_input_raw_dimension, ?d_output_raw_dimension, challenge_l1_mass = lp.challenge_l1_mass(), + challenge_count_pm1 = lp.fold_challenge_config.count_pm1, + challenge_count_pm2 = lp.fold_challenge_config.count_pm2, + challenge_operator_norm_threshold = ?challenge_operator_norm_threshold, log_basis_inner = lp.log_basis_inner, log_basis_outer = lp.log_basis_outer, log_basis_open = lp.log_basis_open, @@ -643,6 +674,7 @@ pub(crate) fn emit_runtime_schedule_summary( num_digits_outer = lp.num_digits_outer, num_digits_open = lp.num_digits_open, delta_fold = lp.num_digits_fold(), + num_digits_quotient = compute_num_digits_field_width(field_bits, lp.log_basis_open), input_witness_len, output_witness_len, current_w_len, @@ -653,54 +685,48 @@ pub(crate) fn emit_runtime_schedule_summary( ); } - // Older merge-base report parsers consume this compatibility event. The - // current parser uses the setup-offload group emitted above. - for (index, fold) in schedule.recursive_folds.iter().enumerate() { - if let Some(prefix) = &fold.params.incoming_setup_prefix { - let layout = &prefix.commitment_params.layout; - tracing::info!( - label, - successor_level = index + 1, - setup_prefix_natural_field_elements = prefix.natural_len, - setup_prefix_padded_field_elements = prefix.n_prefix().unwrap_or(0), - log_basis_inner = layout.log_basis_inner, - log_basis_open = prefix.commitment_params.log_basis_open, - num_live_blocks = layout.num_live_blocks, - num_positions_per_block = layout.num_positions_per_block, - n_a = layout.inner_commit_matrix.output_rank(), - n_b = layout.outer_commit_matrix.output_rank(), - a_input_raw_dimension = ?layout.inner_commit_matrix.raw_input_dimension(), - a_output_raw_dimension = ?layout.inner_commit_matrix.raw_output_dimension(), - b_input_raw_dimension = ?layout.outer_commit_matrix.raw_input_dimension(), - b_output_raw_dimension = ?layout.outer_commit_matrix.raw_output_dimension(), - "planned recursive setup edge" - ); - } - } - + let terminal_level = levels - 1; + let terminal = &schedule.terminal; + let witness = &terminal.params.witness; + let challenge = &terminal.params.sparse_challenge_config; + let security_route = witness.inner_commit_matrix.security_route(); + let response_l2_sq_cap = witness.response_l2_sq_cap(); + let z_admission_linf_cap = terminal + .params + .response_shape + .layout + .groups + .first() + .map(|group| group.z_admission_linf_cap); + let challenge_operator_norm_threshold = + reported_operator_norm_threshold(security_route, witness.d_a(), challenge); tracing::info!( label, - terminal_response_len = schedule.terminal.input_witness_len, - final_inner_log_basis = schedule.terminal.params.witness.log_basis_inner, - final_inner_ring_dimension = schedule.terminal.params.witness.d_a(), - final_inner_module_rank = schedule - .terminal - .params - .witness - .inner_commit_matrix - .output_rank(), - final_inner_input_raw_dimension = ?schedule - .terminal - .params - .witness - .inner_commit_matrix - .raw_input_dimension(), - final_inner_output_raw_dimension = ?schedule - .terminal - .params - .witness - .inner_commit_matrix - .raw_output_dimension(), + level = terminal_level, + input_witness_len = terminal.input_witness_len, + d_a = witness.d_a(), + n_a = witness.inner_commit_matrix.output_rank(), + inner_width = witness.inner_width(), + a_input_raw_dimension = ?witness.inner_commit_matrix.raw_input_dimension(), + a_output_raw_dimension = ?witness.inner_commit_matrix.raw_output_dimension(), + log_basis_inner = witness.log_basis_inner, + num_digits_inner = witness.num_digits_inner, + fold_log_basis = witness.fold_log_basis, + fold_digit_count = witness.fold_digit_count, + challenge_l1_mass = challenge.l1_norm(), + challenge_count_pm1 = challenge.count_pm1, + challenge_count_pm2 = challenge.count_pm2, + challenge_operator_norm_threshold = ?challenge_operator_norm_threshold, + security_route = ?security_route, + response_l2_sq_cap = ?response_l2_sq_cap, + z_admission_linf_cap = ?z_admission_linf_cap, + num_live_ring_elements_per_claim = witness.num_live_ring_elements_per_claim, + num_positions_per_block = witness.num_positions_per_block, + num_live_blocks = witness.num_live_blocks, + block_index_domain_size = witness + .num_live_blocks + .checked_next_power_of_two() + .unwrap_or(0), "planned terminal state" ); } @@ -786,6 +812,10 @@ fn fold_grind_nonce_wire_bytes() -> usize { 0u32.serialized_size(Compress::No) } +fn fold_grind_attempts(accepted_nonce: u32) -> u64 { + u64::from(accepted_nonce) + 1 +} + fn print_akita_level_breakdown( label: &str, level_idx: usize, @@ -824,6 +854,13 @@ where .sum::(); let stage1_range_image_evaluation_size = stage1.range_image_evaluation.serialized_size(Compress::No); + let (stage1_norm_proof_size, response_l2_sq) = + stage1.norm_proof.as_ref().map_or((0, None), |norm| { + ( + norm.serialized_size(Compress::No), + Some(norm.response_l2_sq), + ) + }); let stage2_sumcheck_size = stage2_intermediate .sumcheck_proof .serialized_size(Compress::No); @@ -838,6 +875,7 @@ where .serialized_size(Compress::No); let fold_grind_nonce_size = fold_grind_nonce_wire_bytes(); let grind_nonce = level.fold_grind_nonce; + let grind_attempts = fold_grind_attempts(grind_nonce); tracing::info!( label, @@ -849,9 +887,12 @@ where opening_payload_bytes = opening_payload_size, fold_grind_nonce_bytes = fold_grind_nonce_size, grind_nonce, + grind_attempts, stage1_sumcheck_bytes = stage1_sumcheck_size, stage1_interstage_claims_bytes = stage1_interstage_claims_size, stage1_range_image_evaluation_bytes = stage1_range_image_evaluation_size, + stage1_norm_proof_bytes = stage1_norm_proof_size, + response_l2_sq = ?response_l2_sq, stage2_sumcheck_bytes = stage2_sumcheck_size, stage3_sumcheck_bytes = stage3_sumcheck_size, next_w_payload_bytes = next_w_payload_size, @@ -866,6 +907,7 @@ where eprintln!( "[{label}] stage1_range_image_evaluation={stage1_range_image_evaluation_size} bytes" ); + eprintln!("[{label}] stage1_norm_proof={stage1_norm_proof_size} bytes"); eprintln!("[{label}] stage2_sumcheck={stage2_sumcheck_size} bytes"); eprintln!("[{label}] stage3_sumcheck={stage3_sumcheck_size} bytes"); eprintln!( @@ -882,6 +924,7 @@ where + stage1_sumcheck_size + stage1_interstage_claims_size + stage1_range_image_evaluation_size + + stage1_norm_proof_size + stage2_sumcheck_size + stage3_sumcheck_size + next_w_payload_size @@ -906,6 +949,7 @@ where let terminal_response_size = level.terminal_response().serialized_size(Compress::No); let fold_grind_nonce_size = fold_grind_nonce_wire_bytes(); let grind_nonce = level.fold_grind_nonce; + let grind_attempts = fold_grind_attempts(grind_nonce); let full = level.serialized_size(Compress::No); // `total_bytes` excludes the terminal response to mirror the planner's // `terminal_level_proof_bytes`. The response is reported separately as @@ -927,6 +971,7 @@ where extension_opening_sumcheck_bytes = extension_opening_sumcheck_size, fold_grind_nonce_bytes = fold_grind_nonce_size, grind_nonce, + grind_attempts, terminal_response_bytes = terminal_response_size, root_variant = root_variant, "proof fold level" diff --git a/crates/akita-pcs/src/scheme/tests/fp32_ext4.rs b/crates/akita-pcs/src/scheme/tests/fp32_ext4.rs index 461e19717..a4fd1a1e5 100644 --- a/crates/akita-pcs/src/scheme/tests/fp32_ext4.rs +++ b/crates/akita-pcs/src/scheme/tests/fp32_ext4.rs @@ -29,9 +29,13 @@ fn small_verifier_statement<'a>( } fn onehot_poly(seed: usize) -> OneHotPoly { + onehot_poly_for_num_vars(SMALL_NV, seed) +} + +fn onehot_poly_for_num_vars(num_vars: usize, seed: usize) -> OneHotPoly { let onehot_k = 256; assert!(onehot_k <= 1usize << u8::BITS); - let num_chunks = (1usize << SMALL_NV) / onehot_k; + let num_chunks = (1usize << num_vars) / onehot_k; let indices = (0..num_chunks) .map(|chunk| Some(((chunk * 29 + seed * 41 + 7) % onehot_k) as u8)) .collect(); @@ -101,6 +105,34 @@ fn onehot_opening_at_point(poly: &OneHotPoly, point: &[SmallE]) -> S .fold(SmallE::zero(), |sum, weight| sum + weight) } +fn encode_test_golomb_rice(values: &[i64], rice_low_bits: u32) -> Vec { + let mut bytes = Vec::new(); + let mut bit_position = 0usize; + let mut write_bit = |bit: bool| { + let byte_index = bit_position / 8; + if byte_index == bytes.len() { + bytes.push(0); + } + if bit { + bytes[byte_index] |= 1 << (bit_position % 8); + } + bit_position += 1; + }; + for &value in values { + let zigzag = ((value << 1) ^ (value >> 63)) as u64; + let quotient = zigzag >> rice_low_bits; + for _ in 0..quotient { + write_bit(true); + } + write_bit(false); + let remainder = zigzag & ((1u64 << rice_low_bits) - 1); + for bit in 0..rice_low_bits { + write_bit((remainder >> bit) & 1 == 1); + } + } + bytes +} + #[test] fn fp32_ext4_folded_eor_batched_roundtrip_and_rejections() { let opening_batch = @@ -219,6 +251,282 @@ fn fp32_ext4_folded_eor_batched_roundtrip_and_rejections() { .expect_err("omitting the required root extension-opening reduction must reject"); } +#[test] +fn fp32_ext4_multiblock_l2_pcs_roundtrip_and_stage2_rejections() { + const NUM_VARS: usize = 28; + const LABEL: &[u8] = b"test/fp32-ext4-multiblock-l2-pcs"; + type L2Cfg = SmallCfg; + type L2Scheme = AkitaCommitmentScheme; + + let opening_layout = OpeningClaimsLayout::new(NUM_VARS, 1).expect("L2 opening layout"); + let schedule = L2Cfg::get_params_for_prove(&opening_layout).expect("shipped L2 schedule"); + let l2_step = schedule + .recursive_folds + .iter() + .find(|step| { + matches!( + step.params.witness.inner_commit_matrix.security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ) + }) + .expect("schedule-selected small-field L2 fold"); + assert_eq!(l2_step.params.witness.d_a(), 128); + assert_eq!( + l2_step.params.witness.fold_challenge_config, + akita_challenges::D128_SELECTIVE_L2_CHALLENGE_CONFIG, + ); + assert_eq!( + akita_challenges::selective_l2_operator_norm_rejection( + 128, + &l2_step.params.witness.fold_challenge_config, + ), + Some(akita_challenges::OperatorNormRejection::D128_SELECTIVE_L2), + ); + let akita_types::InnerCommitSecurityRoute::L2 { + norm_proof_shape, .. + } = l2_step.params.witness.inner_commit_matrix.security_route() + else { + unreachable!("selected route checked above") + }; + assert!( + norm_proof_shape + .limb_gram_layout() + .expect("checked LimbGram shape") + .expect("shipped small-field route must use LimbGram") + .block_count() + > 1 + ); + + let poly = onehot_poly_for_num_vars(NUM_VARS, 3); + let point = extension_point(NUM_VARS); + let opening = onehot_opening_at_point(&poly, &point); + + let setup = L2Scheme::setup_prover(NUM_VARS, 1).expect("L2 prover setup"); + let prepared = CpuBackend::DEFAULT + .prepare_setup(&setup) + .expect("prepared L2 setup"); + let stack = akita_prover::UniformProverStack::uniform( + &CpuBackend::DEFAULT, + &prepared, + setup.expanded.as_ref(), + ) + .expect("L2 prover stack"); + let verifier_setup = L2Scheme::setup_verifier(&setup).expect("L2 verifier setup"); + let (commitment, hint) = + L2Scheme::commit(&setup, std::slice::from_ref(&poly), &stack).expect("L2 commitment"); + let poly_refs = [&poly]; + let prover_claims = OpeningClaims::from_groups(vec![PolynomialGroupClaims::new( + point.clone(), + vec![SmallE::zero()], + commitment.clone(), + ) + .expect("L2 prover group")]) + .expect("L2 prover claims"); + let mut prover_transcript = AkitaTranscript::::new(LABEL); + let proof = L2Scheme::batched_prove( + &setup, + selected_prover_data::(prover_claims, vec![hint], vec![&poly_refs]) + .expect("L2 prover data"), + &stack, + &mut prover_transcript, + BasisMode::Lagrange, + ) + .expect("small-field L2 proof"); + let shape = proof.shape(); + let mut bytes = Vec::new(); + proof + .serialize_uncompressed(&mut bytes) + .expect("serialize small-field L2 PCS proof"); + let proof = AkitaBatchedProof::::deserialize_uncompressed(&bytes[..], &shape) + .expect("deserialize small-field L2 PCS proof"); + let l2_index = proof + .recursive_folds + .iter() + .position(|fold| fold.stage1.norm_proof.is_some()) + .expect("proof must carry the selected L2 norm"); + assert!( + proof.recursive_folds[l2_index] + .stage1 + .norm_proof + .as_ref() + .expect("L2 norm proof") + .subclaims + .len() + > 1 + ); + + let verify = |candidate: &AkitaBatchedProof| { + let claims = OpeningClaims::from_groups(vec![PolynomialGroupClaims::new( + point.clone(), + vec![opening], + &commitment, + ) + .expect("L2 verifier group")]) + .expect("L2 verifier claims"); + let mut transcript = AkitaTranscript::::new(LABEL); + L2Scheme::batched_verify( + candidate, + &verifier_setup, + &mut transcript, + selected_statement::(claims).expect("L2 verifier statement"), + BasisMode::Lagrange, + ) + }; + verify(&proof).expect("verify serialized small-field L2 PCS proof"); + + let mut bad_subclaim = proof.clone(); + bad_subclaim.recursive_folds[l2_index] + .stage1 + .norm_proof + .as_mut() + .expect("L2 norm proof") + .subclaims[0] += SmallE::one(); + assert!(verify(&bad_subclaim).is_err()); + + let mut bad_virtual = proof.clone(); + bad_virtual.recursive_folds[l2_index] + .stage1 + .norm_proof + .as_mut() + .expect("L2 norm proof") + .virtual_evaluations[0] += SmallE::one(); + assert!(verify(&bad_virtual).is_err()); + + let mut bad_nonce = proof.clone(); + bad_nonce.recursive_folds[l2_index].fold_grind_nonce += 1; + assert!(verify(&bad_nonce).is_err()); + + let mut bad_stage2 = proof; + bad_stage2.recursive_folds[l2_index] + .stage2 + .sumcheck_proof + .round_polys[0] + .coeffs_except_linear_term[0] += SmallE::one(); + assert!(verify(&bad_stage2).is_err()); +} + +#[test] +fn fp32_nv28_shipped_d128_terminal_l2_roundtrip_and_rejections() { + const NUM_VARS: usize = 28; + const LABEL: &[u8] = b"test/fp32-nv28-shipped-d128-terminal-l2"; + + let opening_layout = OpeningClaimsLayout::new(NUM_VARS, 1).expect("terminal L2 layout"); + let schedule = SmallCfg::get_params_for_prove(&opening_layout).expect("shipped fp32 schedule"); + let terminal_params = &schedule.terminal.params.witness; + let response_l2_sq_cap = terminal_params + .response_l2_sq_cap() + .expect("nv28 must ship a direct terminal L2 cap"); + assert_eq!(terminal_params.d_a(), 128); + assert_eq!( + schedule.terminal.params.sparse_challenge_config, + akita_challenges::D128_SELECTIVE_L2_CHALLENGE_CONFIG, + ); + assert_eq!( + akita_challenges::selective_l2_operator_norm_rejection( + terminal_params.d_a(), + &schedule.terminal.params.sparse_challenge_config, + ), + Some(akita_challenges::OperatorNormRejection::D128_SELECTIVE_L2), + ); + + let root_params = &schedule.root.params.final_group.commitment; + let poly = grouped_onehot_poly(root_params, 9); + let point = extension_point(NUM_VARS); + let opening = onehot_opening_at_point(&poly, &point); + let setup = SmallScheme::setup_prover(NUM_VARS, 1).expect("terminal L2 prover setup"); + let prepared = CpuBackend::DEFAULT + .prepare_setup(&setup) + .expect("prepared terminal L2 setup"); + let stack = akita_prover::UniformProverStack::uniform( + &CpuBackend::DEFAULT, + &prepared, + setup.expanded.as_ref(), + ) + .expect("terminal L2 prover stack"); + let verifier_setup = SmallScheme::setup_verifier(&setup).expect("terminal L2 verifier setup"); + let (commitment, hint) = SmallScheme::commit(&setup, std::slice::from_ref(&poly), &stack) + .expect("terminal L2 commitment"); + let poly_refs = [&poly]; + let prover_claims = OpeningClaims::from_groups(vec![PolynomialGroupClaims::new( + point.clone(), + vec![SmallE::zero()], + commitment.clone(), + ) + .expect("terminal L2 prover group")]) + .expect("terminal L2 prover claims"); + let mut prover_transcript = AkitaTranscript::::new(LABEL); + let proof = SmallScheme::batched_prove::<_, _, _>( + &setup, + selected_prover_data::(prover_claims, vec![hint], vec![&poly_refs]) + .expect("terminal L2 prover data"), + &stack, + &mut prover_transcript, + BasisMode::Lagrange, + ) + .expect("shipped D128 terminal L2 proof"); + + let verify = |candidate: &AkitaBatchedProof| { + let claims = OpeningClaims::from_groups(vec![PolynomialGroupClaims::new( + point.clone(), + vec![opening], + &commitment, + ) + .expect("terminal L2 verifier group")]) + .expect("terminal L2 verifier claims"); + let mut transcript = AkitaTranscript::::new(LABEL); + SmallScheme::batched_verify( + candidate, + &verifier_setup, + &mut transcript, + selected_statement::(claims).expect("terminal L2 verifier statement"), + BasisMode::Lagrange, + ) + }; + verify(&proof).expect("verify shipped D128 terminal L2 proof"); + + let mut bad_nonce = proof.clone(); + bad_nonce.terminal.fold_grind_nonce = bad_nonce + .terminal + .fold_grind_nonce + .checked_add(1) + .expect("terminal nonce increment"); + assert!(verify(&bad_nonce).is_err()); + + let mut over_cap = proof; + let group = *over_cap + .terminal + .terminal_response + .layout + .groups + .first() + .expect("single terminal group"); + let payload = over_cap + .terminal + .terminal_response + .z_payloads + .first_mut() + .expect("terminal z payload"); + let mut values = akita_types::decode_terminal_z_golomb_payload(payload, &group) + .expect("honest terminal z decode") + .into_iter() + .map(i64::from) + .collect::>(); + let coordinate = i64::try_from(group.z_admission_linf_cap).expect("i64 terminal cap"); + let coordinate_sq = u128::try_from(coordinate * coordinate).expect("positive square"); + let mut forced_l2_sq = 0u128; + for value in &mut values { + *value = coordinate; + forced_l2_sq += coordinate_sq; + if forced_l2_sq > response_l2_sq_cap { + break; + } + } + assert!(forced_l2_sq > response_l2_sq_cap); + *payload = encode_test_golomb_rice(&values, group.z_rice_low_bits); + assert!(payload.len() <= group.z_payload_bytes); + assert!(verify(&over_cap).is_err()); +} + #[test] fn fp32_ext4_multi_group_uses_one_batched_eor_sumcheck() { const PRE_NV: usize = 14; diff --git a/crates/akita-pcs/src/scheme/tests/mod.rs b/crates/akita-pcs/src/scheme/tests/mod.rs index 9e4531566..6d1acfb10 100644 --- a/crates/akita-pcs/src/scheme/tests/mod.rs +++ b/crates/akita-pcs/src/scheme/tests/mod.rs @@ -161,12 +161,18 @@ fn expected_same_point_batched_shape( .expect("commitment payload geometry") .transmitted_coefficients() }; + let root_stage1 = DigitRangePlan::new(1usize << root_params.log_basis_open) + .expect("scheduled root range basis") + .proof_shapes_for_route( + root_rounds, + root_params.inner_commit_matrix.security_route(), + ) + .expect("scheduled root Stage 1 shape"); let root_shape = LevelProofShape { extension_opening_reduction: None, opening_payload_coeffs: opening_payload_coeffs(root_params), - stage1_stages: DigitRangePlan::new(1usize << root_params.log_basis_open) - .expect("scheduled root range basis") - .stage_shapes(root_rounds), + stage1_stages: root_stage1.0, + stage1_norm: root_stage1.1, stage2_sumcheck_proof: vec![3; root_rounds], stage3_sumcheck: None, next_witness_binding: match root_successor { @@ -189,12 +195,15 @@ fn expected_same_point_batched_shape( let level_params = &step.params.witness; let output_witness_len = step.output_witness_len; let rounds = batched_shape_rounds(level_params.d_a(), output_witness_len); + let stage1 = DigitRangePlan::new(1usize << level_params.log_basis_open) + .expect("scheduled range basis") + .proof_shapes_for_route(rounds, level_params.inner_commit_matrix.security_route()) + .expect("scheduled Stage 1 shape"); recursive_folds.push(LevelProofShape { extension_opening_reduction: None, opening_payload_coeffs: opening_payload_coeffs(level_params), - stage1_stages: DigitRangePlan::new(1usize << level_params.log_basis_open) - .expect("scheduled range basis") - .stage_shapes(rounds), + stage1_stages: stage1.0, + stage1_norm: stage1.1, stage2_sumcheck_proof: vec![3; rounds], stage3_sumcheck: None, next_witness_binding: match schedule.recursive_folds.get(index + 1) { diff --git a/crates/akita-pcs/src/scheme/tests/onehot.rs b/crates/akita-pcs/src/scheme/tests/onehot.rs index bbb20a162..292d2d108 100644 --- a/crates/akita-pcs/src/scheme/tests/onehot.rs +++ b/crates/akita-pcs/src/scheme/tests/onehot.rs @@ -826,3 +826,132 @@ fn batched_onehot_roundtrip_matches_public_shape_context() { ) .expect("batched onehot verify"); } + +#[test] +fn selective_l2_proof_rejects_transcript_mutations() { + const NV: usize = 30; + const BATCH_SIZE: usize = 4; + const TRANSCRIPT_LABEL: &[u8] = b"test/selective-l2-mutations"; + type L2Cfg = OneHotCfg; + type L2Scheme = AkitaCommitmentScheme; + + let layout = akita_batched_root_layout::(NV, BATCH_SIZE).expect("L2 root layout"); + let polys: Vec> = (0..BATCH_SIZE) + .map(|index| debug_make_onehot_poly(NV, layout.d_a(), 0x0bee_fcaf_1200_0000 + index as u64)) + .collect(); + let poly_refs: Vec<&OneHotPoly> = polys.iter().collect(); + let point = debug_random_point(NV); + let openings: Vec = polys + .iter() + .map(|poly| { + opening_from_poly( + poly, + &point, + layout.d_a(), + layout.num_positions_per_block, + layout.num_live_blocks, + ) + }) + .collect(); + + let setup = L2Scheme::setup_prover(NV, BATCH_SIZE).expect("L2 setup"); + let prepared = CpuBackend::DEFAULT + .prepare_setup(&setup) + .expect("prepared L2 setup"); + let stack = akita_prover::UniformProverStack::uniform( + &CpuBackend::DEFAULT, + &prepared, + setup.expanded.as_ref(), + ) + .expect("L2 stack"); + let verifier_setup = L2Scheme::setup_verifier(&setup).expect("L2 verifier setup"); + let (commitment, hint) = + L2Scheme::commit::<_, _>(&setup, &polys, &stack).expect("L2 commitment"); + let commitments = [commitment]; + let prover_group = PolynomialGroupClaims::new( + point.clone(), + vec![OneHotF::zero(); BATCH_SIZE], + commitments[0].clone(), + ) + .expect("L2 prover group"); + let mut prover_transcript = AkitaTranscript::::new(TRANSCRIPT_LABEL); + let proof = L2Scheme::batched_prove::<_, _, _>( + &setup, + selected_prover_data::( + OpeningClaims::from_groups(vec![prover_group]).expect("L2 prover claims"), + vec![hint], + vec![&poly_refs], + ) + .expect("L2 opening data"), + &stack, + &mut prover_transcript, + BasisMode::Lagrange, + ) + .expect("L2 proof"); + + let verify = |candidate: &AkitaBatchedProof| { + let claims = OpeningClaims::from_groups(vec![PolynomialGroupClaims::new( + point.clone(), + openings.clone(), + &commitments[0], + ) + .expect("L2 verifier group")]) + .expect("L2 verifier claims"); + let mut transcript = AkitaTranscript::::new(TRANSCRIPT_LABEL); + L2Scheme::batched_verify( + candidate, + &verifier_setup, + &mut transcript, + selected_statement::(claims).expect("L2 verifier statement"), + BasisMode::Lagrange, + ) + }; + verify(&proof).expect("valid L2 proof"); + + let l2_index = proof + .recursive_folds + .iter() + .position(|fold| fold.stage1.norm_proof.is_some()) + .expect("generated schedule must select one L2 fold"); + let mut bad_norm = proof.clone(); + bad_norm.recursive_folds[l2_index] + .stage1 + .norm_proof + .as_mut() + .expect("L2 norm") + .response_l2_sq += 1; + assert!(verify(&bad_norm).is_err()); + + let mut over_cap = proof.clone(); + over_cap.recursive_folds[l2_index] + .stage1 + .norm_proof + .as_mut() + .expect("L2 norm") + .response_l2_sq = u128::MAX; + assert!(verify(&over_cap).is_err()); + + let mut bad_virtual = proof.clone(); + bad_virtual.recursive_folds[l2_index] + .stage1 + .norm_proof + .as_mut() + .expect("L2 norm") + .virtual_evaluations[0] += OneHotF::one(); + assert!(verify(&bad_virtual).is_err()); + + let mut bad_sumcheck = proof.clone(); + bad_sumcheck.recursive_folds[l2_index] + .stage1 + .norm_proof + .as_mut() + .expect("L2 norm") + .sumcheck + .round_polys[0] + .coeffs_except_linear_term[0] += OneHotF::one(); + assert!(verify(&bad_sumcheck).is_err()); + + let mut bad_nonce = proof; + bad_nonce.recursive_folds[l2_index].fold_grind_nonce += 1; + assert!(verify(&bad_nonce).is_err()); +} diff --git a/crates/akita-pcs/tests/stage1_roundtrip.rs b/crates/akita-pcs/tests/stage1_roundtrip.rs index 5cb8cba3d..e7964ecb2 100644 --- a/crates/akita-pcs/tests/stage1_roundtrip.rs +++ b/crates/akita-pcs/tests/stage1_roundtrip.rs @@ -48,7 +48,7 @@ fn prove_stage1_case( .expect("stage1 prover should build"); let mut prover_transcript = AkitaTranscript::::new(labels::DOMAIN_AKITA_PROTOCOL); let (proof, stage1_point) = prover - .prove(&mut prover_transcript) + .prove(&mut prover_transcript, None) .expect("stage1 proof should succeed"); (proof, stage1_point, equality_point) } @@ -106,7 +106,7 @@ fn streaming_high_basis_handles_odd_live_prefix_without_materializing_padding() ) .unwrap(); let mut prover_transcript = AkitaTranscript::::new(labels::DOMAIN_AKITA_PROTOCOL); - let (proof, expected_point) = prover.prove(&mut prover_transcript).unwrap(); + let (proof, expected_point) = prover.prove(&mut prover_transcript, None).unwrap(); let verifier = AkitaStage1Verifier::new(equality_point, plan); let mut verifier_transcript = AkitaTranscript::::new(labels::DOMAIN_AKITA_PROTOCOL); @@ -150,7 +150,7 @@ where ) .unwrap(); let mut prover_transcript = AkitaTranscript::::new(labels::DOMAIN_AKITA_PROTOCOL); - let (proof, expected_point) = prover.prove(&mut prover_transcript).unwrap(); + let (proof, expected_point) = prover.prove(&mut prover_transcript, None).unwrap(); let verifier = AkitaStage1Verifier::new(equality_point, plan); let mut verifier_transcript = AkitaTranscript::::new(labels::DOMAIN_AKITA_PROTOCOL); @@ -197,7 +197,7 @@ fn high_basis_final_range_image_matches_dense_padding_oracle_at_every_prefix() { ) .unwrap(); let mut prover_transcript = AkitaTranscript::::new(labels::DOMAIN_AKITA_PROTOCOL); - let (proof, stage1_point) = prover.prove(&mut prover_transcript).unwrap(); + let (proof, stage1_point) = prover.prove(&mut prover_transcript, None).unwrap(); let verifier = AkitaStage1Verifier::new(equality_point, plan); let mut verifier_transcript = AkitaTranscript::::new(labels::DOMAIN_AKITA_PROTOCOL); diff --git a/crates/akita-pcs/tests/support/mod.rs b/crates/akita-pcs/tests/support/mod.rs index 9fb4c4732..13aec5047 100644 --- a/crates/akita-pcs/tests/support/mod.rs +++ b/crates/akita-pcs/tests/support/mod.rs @@ -144,11 +144,6 @@ where Envelope::sis_modulus_profile() } - fn ring_subfield_embedding_norm_bound() -> u32 { - Envelope::ring_subfield_embedding_norm_bound() - .max(Final::ring_subfield_embedding_norm_bound()) - } - fn setup_matrix_capacity( max_num_vars: usize, max_num_batched_polys: usize, diff --git a/crates/akita-planner/Cargo.toml b/crates/akita-planner/Cargo.toml index bc4602656..824e0f6f9 100644 --- a/crates/akita-planner/Cargo.toml +++ b/crates/akita-planner/Cargo.toml @@ -21,6 +21,7 @@ akita-config = { version = "0.1.0", path = "../akita-config", optional = true, d akita-field = { version = "0.1.0", path = "../akita-field" } akita-schedules = { version = "0.1.0", path = "../akita-schedules", default-features = false } akita-types = { version = "0.1.0", path = "../akita-types" } +libm = "0.2" [features] default = [] diff --git a/crates/akita-planner/src/emit/mod.rs b/crates/akita-planner/src/emit/mod.rs index 1ca03df68..08de2e04b 100644 --- a/crates/akita-planner/src/emit/mod.rs +++ b/crates/akita-planner/src/emit/mod.rs @@ -229,6 +229,12 @@ fn generated_entry( payload_mode: step.params.witness.payload_mode, witness: committed_group(&step.params.witness), num_digits_fold: step.params.witness.num_digits_fold as u32, + response_l2_sq_cap: match step.params.witness.inner_commit_matrix.security_route() { + akita_types::InnerCommitSecurityRoute::Linf(_) => None, + akita_types::InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, .. + } => Some(response_l2_sq_cap), + }, open_commit_matrix: open_matrix_params( &step.params.open_commit_matrix, step.params.witness.log_basis_open, @@ -290,6 +296,8 @@ fn generated_entry( log_basis: schedule.terminal.params.witness.log_basis_inner, }, num_digits_inner: schedule.terminal.params.witness.num_digits_inner as u32, + fold_log_basis: schedule.terminal.params.witness.fold_log_basis, + fold_digit_count: schedule.terminal.params.witness.fold_digit_count as u32, inner_output_rank: schedule .terminal .params @@ -301,7 +309,9 @@ fn generated_entry( .params .witness .inner_commit_matrix - .coeff_linf_bound(), + .coeff_linf_bound() + .unwrap_or(0), + response_l2_sq_cap: schedule.terminal.params.witness.response_l2_sq_cap(), z_admission_linf_cap: terminal_group.z_admission_linf_cap, z_rice_low_bits: terminal_group.z_rice_low_bits, z_payload_bytes: terminal_group.z_payload_bytes as u64, @@ -330,7 +340,10 @@ fn emit_precommitted_group_key(layout: &CommittedGroupProfile) -> String { "InnerCommitMatrixParams", layout.inner_commit_matrix.output_rank(), layout.inner_commit_matrix.input_width(), - layout.inner_commit_matrix.sis_table_key(), + layout + .inner_commit_matrix + .sis_table_key() + .expect("validated precommitted matrix is L infinity"), ), layout.log_basis_outer, layout.num_digits_outer, @@ -358,7 +371,10 @@ fn emit_generated_precommitted_profile(profile: &CommittedGroupProfile) -> Strin emit_generated_committed_profile_group(profile), profile.num_digits_inner, profile.inner_commit_matrix.output_rank(), - profile.inner_commit_matrix.coeff_linf_bound(), + profile + .inner_commit_matrix + .coeff_linf_bound() + .expect("validated precommitted matrix is L infinity"), profile.num_digits_outer, profile.outer_commit_matrix.output_rank(), profile.outer_commit_matrix.coeff_linf_bound(), @@ -508,10 +524,14 @@ fn emit_schedule_entry( for fold in entry.recursive_folds { writeln!( out, - " GeneratedRecursiveFold {{ payload_mode: {}, witness: {}, num_digits_fold: {}, open_commit_matrix: {}, incoming_setup_prefix: {}, witness_partition: {} }},", + " GeneratedRecursiveFold {{ payload_mode: {}, witness: {}, num_digits_fold: {}, response_l2_sq_cap: {}, open_commit_matrix: {}, incoming_setup_prefix: {}, witness_partition: {} }},", emit_payload_mode(fold.payload_mode), emit_committed_group(fold.witness), fold.num_digits_fold, + fold.response_l2_sq_cap.map_or_else( + || "None".to_string(), + |cap| format!("Some({cap})"), + ), emit_open_matrix(fold.open_commit_matrix), emit_setup_prefix(fold.incoming_setup_prefix), emit_partition(fold.witness_partition), @@ -522,13 +542,19 @@ fn emit_schedule_entry( } writeln!( out, - " terminal: GeneratedTerminalFold {{ geometry: {}, inner_commit_matrix: GeneratedInnerCommitMatrix {{ ring_dimension: {}, log_basis: {} }}, num_digits_inner: {}, inner_output_rank: {}, inner_coeff_linf_bound: {}, z_admission_linf_cap: {}, z_rice_low_bits: {}, z_payload_bytes: {} }},", + " terminal: GeneratedTerminalFold {{ geometry: {}, inner_commit_matrix: GeneratedInnerCommitMatrix {{ ring_dimension: {}, log_basis: {} }}, num_digits_inner: {}, fold_log_basis: {}, fold_digit_count: {}, inner_output_rank: {}, inner_coeff_linf_bound: {}, response_l2_sq_cap: {}, z_admission_linf_cap: {}, z_rice_low_bits: {}, z_payload_bytes: {} }},", emit_geometry(entry.terminal.geometry), entry.terminal.inner_commit_matrix.ring_dimension, entry.terminal.inner_commit_matrix.log_basis, entry.terminal.num_digits_inner, + entry.terminal.fold_log_basis, + entry.terminal.fold_digit_count, entry.terminal.inner_output_rank, entry.terminal.inner_coeff_linf_bound, + entry.terminal.response_l2_sq_cap.map_or_else( + || "None".to_string(), + |cap| format!("Some({cap})"), + ), entry.terminal.z_admission_linf_cap, entry.terminal.z_rice_low_bits, entry.terminal.z_payload_bytes, @@ -625,6 +651,7 @@ fn emit_identity_const(identity: &GeneratedScheduleCatalogIdentity) -> String { " family_name: \"{family_name}\",\n", " protocol_epoch: {protocol_epoch},\n", " cost_model: PlannerCostModelId::{cost_model},\n", + " selective_l2_response_model: SelectiveL2ResponseModelId::{selective_l2_response_model},\n", " selection_policy: SelectionPolicyId::{selection_policy},\n", " recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::{recursive_split_search_policy},\n", " setup_field_budget: {setup_field_budget},\n", @@ -632,10 +659,10 @@ fn emit_identity_const(identity: &GeneratedScheduleCatalogIdentity) -> String { " sis_modulus_profile: {sis_modulus_profile},\n", " sis_security_policy: SisSecurityPolicyId::{sis_security_policy},\n", " sis_table_digest: SisTableDigest({sis_table_digest}),\n", + " sis_l2_table_digest: SisL2TableDigest({sis_l2_table_digest}),\n", " uniform_ring_dimension: {uniform_ring_dimension},\n", " setup_prefix_inner_ring_dimension: {setup_prefix_inner_ring_dimension},\n", " decomposition: {decomposition},\n", - " ring_subfield_norm_bound: {ring_subfield_norm_bound},\n", " claim_ext_degree: {claim_ext_degree},\n", " chal_ext_degree: {chal_ext_degree},\n", " inner_basis_range: ({inner_basis_min}, {inner_basis_max}),\n", @@ -655,6 +682,7 @@ fn emit_identity_const(identity: &GeneratedScheduleCatalogIdentity) -> String { family_name = identity.family_name, protocol_epoch = identity.protocol_epoch, cost_model = identity.cost_model.name(), + selective_l2_response_model = identity.selective_l2_response_model.name(), selection_policy = identity.selection_policy.name(), recursive_split_search_policy = identity.recursive_split_search_policy.name(), setup_field_budget = match identity.setup_field_budget { @@ -665,10 +693,10 @@ fn emit_identity_const(identity: &GeneratedScheduleCatalogIdentity) -> String { sis_modulus_profile = emit_sis_modulus_profile(identity.sis_modulus_profile), sis_security_policy = identity.sis_security_policy.name(), sis_table_digest = format_bytes(identity.sis_table_digest.0), + sis_l2_table_digest = format_bytes(identity.sis_l2_table_digest.0), uniform_ring_dimension = identity.uniform_ring_dimension, setup_prefix_inner_ring_dimension = identity.setup_prefix_inner_ring_dimension, decomposition = emit_decomposition(identity.decomposition), - ring_subfield_norm_bound = identity.ring_subfield_norm_bound, claim_ext_degree = identity.claim_ext_degree, chal_ext_degree = identity.chal_ext_degree, inner_basis_min = identity.inner_basis_range.0, @@ -763,7 +791,7 @@ pub fn emit_family_module(spec: &EmitSpec) -> Result { GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, \ CommitmentRingDims, PlannerCostModelId, PolynomialGroupLayout, CommittedGroupProfile, \ InnerCommitMatrixParams, OuterCommitMatrixParams, \ - CommitmentPayloadMode, RingDimensionScheduleMode, SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest,\n}};" + CommitmentPayloadMode, RingDimensionScheduleMode, SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest,\n}};" ) .map_err(|e| e.to_string())?; writeln!(out).map_err(|e| e.to_string())?; diff --git a/crates/akita-planner/src/lib.rs b/crates/akita-planner/src/lib.rs index 23bf0abf7..fa2716851 100644 --- a/crates/akita-planner/src/lib.rs +++ b/crates/akita-planner/src/lib.rs @@ -17,8 +17,9 @@ pub use akita_schedules::{ ChunkedWitnessCfg, DecompositionParams, PlannerCostModelId, PlannerPolicy, - RecursiveSplitSearchPolicy, RingDimensionScheduleMode, SelectionPolicyId, SisModulusProfileId, - SisSecurityPolicyId, DEFAULT_SIS_SECURITY_POLICY, + RecursiveSplitSearchPolicy, RingDimensionScheduleMode, SelectionPolicyId, + SelectiveL2ResponseModelId, SisModulusProfileId, SisSecurityPolicyId, + DEFAULT_SIS_SECURITY_POLICY, }; pub mod emit; @@ -26,6 +27,7 @@ pub mod emit; pub mod generated_families; mod planner; mod policy; +mod response_model; pub mod schedule_params; pub use akita_schedules::{ diff --git a/crates/akita-planner/src/planner.rs b/crates/akita-planner/src/planner.rs index 05cc6cc34..8bf607454 100644 --- a/crates/akita-planner/src/planner.rs +++ b/crates/akita-planner/src/planner.rs @@ -31,7 +31,7 @@ fn materialize_precommitted_group_for_open_basis( log_basis_open: u32, ) -> Result { let ring_dimension = layout.inner_commit_matrix.ring_dimension(); - let num_chunks = crate::policy::chunks_at_level(policy, 0); + let num_chunks = policy.chunks_at_level(0); let num_fold_coeffs = layout .inner_commit_matrix .input_width() @@ -58,7 +58,6 @@ fn materialize_precommitted_group_for_open_basis( sis_security_policy: policy.sis_security_policy, sis_table_digest: policy.sis_table_digest, sis_modulus_profile: policy.sis_modulus_profile, - ring_subfield_norm_bound: policy.ring_subfield_norm_bound, }, ring_challenge_cfg, log_basis_open, @@ -186,7 +185,7 @@ pub(crate) fn root_level_candidates_for_basis( reduced_vars, delta_commit, delta_open, - crate::policy::chunks_at_level(policy, 0), + policy.chunks_at_level(0), ); if min_block_index_bits == 0 { split_domain.push(0); @@ -288,7 +287,7 @@ fn root_final_group_level_params_candidate( else { return Ok(None); }; - let num_chunks = crate::policy::chunks_at_level(policy, 0); + let num_chunks = policy.chunks_at_level(0); let Some(num_fold_coeffs) = width_s .checked_mul(d_a) .and_then(|count| count.checked_mul(num_chunks)) @@ -320,7 +319,6 @@ fn root_final_group_level_params_candidate( log_basis_open, ctx.ring_challenge_cfg, num_digits_fold, - policy.ring_subfield_norm_bound, ) else { return Ok(None); }; @@ -496,6 +494,7 @@ pub fn find_schedule( level: 0, current_witness_len: root_input_witness_len, current_lb: 0, + source_moment: None, incoming_setup_prefix: None, dimension_ceiling, payload_phase: akita_types::CommitmentPayloadPhase::CompressedPrefix, diff --git a/crates/akita-planner/src/policy.rs b/crates/akita-planner/src/policy.rs index e4cd992b1..b3d4702b6 100644 --- a/crates/akita-planner/src/policy.rs +++ b/crates/akita-planner/src/policy.rs @@ -63,20 +63,11 @@ pub(crate) fn direct_only_policy(mut policy: PlannerPolicy) -> PlannerPolicy { policy } -pub(crate) fn chunks_at_level(policy: &PlannerPolicy, fold_level: usize) -> usize { - let chunk = policy.witness_chunk; - if chunk.uses_multi_chunk() && fold_level < chunk.num_activated_levels { - chunk.num_chunks - } else { - 1 - } -} - pub(crate) fn witness_chunk_at_level( policy: &PlannerPolicy, fold_level: usize, ) -> ChunkedWitnessCfg { - let num_chunks = chunks_at_level(policy, fold_level); + let num_chunks = policy.chunks_at_level(fold_level); if num_chunks > 1 { ChunkedWitnessCfg { num_chunks, diff --git a/crates/akita-planner/src/response_model.rs b/crates/akita-planner/src/response_model.rs new file mode 100644 index 000000000..ed6b01a14 --- /dev/null +++ b/crates/akita-planner/src/response_model.rs @@ -0,0 +1,610 @@ +//! Planner-only moment model for recursively folded response witnesses. +//! +//! The verifier never evaluates this module. The planner freezes its selected +//! integer response cap into the generated schedule, and the verifier enforces +//! that cap exactly. +//! +//! The model follows the witness construction rather than fitting one scale +//! factor to its final length. For a source vector `s` and a random negacyclic +//! challenge `c`, scalar challenge covariance gives +//! `E[||c * s||_2^2 | s] = E[||c||_2^2] ||s||_2^2`. The accepted challenge +//! sampler is not assumed to have perfect scalar covariance. Its measured +//! covariance defect and every approximation below are covered by a separate +//! source-model envelope. The response multiplier then has a distribution-free +//! Markov interpretation once that envelope bounds the conditional mean. + +use akita_field::AkitaError; +use akita_types::sis::{compute_num_digits_field_width, HonestFoldPolicySpec}; +use akita_types::{CommittedGroupParams, OpeningClaimsLayout, WitnessLayout}; + +/// Relative envelope for any underestimate by the typed moment model. +/// +/// Aggregate source measurements across fp32, fp64, and fp128 currently put the +/// largest observed underestimate below 0.21 percent. Individual typed terms +/// can differ by up to 2.24 percent in the unfavorable direction, but their +/// errors did not align in the measured source vectors. Three percent keeps +/// model error separate from the response allowance. It covers the rounded +/// Gaussian, pseudo-Mersenne, challenge-covariance, and finite-mixing +/// approximations. Conservative overestimates do not consume this envelope. +const SOURCE_MODEL_ENVELOPE_PPM: u128 = 1_030_000; + +/// Per-attempt response cap relative to the conditional response-energy mean. +/// +/// Markov's inequality gives `Pr[X <= 1.06 E[X]] >= 3/53` for every +/// nonnegative response energy `X`. Thus this is a distribution-free +/// completeness guarantee for grinding, not a Gaussian-tail assumption. With +/// 4096 independent transcript attempts, even this worst-case bound makes +/// exhaustion negligible. +const RESPONSE_MEAN_MULTIPLIER_PPM: u128 = 1_060_000; +const PPM: u128 = 1_000_000; + +/// Planner estimate of the squared Euclidean norm of one recursive witness. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub(crate) struct SourceMomentEstimate { + mean_l2_sq: u128, +} + +impl SourceMomentEstimate { + /// Retain seven leading bits and round the remaining energy upward. + /// + /// This gives the suffix DP a bounded, reusable state domain while adding + /// less than 1/64 relative error. The cap is conservative because the + /// rounding direction is always upward. + pub(crate) const fn new(mean_l2_sq: u128) -> Option { + if mean_l2_sq == 0 { + None + } else { + let significant_bits = 7u32; + let bit_len = u128::BITS - mean_l2_sq.leading_zeros(); + let discard = bit_len.saturating_sub(significant_bits); + let quantum = 1u128 << discard; + let rounded = match mean_l2_sq.checked_add(quantum - 1) { + Some(value) => value & !(quantum - 1), + None => u128::MAX, + }; + Some(Self { + mean_l2_sq: rounded, + }) + } + } + + pub(crate) const fn mean_l2_sq(self) -> u128 { + self.mean_l2_sq + } + + /// Freeze the planner's response-energy cap for one challenge family. + pub(crate) fn response_l2_sq_cap(self, challenge_l2_sq: u128) -> Option { + let numerator = self + .mean_l2_sq + .checked_mul(challenge_l2_sq)? + .checked_mul(SOURCE_MODEL_ENVELOPE_PPM)? + .checked_mul(RESPONSE_MEAN_MULTIPLIER_PPM)?; + let scale = PPM.checked_mul(PPM)?; + numerator + .checked_add(scale - 1) + .map(|rounded| rounded / scale) + } +} + +fn checked_ceil_f64(value: f64, context: &str) -> Result { + if !value.is_finite() || value < 0.0 || value > u128::MAX as f64 { + return Err(AkitaError::InvalidSetup(format!( + "{context} is outside the planner's numeric range" + ))); + } + Ok(value.ceil() as u128) +} + +/// Exact second moment of a uniform centered digit in +/// `[-basis/2, basis/2)` for a power-of-two basis. +fn centered_uniform_digit_second_moment(basis: u128) -> Option { + if basis < 2 || !basis.is_power_of_two() { + return None; + } + Some((basis.checked_mul(basis)?.checked_add(2)? as f64) / 12.0) +} + +/// Modeled energy of a full-width finite-field balanced decomposition. +/// +/// The model uses the uniform centered moment for each complete plane. This is +/// exact for a uniform power-of-two residue. The last plane uses the residual +/// field width rather than pretending that it is another full plane. The +/// supported pseudo-Mersenne moduli differ from `2^field_bits` by a negligible +/// fraction. Recursive E, T, and R values can also retain correlation instead +/// of being fully mixed. The explicit model envelope covers unfavorable error; +/// retained correlation usually makes this estimate conservative. +pub(crate) fn field_digit_energy( + scalar_count: usize, + field_bits: u32, + log_basis: u32, + digit_count: usize, +) -> Result { + if scalar_count == 0 || field_bits == 0 || log_basis == 0 || digit_count == 0 { + return Err(AkitaError::InvalidSetup( + "field digit moment requires positive geometry".into(), + )); + } + let mut per_scalar = 0.0; + for plane in 0..digit_count { + let consumed = (plane as u32) + .checked_mul(log_basis) + .ok_or_else(|| AkitaError::InvalidSetup("digit-plane width overflow".into()))?; + if consumed >= field_bits { + break; + } + let plane_bits = log_basis.min(field_bits - consumed); + let basis = 1u128 + .checked_shl(plane_bits) + .ok_or_else(|| AkitaError::InvalidSetup("digit-plane basis overflow".into()))?; + per_scalar += centered_uniform_digit_second_moment(basis) + .ok_or_else(|| AkitaError::InvalidSetup("digit-plane basis is not supported".into()))?; + } + checked_ceil_f64( + per_scalar * scalar_count as f64, + "finite-field digit energy", + ) +} + +fn centered_residue(value: i64, basis: i64) -> i64 { + let residue = value.rem_euclid(basis); + if residue >= basis / 2 { + residue - basis + } else { + residue + } +} + +fn normal_cdf(value: f64) -> f64 { + 0.5 * (1.0 + libm::erf(value / core::f64::consts::SQRT_2)) +} + +/// Expected squared centered residue of a rounded normal integer. +fn rounded_normal_digit_second_moment(sigma: f64, basis: i64) -> f64 { + if sigma <= f64::EPSILON { + return 0.0; + } + + // Once the standard deviation spans one residue period, the first + // nonconstant Fourier coefficient of the wrapped normal is at most + // exp(-2*pi^2), below 3e-9. Rounding contributes only still-smaller alias + // terms for the supported bases. This is negligible beside the 3% source + // envelope and bounds planner work at early, high-variance levels. + if sigma >= basis as f64 { + return centered_uniform_digit_second_moment(basis as u128).unwrap_or(0.0); + } + + let radius = (8.0 * sigma + 0.5).ceil() as i64; + let mut moment = 0.0; + let mut lower_cdf = normal_cdf((-radius as f64 - 0.5) / sigma); + for value in -radius..=radius { + let upper = (value as f64 + 0.5) / sigma; + let upper_cdf = normal_cdf(upper); + let probability = upper_cdf - lower_cdf; + let digit = centered_residue(value, basis) as f64; + moment += probability * digit * digit; + lower_cdf = upper_cdf; + } + moment +} + +/// Expected energy after balanced-decomposing an approximately Gaussian +/// folded response. +/// +/// `response_l2_sq` is the total response-energy mean before decomposition; +/// `response_coeff_count` is its physical scalar coefficient count. +pub(crate) fn gaussian_response_digit_energy( + response_l2_sq: u128, + response_coeff_count: usize, + log_basis: u32, + digit_count: usize, +) -> Result { + if response_l2_sq == 0 || response_coeff_count == 0 || log_basis == 0 || digit_count == 0 { + return Err(AkitaError::InvalidSetup( + "Gaussian digit moment requires positive geometry".into(), + )); + } + let basis = 1i64 + .checked_shl(log_basis) + .ok_or_else(|| AkitaError::InvalidSetup("Gaussian digit basis overflow".into()))?; + let sigma = ((response_l2_sq as f64) / response_coeff_count as f64).sqrt(); + let mut per_response_coefficient = 0.0; + let mut plane_sigma = sigma; + for _ in 0..digit_count { + per_response_coefficient += rounded_normal_digit_second_moment(plane_sigma, basis); + plane_sigma /= basis as f64; + } + checked_ceil_f64( + per_response_coefficient * response_coeff_count as f64, + "Gaussian response digit energy", + ) +} + +/// Expected energy of negative-binary compression digits. +pub(crate) fn compression_digit_energy(coefficient_count: usize) -> u128 { + coefficient_count.div_ceil(2) as u128 +} + +/// Apply the exact energy multiplicity of extension-field tensor packing under +/// exchangeable extension coordinates. +/// +/// Coordinate zero appears once. Each of the other `K-1` coordinates appears +/// twice with opposite signs, so the expected multiplier is `(2K-1)/K`. +pub(crate) fn tensor_packed_energy(logical_energy: u128, extension_degree: usize) -> Option { + if logical_energy == 0 || extension_degree == 0 { + return None; + } + let numerator = + logical_energy.checked_mul((extension_degree as u128).checked_mul(2)?.checked_sub(1)?)?; + numerator + .checked_add(extension_degree as u128 - 1) + .map(|rounded| rounded / extension_degree as u128) +} + +fn checked_logical_group_len(num_vars: usize, num_polynomials: usize) -> Result { + 1usize + .checked_shl(num_vars as u32) + .and_then(|len| len.checked_mul(num_polynomials)) + .ok_or_else(|| AkitaError::InvalidSetup("root source length overflow".into())) +} + +/// Source moments of each root opening group before its first fold. +pub(crate) fn root_group_source_moments( + params: &CommittedGroupParams, + opening_layout: &OpeningClaimsLayout, + final_policy: HonestFoldPolicySpec, + precommitted_policies: &[HonestFoldPolicySpec], + field_bits: u32, +) -> Result, AkitaError> { + let final_group_index = opening_layout.root_final_group_index()?; + if precommitted_policies.len() != final_group_index { + return Err(AkitaError::InvalidSetup( + "root response model requires one policy per precommitted group".into(), + )); + } + let mut moments = Vec::with_capacity(opening_layout.num_groups()); + for group_index in 0..opening_layout.num_groups() { + let group_layout = *opening_layout.group_layout(group_index)?; + let group_params = params.group_params(opening_layout, group_index)?; + let logical_len = + checked_logical_group_len(group_layout.num_vars(), group_layout.num_polynomials())?; + let policy = if group_index == final_group_index { + final_policy + } else { + *precommitted_policies.get(group_index).ok_or_else(|| { + AkitaError::InvalidSetup("precommitted response policy is missing".into()) + })? + }; + let mean_l2_sq = match policy { + HonestFoldPolicySpec::UnitOneHot(onehot) => { + let chunk = onehot.source_chunk_size(); + if chunk == 0 || !logical_len.is_multiple_of(chunk) { + return Err(AkitaError::InvalidSetup( + "unit one-hot root length must be a multiple of its source chunk size" + .into(), + )); + } + (logical_len / chunk) as u128 + } + HonestFoldPolicySpec::BalancedSignedDigit(_) => field_digit_energy( + logical_len, + field_bits, + group_params.log_basis_inner(), + group_params.num_digits_inner(), + )?, + }; + moments.push(SourceMomentEstimate::new(mean_l2_sq).ok_or_else(|| { + AkitaError::InvalidSetup("root response source has zero modeled energy".into()) + })?); + } + Ok(moments) +} + +fn checked_add_energy(total: &mut u128, value: u128) -> Result<(), AkitaError> { + *total = total + .checked_add(value) + .ok_or_else(|| AkitaError::InvalidSetup("response-model energy overflow".into()))?; + Ok(()) +} + +/// Predict the recursive witness produced by one ring-switch level from its +/// exact typed layout. +pub(crate) fn next_source_moment( + params: &CommittedGroupParams, + opening_layout: &OpeningClaimsLayout, + source_groups: &[SourceMomentEstimate], + field_bits: u32, + extension_degree: usize, +) -> Result { + if source_groups.len() != opening_layout.num_groups() { + return Err(AkitaError::InvalidSetup( + "response source moments disagree with the opening groups".into(), + )); + } + let quotient_depth = compute_num_digits_field_width(field_bits, params.log_basis_open); + let layout = WitnessLayout::new( + params, + opening_layout, + params.witness_chunk.num_chunks, + quotient_depth, + )?; + let mut logical_energy = 0u128; + + for unit in layout.units() { + let group_index = unit.group_index(); + let group_params = params.group_params(opening_layout, group_index)?; + let group_source = source_groups + .get(group_index) + .copied() + .ok_or_else(|| AkitaError::InvalidSetup("response source group is missing".into()))?; + let total_blocks = group_params.num_live_blocks(); + if total_blocks == 0 || group_params.num_digits_fold() == 0 { + return Err(AkitaError::InvalidSetup( + "response-model group geometry is empty".into(), + )); + } + let chunk_source = group_source + .mean_l2_sq() + .checked_mul(unit.num_live_blocks() as u128) + .and_then(|value| value.checked_add(total_blocks as u128 - 1)) + .map(|rounded| rounded / total_blocks as u128) + .ok_or_else(|| AkitaError::InvalidSetup("chunk source energy overflow".into()))?; + let response_energy = chunk_source + .checked_mul(group_params.fold_challenge_config().challenge_l2_sq_max()) + .ok_or_else(|| AkitaError::InvalidSetup("fold response energy overflow".into()))?; + let response_coeff_count = unit.z_range().len() / group_params.num_digits_fold(); + if response_energy != 0 && response_coeff_count != 0 { + checked_add_energy( + &mut logical_energy, + gaussian_response_digit_energy( + response_energy, + response_coeff_count, + group_params.log_basis_open(), + group_params.num_digits_fold(), + )?, + )?; + } + + let num_claims = opening_layout.group_layout(group_index)?.num_polynomials(); + let group_d_a = params.group_role_dims(opening_layout, group_index)?.d_a(); + let e_scalar_count = num_claims + .checked_mul(unit.num_live_blocks()) + .and_then(|count| count.checked_mul(group_d_a)) + .ok_or_else(|| AkitaError::InvalidSetup("live E source length overflow".into()))?; + let allocated_e_scalar_count = unit.e_range().len() / group_params.num_digits_open(); + if e_scalar_count > allocated_e_scalar_count { + return Err(AkitaError::InvalidSetup( + "live E source exceeds its witness span".into(), + )); + } + if e_scalar_count != 0 { + checked_add_energy( + &mut logical_energy, + field_digit_energy( + e_scalar_count, + field_bits, + group_params.log_basis_open(), + group_params.num_digits_open(), + )?, + )?; + } + let t_scalar_count = e_scalar_count + .checked_mul(group_params.a_rows_len()) + .ok_or_else(|| AkitaError::InvalidSetup("live T source length overflow".into()))?; + let allocated_t_scalar_count = unit.t_range().len() / group_params.num_digits_outer(); + if t_scalar_count > allocated_t_scalar_count { + return Err(AkitaError::InvalidSetup( + "live T source exceeds its witness span".into(), + )); + } + if t_scalar_count != 0 { + checked_add_energy( + &mut logical_energy, + field_digit_energy( + t_scalar_count, + field_bits, + group_params.log_basis_outer(), + group_params.num_digits_outer(), + )?, + )?; + } + } + + for row in layout.r_rows() { + let scalar_count = row.range().len() / quotient_depth; + if scalar_count != 0 { + checked_add_energy( + &mut logical_energy, + field_digit_energy( + scalar_count, + field_bits, + params.log_basis_open, + quotient_depth, + )?, + )?; + } + } + + let compression_coefficients = layout + .compression_layers() + .iter() + .try_fold(0usize, |total, layer| { + let f = layer + .f_spans() + .iter() + .try_fold(0usize, |sum, (_, span)| sum.checked_add(span.range().len()))?; + total + .checked_add(f)? + .checked_add(layer.h_span().range().len()) + }) + .ok_or_else(|| AkitaError::InvalidSetup("compression model length overflow".into()))?; + checked_add_energy( + &mut logical_energy, + compression_digit_energy(compression_coefficients), + )?; + + let packed = tensor_packed_energy(logical_energy, extension_degree) + .ok_or_else(|| AkitaError::InvalidSetup("tensor-packed response energy overflow".into()))?; + SourceMomentEstimate::new(packed) + .ok_or_else(|| AkitaError::InvalidSetup("modeled recursive witness is empty".into())) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn field_plane_moments_include_the_residual_top_plane() { + // fp64 at basis 64 has ten full planes and one four-bit top plane. + let energy = field_digit_energy(1_000_000, 64, 6, 11).unwrap(); + let expected = 1_000_000.0 * (10.0 * 341.5 + 21.5); + assert_eq!(energy, expected as u128); + } + + #[test] + fn tensor_pack_energy_matches_supported_extension_factors() { + assert_eq!(tensor_packed_energy(400, 1), Some(400)); + assert_eq!(tensor_packed_energy(400, 2), Some(600)); + assert_eq!(tensor_packed_energy(400, 4), Some(700)); + } + + #[test] + fn gaussian_z_model_matches_measured_cross_field_states() { + // (response energy, coefficient count, log basis, digit count, + // observed decomposed-Z energy). These are independent honest-prover + // measurements from fp32, fp64, and fp128 schedules. + let rows = [ + (21_319_133_492, 524_288, 3, 4, 8_570_345), + (352_065_629, 65_536, 4, 3, 2_447_776), + (3_847_283_483, 262_144, 3, 4, 3_767_203), + (473_967_459, 65_536, 4, 3, 2_593_330), + (234_370_171, 32_768, 5, 2, 3_041_573), + (9_985_694_564, 262_144, 4, 3, 11_458_186), + (483_233_512, 32_768, 6, 2, 11_379_250), + (2_853_063_371, 16_384, 6, 2, 6_333_831), + ]; + for (response, count, log_basis, digits, observed) in rows { + let predicted = + gaussian_response_digit_energy(response, count, log_basis, digits).unwrap(); + let relative_error = (predicted as f64 / observed as f64 - 1.0).abs(); + assert!( + relative_error <= 0.02, + "response={response} basis={log_basis}: predicted={predicted}, observed={observed}, error={relative_error}" + ); + } + } + + #[test] + fn cap_multiplier_has_markov_grinding_budget() { + let source = SourceMomentEstimate::new(1_048_576).unwrap(); + assert_eq!(source.response_l2_sq_cap(75), Some(85_862_646)); + // The 3% source envelope followed by the 1.06 grinding allowance. + assert_eq!( + 85_862_646u128, + (78_643_200u128 * 1_091_800u128).div_ceil(1_000_000u128) + ); + } + + #[test] + fn source_moment_bucketing_is_conservative_and_below_one_over_sixty_four() { + for value in [1, 127, 128, 129, 1_000_000, u64::MAX as u128] { + let bucketed = SourceMomentEstimate::new(value).unwrap().mean_l2_sq(); + assert!(bucketed >= value); + assert!(bucketed - value < value.div_ceil(64).max(1)); + } + } + + #[test] + fn empirical_selected_l2_caps_cover_every_profile_with_twenty_percent_slack() { + // (actual source energy, challenge energy, actual response energy, + // frozen cap, accepted nonce). These 52 observations come from fresh + // honest proofs after regenerating every production catalog with the + // typed model. The profiles cover dense and one-hot fp32, fp64, and + // fp128, plus direct, recursive, multi-group, and W2/W4/W8 multi-chunk + // adapters. Every proof passed both verifier modes. + let rows: [(u128, u128, u128, u128, u32); 52] = [ + // dense fp128, nv28 + (12_407_040, 75, 926_141_682, 1_019_618_919, 0), + (5_796_378, 75, 445_552_700, 477_610_968, 0), + (3_647_474, 75, 274_451_686, 300_519_261, 0), + (7_743_642, 75, 586_433_408, 638_603_428, 0), + // dense fp128 W8R2, nv16 + (35_107_808, 75, 2_626_361_028, 2_919_329_956, 0), + // dense fp32, nv26 + (40_629_192, 31, 1_239_850_532, 1_384_105_850, 0), + (57_099_436, 31, 1_768_110_122, 1_934_199_201, 0), + (40_125_119, 31, 1_244_482_641, 1_366_360_903, 0), + (33_318_735, 31, 1_049_730_223, 1_135_676_595, 0), + // dense fp64, nv26 + (13_064_104, 75, 972_766_912, 1_073_283_072, 0), + (6_572_335, 75, 484_480_549, 542_007_952, 0), + (38_594_808, 75, 2_880_104_854, 3_219_849_216, 0), + (32_046_576, 75, 2_358_924_124, 2_618_810_696, 0), + // one-hot fp128 multi-group direct, nv32 + (13_113_613, 75, 990_397_381, 1_084_015_903, 0), + (5_790_401, 75, 435_504_807, 477_610_968, 0), + (3_629_916, 75, 274_360_018, 300_519_261, 0), + (7_792_001, 75, 597_384_985, 638_603_428, 0), + // one-hot fp128 multi-group recursive, nv32 + (5_238_923, 75, 389_262_109, 434_679_645, 0), + (3_643_002, 75, 273_006_474, 300_519_261, 0), + (7_690_060, 75, 576_160_576, 638_603_428, 0), + // one-hot fp128 multi-group recursive W8R2, nv32 + (55_820_237, 75, 4_214_079_087, 4_980_033_455, 0), + (12_646_637, 75, 945_965_213, 1_041_084_580, 0), + (5_808_394, 75, 431_485_946, 477_610_968, 0), + (3_633_833, 75, 269_471_043, 300_519_261, 0), + (7_717_933, 75, 574_249_975, 638_603_428, 0), + // one-hot fp128 direct, nv36 + (6_623_127, 75, 491_509_521, 547_374_367, 1), + (6_806_508, 75, 503_824_058, 563_473_613, 0), + (3_960_821, 75, 302_168_513, 327_351_337, 0), + (7_780_509, 75, 582_947_255, 638_603_428, 0), + // one-hot fp128 recursive, nv36 + (5_824_305, 75, 439_023_783, 477_610_968, 0), + (3_646_029, 75, 271_086_421, 300_519_261, 0), + (7_700_743, 75, 579_984_205, 638_603_428, 0), + // one-hot fp128 W2R2, nv32 + (7_711_639, 75, 575_828_653, 633_237_013, 0), + (7_395_059, 75, 560_656_609, 611_771_352, 0), + (4_128_110, 75, 306_830_462, 340_767_376, 0), + (7_767_427, 75, 578_967_153, 638_603_428, 0), + // one-hot fp128 W4R2, nv32 + (6_962_796, 75, 523_336_068, 574_206_444, 0), + (7_496_134, 75, 575_021_712, 622_504_182, 0), + (4_151_889, 75, 308_980_429, 340_767_376, 0), + (7_770_129, 75, 582_553_175, 638_603_428, 0), + // one-hot fp128 W8R2, nv32 + (3_689_784, 75, 280_924_824, 303_202_468, 0), + (5_084_626, 75, 379_634_330, 423_946_814, 0), + (3_635_868, 75, 272_623_976, 300_519_261, 0), + (7_648_184, 75, 575_044_430, 638_603_428, 0), + // one-hot fp32, nv30 + (40_709_103, 31, 1_276_171_391, 1_384_105_850, 0), + (57_194_754, 31, 1_755_752_816, 1_934_199_201, 0), + (39_919_435, 31, 1_229_011_205, 1_366_360_903, 0), + (33_184_890, 31, 1_030_585_156, 1_135_676_595, 0), + // one-hot fp64, nv30 + (4_789_769, 75, 367_508_391, 397_114_737, 0), + (21_440_544, 75, 1_607_978_058, 1_781_649_900, 0), + (39_747_250, 75, 2_915_927_368, 3_262_780_539, 0), + (31_824_799, 75, 2_357_368_597, 2_618_810_696, 0), + ]; + + for (source, challenge, response, cap, nonce) in rows { + assert!(response <= cap, "honest response exceeded its frozen cap"); + assert!( + cap * 100 <= response * 120, + "frozen cap used more than twenty percent slack" + ); + assert!(nonce <= 1, "empirical proof required unexpected grinding"); + + // Recover the planner's frozen source estimate from its cap. The + // rounding error is far below these bounds. This pins the observed + // aggregate model error to about -0.21 to +8.96 percent. + let implied_source = cap as f64 * (PPM * PPM) as f64 + / (challenge * SOURCE_MODEL_ENVELOPE_PPM * RESPONSE_MEAN_MULTIPLIER_PPM) as f64; + let source_ratio = implied_source / source as f64; + assert!((0.997..=1.09).contains(&source_ratio)); + } + } +} diff --git a/crates/akita-planner/src/schedule_params.rs b/crates/akita-planner/src/schedule_params.rs index 56318b54a..d15ea6522 100644 --- a/crates/akita-planner/src/schedule_params.rs +++ b/crates/akita-planner/src/schedule_params.rs @@ -42,6 +42,8 @@ pub(crate) use akita_schedules::planner_support::{ CandidateTerminalResponse, }; pub use akita_types::suffix_opening_layout; +#[cfg(test)] +pub(crate) use candidate::derive_linf_candidate_level_params; pub(crate) use candidate::{ derive_candidate_level_params, derive_candidate_level_params_split_frontier, recursive_split_search_domain, SetupPrefixSearchCache, @@ -305,15 +307,32 @@ pub(crate) fn candidate_schedule_descriptor_bytes( } .canonical_descriptor_bytes()); } - Ok(materialize_candidate_schedule( + let mut folds = choice.folds.to_vec(); + let carrier_prefix_len = folds.len().min(2); + let carrier_payload_modes = folds + .iter() + .take(carrier_prefix_len) + .map(|fold| fold.params.payload_mode) + .collect::>(); + for fold in folds.iter_mut().take(carrier_prefix_len) { + Arc::make_mut(&mut fold.params).payload_mode = + akita_types::CommitmentPayloadMode::Compressed; + } + let mut bytes = materialize_candidate_schedule( choice.total_bytes, choice.setup_field_elements, choice.first_direct_setup_field_len.map(NonZeroUsize::get), - choice.folds.to_vec(), + folds, choice.terminal.as_ref().clone(), )? .schedule - .canonical_descriptor_bytes()) + .canonical_descriptor_bytes(); + let mut prefix = Vec::with_capacity(carrier_prefix_len + 1); + prefix.push(carrier_prefix_len as u8); + prefix.extend(carrier_payload_modes.into_iter().map(|mode| mode.tag())); + prefix.append(&mut bytes); + let bytes = prefix; + Ok(bytes) } /// Stage-1 sparse-challenge closure shared by the planner entry points. diff --git a/crates/akita-planner/src/schedule_params/candidate.rs b/crates/akita-planner/src/schedule_params/candidate.rs index 57ac64c51..ee0449995 100644 --- a/crates/akita-planner/src/schedule_params/candidate.rs +++ b/crates/akita-planner/src/schedule_params/candidate.rs @@ -1,11 +1,16 @@ use super::*; pub(crate) use akita_schedules::planner_support::planned_next_witness_len; -use akita_schedules::planner_support::{projected_collision_role_price, sis_key_at_dimension}; +use akita_schedules::planner_support::{ + projected_collision_role_price, selective_l2_inner_matrix, sis_key_at_dimension, + SelectiveL2CandidateGeometry, +}; mod recursive; mod setup_prefix; +#[cfg(test)] +pub(crate) use recursive::derive_linf_candidate_level_params; pub(crate) use recursive::{ derive_candidate_level_params, derive_candidate_level_params_split_frontier, recursive_split_search_domain, diff --git a/crates/akita-planner/src/schedule_params/candidate/recursive.rs b/crates/akita-planner/src/schedule_params/candidate/recursive.rs index ff6367847..eb2cfd824 100644 --- a/crates/akita-planner/src/schedule_params/candidate/recursive.rs +++ b/crates/akita-planner/src/schedule_params/candidate/recursive.rs @@ -25,7 +25,7 @@ pub(crate) fn recursive_fold_level_params_candidate( { return Ok(None); } - let num_chunks = crate::policy::chunks_at_level(policy, fold_level); + let num_chunks = policy.chunks_at_level(fold_level); let num_positions_per_block = 1usize .checked_shl((reduced_vars - block_index_bits) as u32) .ok_or_else(|| { @@ -72,7 +72,6 @@ pub(crate) fn recursive_fold_level_params_candidate( log_basis_open, ring_challenge_cfg, num_digits_fold, - policy.ring_subfield_norm_bound, ) else { return Ok(None); }; @@ -317,7 +316,7 @@ fn prepare_recursive_level_search( fold_level: usize, incoming_setup_prefix: Option, ) -> Result, AkitaError> { - let num_chunks = crate::policy::chunks_at_level(policy, fold_level); + let num_chunks = policy.chunks_at_level(fold_level); dimensions.validate_role_projection()?; let d_a = dimensions.d_a(); if current_witness_len == 0 { @@ -417,6 +416,11 @@ fn finalize_recursive_level_candidate( Ok(Some((score, candidate_params, next_witness_len))) } +/// Return the established L-infinity candidate plus any calibrated L2 +/// alternative at this state. +/// +/// The response model reuses the ordinary best split. The suffix DP then prices +/// that alternative against the L-infinity candidate. #[allow(clippy::too_many_arguments)] fn recursive_level_base_candidate_for_split( policy: &PlannerPolicy, @@ -534,34 +538,17 @@ fn walk_recursive_splits( } #[allow(clippy::too_many_arguments)] -pub(crate) fn derive_candidate_level_params( - setup_prefix_cache: Option<&mut SetupPrefixSearchCache>, +fn best_linf_candidate( policy: &PlannerPolicy, payload_mode: akita_types::CommitmentPayloadMode, ring_challenge_cfg: &akita_challenges::SparseChallengeConfig, dimensions: CommitmentRingDims, - current_witness_len: usize, + search: &RecursiveLevelSearch, source: crate::InnerBasisSource, log_basis_inner: u32, log_basis_open: u32, fold_level: usize, - incoming_setup_prefix: Option, ) -> Result, AkitaError> { - let Some(search) = prepare_recursive_level_search( - setup_prefix_cache, - policy, - ring_challenge_cfg, - dimensions, - current_witness_len, - log_basis_open, - fold_level, - incoming_setup_prefix, - )? - else { - return Ok(None); - }; - - // Larger `r` wins exact score ties inside the policy-selected domain. let mut best: Option<(LayoutCandidateScore, usize, CommittedGroupParams, usize)> = None; let best_score = std::cell::Cell::new(None::); walk_recursive_splits( @@ -569,7 +556,7 @@ pub(crate) fn derive_candidate_level_params( payload_mode, ring_challenge_cfg, dimensions, - &search, + search, source, log_basis_inner, log_basis_open, @@ -589,16 +576,266 @@ pub(crate) fn derive_candidate_level_params( } }, )?; + Ok(best.and_then(|(_, _, params, next)| { + (next < search.current_witness_len).then_some((params, next)) + })) +} - let Some((_, _, candidate_params, next_witness_len)) = best else { - return Ok(None); - }; +#[allow(clippy::too_many_arguments)] +fn append_selective_l2_candidates( + candidates: &mut Vec<(CommittedGroupParams, usize)>, + model_base: Option<&(CommittedGroupParams, usize)>, + policy: &PlannerPolicy, + payload_mode: akita_types::CommitmentPayloadMode, + ring_challenge_cfg: &akita_challenges::SparseChallengeConfig, + dimensions: CommitmentRingDims, + search: &RecursiveLevelSearch, + source: crate::InnerBasisSource, + log_basis_inner: u32, + log_basis_open: u32, + fold_level: usize, + source_moment: Option, +) -> Result<(), AkitaError> { + let selected_l2_challenge = akita_challenges::selective_l2_challenge_config(dimensions.d_a()); + let l2_challenge_cfg = selected_l2_challenge.as_ref().unwrap_or(ring_challenge_cfg); + if policy.selective_l2_response_model_enabled() { + if let (Some((base, _)), Some(source_moment)) = (model_base, source_moment) { + let physical_response_len = base + .inner_commit_matrix + .input_width() + .checked_mul(dimensions.d_a()) + .ok_or_else(|| AkitaError::InvalidSetup("L2 response length overflow".into()))?; + append_selective_l2_candidate( + candidates, + policy, + payload_mode, + ring_challenge_cfg, + dimensions, + search, + source, + log_basis_inner, + log_basis_open, + fold_level, + physical_response_len, + source_moment.response_l2_sq_cap(l2_challenge_cfg.challenge_l2_sq_max()), + )?; + } + } + Ok(()) +} - if next_witness_len >= current_witness_len { - return Ok(None); +#[allow(clippy::too_many_arguments)] +fn append_selective_l2_candidate( + candidates: &mut Vec<(CommittedGroupParams, usize)>, + policy: &PlannerPolicy, + payload_mode: akita_types::CommitmentPayloadMode, + ring_challenge_cfg: &akita_challenges::SparseChallengeConfig, + dimensions: CommitmentRingDims, + search: &RecursiveLevelSearch, + source: crate::InnerBasisSource, + log_basis_inner: u32, + log_basis_open: u32, + fold_level: usize, + physical_response_len: usize, + modeled_response_l2_sq_cap: Option, +) -> Result<(), AkitaError> { + let fold_basis = 1usize + .checked_shl(log_basis_open) + .ok_or_else(|| AkitaError::InvalidSetup("L2 fold basis overflow".into()))?; + let selected_l2_challenge = akita_challenges::selective_l2_challenge_config(dimensions.d_a()); + let l2_challenge_cfg = selected_l2_challenge.as_ref().unwrap_or(ring_challenge_cfg); + let delta_commit = source.num_digits_inner(policy.decomposition, log_basis_inner)?; + let d_a = dimensions.d_a(); + if !physical_response_len.is_multiple_of(d_a) { + return Ok(()); + } + let inner_width = physical_response_len / d_a; + if delta_commit == 0 || !inner_width.is_multiple_of(delta_commit) { + return Ok(()); + } + let positions_per_block = inner_width / delta_commit; + if !positions_per_block.is_power_of_two() { + return Ok(()); + } + let position_bits = positions_per_block.trailing_zeros() as usize; + let Some(block_index_bits) = search.reduced_vars.checked_sub(position_bits) else { + return Ok(()); + }; + let Some(mut base) = recursive_level_base_candidate_for_split( + policy, + payload_mode, + l2_challenge_cfg, + dimensions, + search, + source, + log_basis_inner, + log_basis_open, + fold_level, + block_index_bits, + )? + else { + return Ok(()); + }; + let linf_rank = base.inner_commit_matrix.output_rank(); + let Some(inner_commit_matrix) = selective_l2_inner_matrix( + policy, + SelectiveL2CandidateGeometry { + fold_level, + num_claims: 1, + num_chunks: search.num_chunks, + inner_width: base.inner_commit_matrix.input_width(), + ring_dimension: d_a, + fold_basis, + fold_digit_count: base.num_digits_fold, + fold_challenge_config: l2_challenge_cfg, + response_l2_sq_cap: modeled_response_l2_sq_cap, + norm_proof_shape: None, + }, + )? + else { + return Ok(()); + }; + if inner_commit_matrix.output_rank() >= linf_rank { + return Ok(()); + } + let Some(native_width_t) = decomposed_t_ring_count( + inner_commit_matrix.output_rank(), + base.num_digits_outer, + base.num_live_blocks, + 1, + ) else { + return Ok(()); + }; + let Some((outer_key, width_t)) = projected_collision_role_price( + policy, + akita_types::SisMatrixRole::Outer, + d_a, + dimensions.d_b(), + native_width_t, + log_basis_open, + ) else { + return Ok(()); + }; + let Ok(outer_commit_matrix) = + OuterCommitMatrixParams::try_new_with_min_rank(outer_key, width_t) + else { + return Ok(()); + }; + base.inner_commit_matrix = inner_commit_matrix; + base.outer_commit_matrix = outer_commit_matrix; + for setup_prefix in &search.setup_prefixes { + let Some((_, params, next_witness_len)) = finalize_recursive_level_candidate( + policy, + search, + setup_prefix.as_ref(), + base.clone(), + )? + else { + continue; + }; + if next_witness_len < search.current_witness_len { + candidates.push((params, next_witness_len)); + } } + Ok(()) +} - Ok(Some((candidate_params, next_witness_len))) +#[allow(clippy::too_many_arguments)] +pub(crate) fn derive_candidate_level_params( + setup_prefix_cache: Option<&mut SetupPrefixSearchCache>, + policy: &PlannerPolicy, + payload_mode: akita_types::CommitmentPayloadMode, + ring_challenge_cfg: &akita_challenges::SparseChallengeConfig, + dimensions: CommitmentRingDims, + current_witness_len: usize, + source: crate::InnerBasisSource, + log_basis_inner: u32, + log_basis_open: u32, + fold_level: usize, + incoming_setup_prefix: Option, + source_moment: Option, +) -> Result, AkitaError> { + let Some(search) = prepare_recursive_level_search( + setup_prefix_cache, + policy, + ring_challenge_cfg, + dimensions, + current_witness_len, + log_basis_open, + fold_level, + incoming_setup_prefix, + )? + else { + return Ok(Vec::new()); + }; + let best_linf = best_linf_candidate( + policy, + payload_mode, + ring_challenge_cfg, + dimensions, + &search, + source, + log_basis_inner, + log_basis_open, + fold_level, + )?; + let mut candidates = best_linf.clone().into_iter().collect(); + append_selective_l2_candidates( + &mut candidates, + best_linf.as_ref(), + policy, + payload_mode, + ring_challenge_cfg, + dimensions, + &search, + source, + log_basis_inner, + log_basis_open, + fold_level, + source_moment, + )?; + Ok(candidates) +} + +#[cfg(test)] +#[allow(clippy::too_many_arguments)] +pub(crate) fn derive_linf_candidate_level_params( + setup_prefix_cache: Option<&mut SetupPrefixSearchCache>, + policy: &PlannerPolicy, + payload_mode: akita_types::CommitmentPayloadMode, + ring_challenge_cfg: &akita_challenges::SparseChallengeConfig, + dimensions: CommitmentRingDims, + current_witness_len: usize, + source: crate::InnerBasisSource, + log_basis_inner: u32, + log_basis_open: u32, + fold_level: usize, + incoming_setup_prefix: Option, +) -> Result, AkitaError> { + let Some(search) = prepare_recursive_level_search( + setup_prefix_cache, + policy, + ring_challenge_cfg, + dimensions, + current_witness_len, + log_basis_open, + fold_level, + incoming_setup_prefix, + )? + else { + return Ok(None); + }; + best_linf_candidate( + policy, + payload_mode, + ring_challenge_cfg, + dimensions, + &search, + source, + log_basis_inner, + log_basis_open, + fold_level, + ) } /// Derive the candidate frontier over recursive splits. @@ -620,6 +857,7 @@ pub(crate) fn derive_candidate_level_params_split_frontier( log_basis_open: u32, fold_level: usize, incoming_setup_prefix: Option, + source_moment: Option, ) -> Result, AkitaError> { let Some(search) = prepare_recursive_level_search( setup_prefix_cache, @@ -634,6 +872,17 @@ pub(crate) fn derive_candidate_level_params_split_frontier( else { return Ok(Vec::new()); }; + let best_linf = best_linf_candidate( + policy, + payload_mode, + ring_challenge_cfg, + dimensions, + &search, + source, + log_basis_inner, + log_basis_open, + fold_level, + )?; let mut candidates = Vec::new(); walk_recursive_splits( policy, @@ -656,5 +905,19 @@ pub(crate) fn derive_candidate_level_params_split_frontier( } }, )?; + append_selective_l2_candidates( + &mut candidates, + best_linf.as_ref(), + policy, + payload_mode, + ring_challenge_cfg, + dimensions, + &search, + source, + log_basis_inner, + log_basis_open, + fold_level, + source_moment, + )?; Ok(candidates) } diff --git a/crates/akita-planner/src/schedule_params/candidate/setup_prefix.rs b/crates/akita-planner/src/schedule_params/candidate/setup_prefix.rs index d39c26c83..c26ee6cc4 100644 --- a/crates/akita-planner/src/schedule_params/candidate/setup_prefix.rs +++ b/crates/akita-planner/src/schedule_params/candidate/setup_prefix.rs @@ -147,7 +147,6 @@ pub(in crate::schedule_params) fn derive_setup_prefix_groups( log_basis_open, ring_challenge_cfg, num_digits_fold, - policy.ring_subfield_norm_bound, ) else { continue; }; diff --git a/crates/akita-planner/src/schedule_params/suffix_dp.rs b/crates/akita-planner/src/schedule_params/suffix_dp.rs index 3ede1b54f..144f5115c 100644 --- a/crates/akita-planner/src/schedule_params/suffix_dp.rs +++ b/crates/akita-planner/src/schedule_params/suffix_dp.rs @@ -6,7 +6,7 @@ use std::{ use akita_field::AkitaError; use akita_types::{ - active_setup_field_len, level_proof_bytes, terminal_response_bytes, + active_setup_field_len, level_proof_bytes, terminal_response_planner_bytes, try_extension_opening_reduction_level_bytes, AkitaScheduleLookupKey, CommitmentRingDims, CommittedGroupParams, OpeningClaimsLayout, PolynomialGroupLayout, TerminalResponseShape, }; @@ -242,12 +242,14 @@ fn price_level_candidate_with_children( { let field_bits = policy.decomposition.field_bits(); if let Some((mut direct_step, suffix_cost)) = try_terminal_direct_suffix_cost( + policy, state.current_witness_len, candidate_params, field_bits, ctx.key, state.level, None, + state.source_moment, )? { let level_proof_size = akita_types::proof_size::FOLD_GRIND_NONCE_BYTES .checked_add(eor_bytes) @@ -356,6 +358,7 @@ pub(crate) fn derive_selected_suffix_schedule( level, current_witness_len, current_lb, + source_moment, incoming_setup_prefix, dimension_ceiling, payload_phase, @@ -375,6 +378,14 @@ pub(crate) fn derive_selected_suffix_schedule( // recomputations. return Ok(empty_suffix_result()); } + if policy.selective_l2_response_model_enabled() + && !(level_zero_is_root && level == 0) + && source_moment.is_none() + { + return Err(AkitaError::InvalidSetup( + "recursive suffix is missing its response source moment".into(), + )); + } let retains_setup_projection = incoming_setup_prefix.is_some() || (level_zero_is_root && level == 0); let mut payload_only = BTreeMap::new(); @@ -549,6 +560,7 @@ pub(crate) fn derive_selected_suffix_schedule( open_lb, level, incoming_setup_prefix, + source_moment, )? } else { derive_candidate_level_params( @@ -563,9 +575,8 @@ pub(crate) fn derive_selected_suffix_schedule( open_lb, level, incoming_setup_prefix, + source_moment, )? - .into_iter() - .collect() }; candidates.extend(level_candidates.into_iter().map( |(params, next_witness_len)| (params, next_witness_len, eor_bytes), @@ -580,6 +591,53 @@ pub(crate) fn derive_selected_suffix_schedule( } for (candidate_params, next_witness_len, eor_bytes) in candidates { + let next_source_moment = if policy.selective_l2_response_model_enabled() { + let source_groups = if root_level_key.is_some() { + crate::response_model::root_group_source_moments( + &candidate_params, + current_opening_layout, + root_honest_fold_policy.ok_or_else(|| { + AkitaError::InvalidSetup( + "root batch is missing its response source policy".into(), + ) + })?, + precommitted_honest_fold_policies, + policy.decomposition.field_bits(), + )? + } else if let Some(natural_prefix_len) = incoming_setup_prefix { + let prefix_params = candidate_params.group_params(current_opening_layout, 0)?; + let prefix_energy = crate::response_model::field_digit_energy( + natural_prefix_len, + policy.decomposition.field_bits(), + prefix_params.log_basis_inner(), + prefix_params.num_digits_inner(), + )?; + vec![ + crate::response_model::SourceMomentEstimate::new(prefix_energy) + .ok_or_else(|| { + AkitaError::InvalidSetup( + "setup-prefix source has zero energy".into(), + ) + })?, + source_moment.ok_or_else(|| { + AkitaError::InvalidSetup("recursive response source is missing".into()) + })?, + ] + } else { + vec![source_moment.ok_or_else(|| { + AkitaError::InvalidSetup("recursive response source is missing".into()) + })?] + }; + Some(crate::response_model::next_source_moment( + &candidate_params, + current_opening_layout, + &source_groups, + policy.decomposition.field_bits(), + policy.claim_ext_degree, + )?) + } else { + None + }; if let Some(natural_prefix_len) = incoming_setup_prefix { let padded_prefix_len = akita_types::padded_setup_prefix_len(natural_prefix_len); if !offloaded_witness_contracts( @@ -611,6 +669,7 @@ pub(crate) fn derive_selected_suffix_schedule( level: level + 1, current_witness_len: next_witness_len, current_lb: open_lb, + source_moment: next_source_moment, incoming_setup_prefix: None, dimension_ceiling: candidate_params.role_dims(), payload_phase: payload_phase.after(candidate_params.payload_mode), @@ -633,6 +692,7 @@ pub(crate) fn derive_selected_suffix_schedule( level: level + 1, current_witness_len: next_witness_len, current_lb: open_lb, + source_moment: next_source_moment, incoming_setup_prefix: Some(natural_len), dimension_ceiling: candidate_params.role_dims(), payload_phase, diff --git a/crates/akita-planner/src/schedule_params/suffix_dp/state.rs b/crates/akita-planner/src/schedule_params/suffix_dp/state.rs index a49cd8a83..d98f63220 100644 --- a/crates/akita-planner/src/schedule_params/suffix_dp/state.rs +++ b/crates/akita-planner/src/schedule_params/suffix_dp/state.rs @@ -82,6 +82,7 @@ pub(super) struct ScheduleMemoKey { pub(super) level: usize, pub(super) current_witness_len: usize, pub(super) current_lb: u32, + pub(super) source_mean_l2_sq: Option, pub(super) incoming_setup_prefix: Option, pub(super) d_a: usize, pub(super) d_b: usize, @@ -222,6 +223,7 @@ pub(crate) struct SuffixState { pub(crate) level: usize, pub(crate) current_witness_len: usize, pub(crate) current_lb: u32, + pub(crate) source_moment: Option, pub(crate) incoming_setup_prefix: Option, pub(crate) dimension_ceiling: CommitmentRingDims, pub(crate) payload_phase: akita_types::CommitmentPayloadPhase, @@ -247,6 +249,7 @@ impl SuffixState { level: self.level, current_witness_len: self.current_witness_len, current_lb: self.current_lb, + source_mean_l2_sq: self.source_moment.map(|moment| moment.mean_l2_sq()), incoming_setup_prefix: self.incoming_setup_prefix, d_a: memo_dimensions.d_a(), d_b: memo_dimensions.d_b(), diff --git a/crates/akita-planner/src/schedule_params/suffix_dp/terminal.rs b/crates/akita-planner/src/schedule_params/suffix_dp/terminal.rs index 6b50dd272..644a18fba 100644 --- a/crates/akita-planner/src/schedule_params/suffix_dp/terminal.rs +++ b/crates/akita-planner/src/schedule_params/suffix_dp/terminal.rs @@ -3,24 +3,29 @@ use super::*; /// Like [`terminal_direct_suffix_cost`], but returns `None` when the fold at /// `terminal_fold_level` is multi-chunk. The suffix DP uses this to skip the /// fold-then-direct branch without aborting fold-then-fold exploration. +#[allow(clippy::too_many_arguments)] pub(crate) fn try_terminal_direct_suffix_cost( + policy: &PlannerPolicy, input_witness_len: usize, terminal_lp: &CommittedGroupParams, field_bits: u32, key: PolynomialGroupLayout, terminal_fold_level: usize, opening_layout: Option<&OpeningClaimsLayout>, + source_moment: Option, ) -> Result, AkitaError> { if terminal_lp.witness_chunk.num_chunks > 1 { return Ok(None); } let result = terminal_direct_suffix_cost( + policy, input_witness_len, terminal_lp, field_bits, key, terminal_fold_level, opening_layout, + source_moment, ); match result { Ok(candidate) => Ok(Some(candidate)), @@ -32,13 +37,16 @@ pub(crate) fn try_terminal_direct_suffix_cost( } } +#[allow(clippy::too_many_arguments)] pub(crate) fn terminal_direct_suffix_cost( + policy: &PlannerPolicy, input_witness_len: usize, terminal_lp: &CommittedGroupParams, field_bits: u32, key: PolynomialGroupLayout, terminal_fold_level: usize, opening_layout: Option<&OpeningClaimsLayout>, + source_moment: Option, ) -> Result<(CandidateTerminalResponse, usize), AkitaError> { // Scalar same-point root fold: polynomial count at the root, 1 recursively. let num_polynomials = if terminal_fold_level == 0 { @@ -61,17 +69,58 @@ pub(crate) fn terminal_direct_suffix_cost( "terminal direct response must be a scalar flat fold".to_string(), )); } - let (terminal_params, admission_cap) = + let (mut terminal_params, admission_cap) = akita_types::TerminalCommittedGroupParams::try_from_expanded_group(terminal_lp.clone())?; + let mut sparse_challenge_config = terminal_lp.fold_challenge_config; + if let Some(l2_challenge) = + akita_challenges::selective_l2_challenge_config(terminal_params.d_a()) + { + let fold_basis = 1usize + .checked_shl(terminal_lp.log_basis_open) + .ok_or_else(|| AkitaError::InvalidSetup("terminal L2 basis overflow".into()))?; + let response_l2_sq_cap = source_moment + .and_then(|moment| moment.response_l2_sq_cap(l2_challenge.challenge_l2_sq_max())); + if let Some(l2_matrix) = akita_schedules::planner_support::selective_l2_inner_matrix( + policy, + akita_schedules::planner_support::SelectiveL2CandidateGeometry { + fold_level: terminal_fold_level, + num_claims: 1, + num_chunks: 1, + inner_width: terminal_params.inner_width(), + ring_dimension: terminal_params.d_a(), + fold_basis, + fold_digit_count: terminal_lp.num_digits_fold, + fold_challenge_config: &l2_challenge, + response_l2_sq_cap, + norm_proof_shape: Some(akita_types::PhysicalL2NormProofShape::Direct { + physical_response_len: terminal_params + .inner_width() + .checked_mul(terminal_params.d_a()) + .ok_or_else(|| { + AkitaError::InvalidSetup("terminal L2 response length overflow".into()) + })?, + }), + }, + )? { + if l2_matrix.output_rank() < terminal_params.inner_commit_matrix.output_rank() { + terminal_params.inner_commit_matrix = l2_matrix; + sparse_challenge_config = l2_challenge; + } + } + } let witness_shape = TerminalResponseShape::derive(&terminal_params, admission_cap)?; - let terminal_bytes = terminal_response_bytes(field_bits, &witness_shape); + let estimated_terminal_bytes = terminal_response_planner_bytes( + field_bits, + &witness_shape, + terminal_params.response_l2_sq_cap(), + ); let direct = CandidateTerminalResponse { params: terminal_params, - sparse_challenge_config: terminal_lp.fold_challenge_config, + sparse_challenge_config, input_witness_len, estimated_direct_payload_bytes: 0, response_shape: witness_shape, - estimated_payload_bytes: terminal_bytes, + estimated_payload_bytes: estimated_terminal_bytes, }; - Ok((direct, terminal_bytes)) + Ok((direct, estimated_terminal_bytes)) } diff --git a/crates/akita-planner/src/test/adaptive_dimensions.rs b/crates/akita-planner/src/test/adaptive_dimensions.rs index e6f323f97..171acc452 100644 --- a/crates/akita-planner/src/test/adaptive_dimensions.rs +++ b/crates/akita-planner/src/test/adaptive_dimensions.rs @@ -68,17 +68,27 @@ fn fp32_suffix_candidates_are_uniform_and_monotone() { } #[test] -fn fp32_dense_rejects_the_insecure_nv14_shape() { +fn fp32_dense_nv14_uses_corrected_physical_a_bound() { use akita_config::proof_optimized::fp32; + use akita_types::InnerCommitSecurityRoute; let policy = akita_config::policy_of::(); - let error = crate::planner::find_schedule( + let planned = crate::planner::find_schedule( &akita_types::AkitaScheduleLookupKey::single(PolynomialGroupLayout::singleton(14)), fp32::Dense::root_honest_fold_policy(), &[], &policy, fp32::Dense::ring_challenge_config, ) - .expect_err("fp32 dense nv14 must remain outside the securable catalog"); - assert!(matches!(error, AkitaError::UnsupportedSchedule(_))); + .expect("physical A sizing no longer double-counts the subfield embedding norm"); + let root = &planned.schedule.root.params.final_group.commitment; + assert_eq!(root.inner_commit_matrix.coeff_linf_bound(), Some(8_388_607)); + assert!(matches!( + root.inner_commit_matrix.security_route(), + InnerCommitSecurityRoute::Linf(_) + )); + assert!(planned.schedule.recursive_folds.iter().any(|step| matches!( + step.params.witness.inner_commit_matrix.security_route(), + InnerCommitSecurityRoute::L2 { .. } + ))); } diff --git a/crates/akita-planner/src/test/adaptive_search.rs b/crates/akita-planner/src/test/adaptive_search.rs index 207316596..7cc88e58f 100644 --- a/crates/akita-planner/src/test/adaptive_search.rs +++ b/crates/akita-planner/src/test/adaptive_search.rs @@ -158,6 +158,7 @@ fn terminal_candidates_compete_across_opening_bases() { ring_dimension: 128, }; policy.selection_policy = crate::SelectionPolicyId::MinEstimatedProofPayload; + policy.selective_l2_response_model = crate::SelectiveL2ResponseModelId::Disabled; let selected = find_schedule( PolynomialGroupLayout::singleton(14), &policy, @@ -177,7 +178,7 @@ fn terminal_candidates_compete_across_opening_bases() { .witness .inner_commit_matrix .coeff_linf_bound(), - 262_143, + Some(131_071), ); } @@ -222,6 +223,30 @@ fn adaptive_dimension_search_is_canonical() { ); } +#[cfg(feature = "catalog-gen")] +#[test] +fn production_suffix_selects_l2_with_the_typed_response_model() { + use akita_config::{policy_of, proof_optimized::fp128, CommitmentConfig}; + use akita_types::InnerCommitSecurityRoute; + + let domain = RingDimensionSearchDomain::uniform(64).expect("test domain"); + let fp128_policy = policy_of::(); + let selected = find_schedule( + PolynomialGroupLayout::singleton(40), + &fp128_policy, + fp128::OneHot::root_honest_fold_policy(), + &domain, + fp128::OneHot::ring_challenge_config, + ) + .expect("shipped fp128 selective L2 schedule"); + assert!(selected.schedule.recursive_folds.iter().any(|step| { + matches!( + step.params.witness.inner_commit_matrix.security_route(), + InnerCommitSecurityRoute::L2 { .. } + ) + })); +} + #[test] fn uniform_suffix_dp_matches_unpruned_exact_cutover_search() { use akita_config::{policy_of, proof_optimized::fp128::OneHot, CommitmentConfig}; @@ -770,6 +795,7 @@ fn exact_payload_ties_prefer_the_smaller_setup_envelope() { // fixed-D64 domain, where two equal-payload schedules differ in setup size. let mut base_policy = policy_of::(); base_policy.uniform_ring_dimension = 64; + base_policy.selective_l2_response_model = crate::SelectiveL2ResponseModelId::Disabled; let policy = policy_for_domain(base_policy, &domain); let selected = find_schedule( PolynomialGroupLayout::singleton(32), diff --git a/crates/akita-planner/src/test/recursive_setup.rs b/crates/akita-planner/src/test/recursive_setup.rs index 6ec439f5b..92d3eec6b 100644 --- a/crates/akita-planner/src/test/recursive_setup.rs +++ b/crates/akita-planner/src/test/recursive_setup.rs @@ -38,7 +38,7 @@ fn recursive_exact_cutover_proof_size_is_documented() { assert_eq!( planned.estimate.estimated_proof_payload_bytes().unwrap(), - 91_832 + 80_644 ); } @@ -100,7 +100,7 @@ fn scalar_recursive_nv36_selects_offloaded_schedule() { ); assert_eq!( planned.estimate.estimated_proof_payload_bytes().unwrap(), - 93_224 + 81_364 ); } diff --git a/crates/akita-planner/src/test/schedule_params_candidate.rs b/crates/akita-planner/src/test/schedule_params_candidate.rs index 11a7d63d0..bf8569fc9 100644 --- a/crates/akita-planner/src/test/schedule_params_candidate.rs +++ b/crates/akita-planner/src/test/schedule_params_candidate.rs @@ -95,6 +95,52 @@ fn recursive_split_policy_controls_the_shared_search_domain() { ); } +#[cfg(feature = "catalog-gen")] +#[test] +fn response_model_adds_at_most_one_best_split_l2_alternative() { + use akita_config::{policy_of, proof_optimized::fp128::OneHot, CommitmentConfig}; + use akita_types::InnerCommitSecurityRoute; + + let policy = policy_of::(); + let challenge = OneHot::ring_challenge_config(64).expect("D64 challenge"); + let candidates = derive_candidate_level_params( + None, + &policy, + akita_types::CommitmentPayloadMode::Compressed, + &challenge, + CommitmentRingDims::uniform(64), + 948_672, + crate::InnerBasisSource::BalancedDigits { log_basis: 4 }, + 4, + 4, + 3, + None, + Some(crate::response_model::SourceMomentEstimate::new(1_000_000).unwrap()), + ) + .expect("modeled late-fold candidates"); + let linf = candidates + .iter() + .filter(|(params, _)| { + matches!( + params.inner_commit_matrix.security_route(), + InnerCommitSecurityRoute::Linf(_) + ) + }) + .count(); + let l2 = candidates + .iter() + .filter(|(params, _)| { + matches!( + params.inner_commit_matrix.security_route(), + InnerCommitSecurityRoute::L2 { .. } + ) + }) + .count(); + assert_eq!(linf, 1); + assert_eq!(l2, 1); + assert_eq!(candidates.len(), 2); +} + #[cfg(feature = "catalog-gen")] #[test] fn setup_prefix_frontier_excludes_unsupported_compression_sources() { diff --git a/crates/akita-planner/src/test/suffix_dp.rs b/crates/akita-planner/src/test/suffix_dp.rs index 80c6926b6..a0386e329 100644 --- a/crates/akita-planner/src/test/suffix_dp.rs +++ b/crates/akita-planner/src/test/suffix_dp.rs @@ -8,6 +8,7 @@ fn suffix_cache_gives_referenced_entry_a_second_chance() { level, current_witness_len: 1024, current_lb: 3, + source_mean_l2_sq: None, incoming_setup_prefix: None, d_a: 64, d_b: 64, @@ -54,6 +55,7 @@ fn memo_key_discards_dimension_history_after_adaptive_cutoff() { level, current_witness_len: 1024, current_lb: 3, + source_moment: None, incoming_setup_prefix: None, dimension_ceiling, payload_phase: akita_types::CommitmentPayloadPhase::CompressedPrefix, @@ -94,6 +96,7 @@ fn fp32_suffix_memo_key_retains_only_the_effective_transition_ceiling() { level: num_search_levels, current_witness_len: 1024, current_lb: 3, + source_moment: None, incoming_setup_prefix: None, dimension_ceiling, payload_phase: akita_types::CommitmentPayloadPhase::CompressedPrefix, diff --git a/crates/akita-planner/src/test/unpruned_search.rs b/crates/akita-planner/src/test/unpruned_search.rs index 9049b213b..55564b1f9 100644 --- a/crates/akita-planner/src/test/unpruned_search.rs +++ b/crates/akita-planner/src/test/unpruned_search.rs @@ -13,6 +13,7 @@ struct UnprunedState { level: usize, input_witness_len: usize, current_log_basis: u32, + source_moment: Option, dimension_ceiling: CommitmentRingDims, payload_phase: akita_types::CommitmentPayloadPhase, } @@ -31,6 +32,7 @@ fn enumerate_suffixes( level, input_witness_len, current_log_basis, + source_moment, dimension_ceiling, payload_phase, } = state; @@ -83,9 +85,10 @@ fn enumerate_suffixes( log_basis, level, None, + source_moment, )? } else { - derive_candidate_level_params( + derive_linf_candidate_level_params( None, policy, payload_mode, @@ -109,12 +112,14 @@ fn enumerate_suffixes( || level >= akita_schedules::ADAPTIVE_SEARCH_LEVELS { suffix_dp::try_terminal_direct_suffix_cost( + policy, input_witness_len, ¶ms, field_bits, key, level, None, + source_moment, )? } else { None @@ -153,12 +158,29 @@ fn enumerate_suffixes( } else { params.role_dims() }; + let next_source_moment = if policy.selective_l2_response_model_enabled() { + let opening_layout = suffix_opening_layout(input_witness_len, None)?; + Some(crate::response_model::next_source_moment( + ¶ms, + &opening_layout, + &[source_moment.ok_or_else(|| { + AkitaError::InvalidSetup( + "unpruned response source moment is missing".into(), + ) + })?], + field_bits, + policy.claim_ext_degree, + )?) + } else { + None + }; for child in enumerate_suffixes( ctx, UnprunedState { level: level + 1, input_witness_len: output_witness_len, current_log_basis: log_basis, + source_moment: next_source_moment, dimension_ceiling: child_ceiling, payload_phase: payload_phase.after(params.payload_mode), }, @@ -269,6 +291,25 @@ pub(super) fn find_schedule( true, )? { + let next_source_moment = if policy.selective_l2_response_model_enabled() { + let opening_layout = schedule_key.opening_layout()?; + let source_groups = crate::response_model::root_group_source_moments( + &root_params, + &opening_layout, + honest_fold_policy, + &[], + field_bits, + )?; + Some(crate::response_model::next_source_moment( + &root_params, + &opening_layout, + &source_groups, + field_bits, + policy.claim_ext_degree, + )?) + } else { + None + }; let Some(eor_bytes) = try_extension_opening_reduction_level_bytes( policy.challenge_field_bits()?, policy.claim_ext_degree, @@ -286,6 +327,7 @@ pub(super) fn find_schedule( level: 1, input_witness_len: output_witness_len, current_log_basis: log_basis, + source_moment: next_source_moment, dimension_ceiling: *root_dimensions, payload_phase: akita_types::CommitmentPayloadPhase::CompressedPrefix, }, diff --git a/crates/akita-prover/src/backend/poly_helpers/decompose_fold_partitioned.rs b/crates/akita-prover/src/backend/poly_helpers/decompose_fold_partitioned.rs index 475b7796a..b867d29dc 100644 --- a/crates/akita-prover/src/backend/poly_helpers/decompose_fold_partitioned.rs +++ b/crates/akita-prover/src/backend/poly_helpers/decompose_fold_partitioned.rs @@ -6,7 +6,8 @@ use super::rotated_accum::{ }; use super::{ decompose_ring_interleaved, decompose_ring_interleaved_i16, fill_rotated_challenge, - sparse_mul_acc, sparse_mul_acc_i16, DecomposeParams, + sparse_mul_acc, sparse_mul_acc_i16, sparse_mul_acc_i16_pm1, sparse_mul_acc_pm1, + DecomposeParams, }; use akita_algebra::CyclotomicRing; use akita_challenges::SparseChallenge; @@ -16,6 +17,32 @@ use akita_types::SignedDigitKernel; type RotatedTable = Option<[[i16; D]; D]>; +struct PreparedPm1Challenge { + positive: Vec, + negative: Vec, +} + +fn prepare_pm1_challenge( + challenge: &SparseChallenge, +) -> Option { + if challenge.positions.len() != challenge.coeffs.len() { + return None; + } + let mut positive = Vec::with_capacity(challenge.positions.len()); + let mut negative = Vec::with_capacity(challenge.positions.len()); + for (&position, &coefficient) in challenge.positions.iter().zip(&challenge.coeffs) { + if position >= D as u32 { + return None; + } + match coefficient { + 1 => positive.push(position), + -1 => negative.push(position), + _ => return None, + } + } + Some(PreparedPm1Challenge { positive, negative }) +} + fn precompute_rotated_tables( challenges: &[SparseChallenge], ) -> Vec> { @@ -31,6 +58,23 @@ fn precompute_rotated_tables( .collect() } +fn precompute_pm1_challenges( + challenges: &[SparseChallenge], + rotated_tables: &[RotatedTable], +) -> Vec> { + challenges + .iter() + .zip(rotated_tables) + .map(|(challenge, rotated)| { + if rotated.is_none() { + prepare_pm1_challenge::(challenge) + } else { + None + } + }) + .collect() +} + fn partition_thread_count(num_positions_per_block: usize) -> usize { #[cfg(feature = "parallel")] let num_threads = rayon::current_num_threads(); @@ -89,6 +133,7 @@ impl ElementFoldSource<'_, F, D> { acc: &mut [[i32; D]], challenge: &SparseChallenge, rotated: Option<&[[i16; D]; D]>, + pm1: Option<&PreparedPm1Challenge>, digit_scratch: Option<&mut DigitScratch>, num_digits: usize, ) { @@ -107,11 +152,13 @@ impl ElementFoldSource<'_, F, D> { (Self::Predecomposed { digit_planes, .. }, None) => { let src_base = ring_idx * num_digits; for digit_idx in 0..num_digits { - sparse_mul_acc::( - &digit_planes[src_base + digit_idx], - challenge, - &mut acc[dst_base + digit_idx], - ); + let digit_plane = &digit_planes[src_base + digit_idx]; + let digit_acc = &mut acc[dst_base + digit_idx]; + if let Some(pm1) = pm1 { + sparse_mul_acc_pm1(digit_plane, &pm1.positive, &pm1.negative, digit_acc); + } else { + sparse_mul_acc(digit_plane, challenge, digit_acc); + } } } (Self::LiveRings { coeffs, params }, Some(rotated)) => { @@ -134,11 +181,20 @@ impl ElementFoldSource<'_, F, D> { params, ); for digit in 0..num_digits { - sparse_mul_acc::( - &digit_buf[digit], - challenge, - &mut acc[base + digit], - ); + if let Some(pm1) = pm1 { + sparse_mul_acc_pm1( + &digit_buf[digit], + &pm1.positive, + &pm1.negative, + &mut acc[base + digit], + ); + } else { + sparse_mul_acc( + &digit_buf[digit], + challenge, + &mut acc[base + digit], + ); + } } } DigitScratch::I16(digit_buf) => { @@ -149,11 +205,20 @@ impl ElementFoldSource<'_, F, D> { params, ); for digit in 0..num_digits { - sparse_mul_acc_i16::( - &digit_buf[digit], - challenge, - &mut acc[base + digit], - ); + if let Some(pm1) = pm1 { + sparse_mul_acc_i16_pm1( + &digit_buf[digit], + &pm1.positive, + &pm1.negative, + &mut acc[base + digit], + ); + } else { + sparse_mul_acc_i16( + &digit_buf[digit], + challenge, + &mut acc[base + digit], + ); + } } } } @@ -176,6 +241,7 @@ fn element_partitioned_decompose_fold( } let rotated_tables = precompute_rotated_tables::(challenges); + let pm1_challenges = precompute_pm1_challenges(challenges, &rotated_tables); let actual_threads = partition_thread_count(num_positions_per_block); let elem_chunk = num_positions_per_block.div_ceil(actual_threads); let mut out = vec![[0i32; D]; inner_width]; @@ -209,6 +275,7 @@ fn element_partitioned_decompose_fold( acc, challenge, rotated_tables[block_idx].as_ref(), + pm1_challenges[block_idx].as_ref(), digit_scratch.as_mut(), num_digits, ); @@ -270,6 +337,10 @@ pub fn balanced_tight_digit_fold_partitioned( let actual_threads = num_threads.min(inner_width).max(1); let pos_chunk = inner_width.div_ceil(actual_threads); + let pm1_challenges = challenges + .iter() + .map(prepare_pm1_challenge::) + .collect::>(); let chunks: Vec> = cfg_into_iter!(0..actual_threads) .map(|tid| { @@ -292,7 +363,8 @@ pub fn balanced_tight_digit_fold_partitioned( continue; } - for (block, challenge) in challenges.iter().enumerate() { + for (block, (challenge, pm1)) in challenges.iter().zip(&pm1_challenges).enumerate() + { let Some(index) = block .checked_mul(num_positions_per_block) .and_then(|base| base.checked_add(col)) @@ -302,7 +374,16 @@ pub fn balanced_tight_digit_fold_partitioned( let Some(coeff) = coeffs.get(index) else { break; }; - sparse_mul_acc::(coeff, challenge, &mut acc[out_pos - pos_start]); + if let Some(pm1) = pm1 { + sparse_mul_acc_pm1( + coeff, + &pm1.positive, + &pm1.negative, + &mut acc[out_pos - pos_start], + ); + } else { + sparse_mul_acc(coeff, challenge, &mut acc[out_pos - pos_start]); + } } } acc diff --git a/crates/akita-prover/src/backend/poly_helpers/mod.rs b/crates/akita-prover/src/backend/poly_helpers/mod.rs index a02f800d0..eb6a6eddf 100644 --- a/crates/akita-prover/src/backend/poly_helpers/mod.rs +++ b/crates/akita-prover/src/backend/poly_helpers/mod.rs @@ -349,12 +349,22 @@ pub(crate) fn sparse_mul_acc_scalar( 1 => sparse_mul_acc_add_scalar::(digit_plane, acc, p), -1 => sparse_mul_acc_sub_scalar::(digit_plane, acc, p), 2 => { - sparse_mul_acc_add_scalar::(digit_plane, acc, p); - sparse_mul_acc_add_scalar::(digit_plane, acc, p); + let split = D - p; + for i in 0..split { + acc[i + p] += 2 * i32::from(digit_plane[i]); + } + for i in split..D { + acc[i - split] -= 2 * i32::from(digit_plane[i]); + } } -2 => { - sparse_mul_acc_sub_scalar::(digit_plane, acc, p); - sparse_mul_acc_sub_scalar::(digit_plane, acc, p); + let split = D - p; + for i in 0..split { + acc[i + p] -= 2 * i32::from(digit_plane[i]); + } + for i in split..D { + acc[i - split] += 2 * i32::from(digit_plane[i]); + } } _ => { let split = D - p; @@ -437,6 +447,51 @@ pub(crate) fn sparse_mul_acc( sparse_mul_acc_scalar::(digit_plane, challenge, acc); } +pub(crate) fn sparse_mul_acc_pm1( + digit_plane: &[i8; D], + positive: &[u32], + negative: &[u32], + acc: &mut [i32; D], +) { + debug_assert!(positive + .iter() + .chain(negative) + .all(|&position| position < D as u32)); + #[cfg(any( + target_arch = "aarch64", + all(target_arch = "x86_64", target_feature = "avx2") + ))] + if use_simd_decompose_fold() { + #[cfg(target_arch = "aarch64")] + unsafe { + decompose_fold_neon::sparse_mul_acc_pm1_neon( + digit_plane.as_ptr(), + acc.as_mut_ptr(), + D, + positive, + negative, + ); + } + #[cfg(all(target_arch = "x86_64", target_feature = "avx2"))] + unsafe { + decompose_fold_avx::sparse_mul_acc_pm1_avx( + digit_plane.as_ptr(), + acc.as_mut_ptr(), + D, + positive, + negative, + ); + } + return; + } + for &position in positive { + sparse_mul_acc_add_scalar(digit_plane, acc, position as usize); + } + for &position in negative { + sparse_mul_acc_sub_scalar(digit_plane, acc, position as usize); + } +} + /// Signed-i16 sparse multiply-accumulate for large inner bases. #[inline(always)] pub(crate) fn sparse_mul_acc_i16( @@ -486,6 +541,59 @@ pub(crate) fn sparse_mul_acc_i16( sparse_mul_acc_i16_scalar::(digit_plane, challenge, acc); } +pub(crate) fn sparse_mul_acc_i16_pm1( + digit_plane: &[i16; D], + positive: &[u32], + negative: &[u32], + acc: &mut [i32; D], +) { + debug_assert!(positive + .iter() + .chain(negative) + .all(|&position| position < D as u32)); + #[cfg(any( + target_arch = "aarch64", + all(target_arch = "x86_64", target_feature = "avx2") + ))] + if use_simd_decompose_fold() { + #[cfg(target_arch = "aarch64")] + unsafe { + decompose_fold_neon::sparse_mul_acc_i16_pm1_neon( + digit_plane.as_ptr(), + acc.as_mut_ptr(), + D, + positive, + negative, + ); + } + #[cfg(all(target_arch = "x86_64", target_feature = "avx2"))] + unsafe { + decompose_fold_avx::sparse_mul_acc_i16_pm1_avx( + digit_plane.as_ptr(), + acc.as_mut_ptr(), + D, + positive, + negative, + ); + } + return; + } + for (&position, scale) in positive + .iter() + .map(|position| (position, 1)) + .chain(negative.iter().map(|position| (position, -1))) + { + let position = position as usize; + let split = D - position; + for i in 0..split { + acc[i + position] += scale * i32::from(digit_plane[i]); + } + for i in split..D { + acc[i - split] -= scale * i32::from(digit_plane[i]); + } + } +} + /// Precompute dense rotation table for a sparse challenge. /// /// `table[c]` holds the small signed coefficients of `challenge * X^c` in the ring diff --git a/crates/akita-prover/src/backend/poly_helpers/tests.rs b/crates/akita-prover/src/backend/poly_helpers/tests.rs index 0f2c64a02..d25b5f842 100644 --- a/crates/akita-prover/src/backend/poly_helpers/tests.rs +++ b/crates/akita-prover/src/backend/poly_helpers/tests.rs @@ -3,8 +3,8 @@ use super::rotated_accum::{ }; use super::{ balanced_ring_decompose_fold_partitioned, decompose_ring_interleaved, fill_rotated_challenge, - sparse_mul_acc, sparse_mul_acc_i16, sparse_mul_acc_i16_scalar, sparse_mul_acc_scalar, - DecomposeParams, + sparse_mul_acc, sparse_mul_acc_i16, sparse_mul_acc_i16_pm1, sparse_mul_acc_i16_scalar, + sparse_mul_acc_pm1, sparse_mul_acc_scalar, DecomposeParams, }; use akita_algebra::CyclotomicRing; use akita_challenges::SparseChallenge; @@ -190,6 +190,33 @@ fn sparse_mul_acc_i16_simd_matches_scalar() { assert_eq!(simd_acc, scalar_acc); } +#[test] +fn prepared_pm1_kernels_match_generic_sparse_accumulation() { + const D: usize = 256; + let positive = vec![0, 17, 61, 128, 251]; + let negative = vec![3, 29, 97, 191, 255]; + let challenge = SparseChallenge { + positions: positive.iter().chain(&negative).copied().collect(), + coeffs: std::iter::repeat_n(1, positive.len()) + .chain(std::iter::repeat_n(-1, negative.len())) + .collect(), + }; + + let i8_plane = std::array::from_fn(|index| ((index * 17) % 127) as i8 - 63); + let mut expected_i8 = [0i32; D]; + sparse_mul_acc(&i8_plane, &challenge, &mut expected_i8); + let mut actual_i8 = [0i32; D]; + sparse_mul_acc_pm1(&i8_plane, &positive, &negative, &mut actual_i8); + assert_eq!(actual_i8, expected_i8); + + let i16_plane = std::array::from_fn(|index| ((index * 509) % 1024) as i16 - 512); + let mut expected_i16 = [0i32; D]; + sparse_mul_acc_i16(&i16_plane, &challenge, &mut expected_i16); + let mut actual_i16 = [0i32; D]; + sparse_mul_acc_i16_pm1(&i16_plane, &positive, &negative, &mut actual_i16); + assert_eq!(actual_i16, expected_i16); +} + #[test] #[should_panic] fn sparse_mul_acc_rejects_out_of_range_challenge_before_dispatch() { diff --git a/crates/akita-prover/src/backend/recursive/setup_prefix_source.rs b/crates/akita-prover/src/backend/recursive/setup_prefix_source.rs index 3fdcaf1b9..41eac0d74 100644 --- a/crates/akita-prover/src/backend/recursive/setup_prefix_source.rs +++ b/crates/akita-prover/src/backend/recursive/setup_prefix_source.rs @@ -76,6 +76,15 @@ impl RootPolyMeta for RecursiveFoldSource { Self::Witness(witness) => RootPolyMeta::::num_vars(witness.as_ref()), } } + + fn exact_integer_coeff_l2_sq(&self) -> Option { + match self { + Self::SetupPrefix { .. } => None, + Self::Witness(witness) => { + RootPolyMeta::::exact_integer_coeff_l2_sq(witness.as_ref()) + } + } + } } impl RootPolyShape for RecursiveFoldSource { diff --git a/crates/akita-prover/src/backend/recursive/witness.rs b/crates/akita-prover/src/backend/recursive/witness.rs index a0a1687c7..c0363bd6b 100644 --- a/crates/akita-prover/src/backend/recursive/witness.rs +++ b/crates/akita-prover/src/backend/recursive/witness.rs @@ -542,6 +542,15 @@ where let coeff_count = self.digits.len().next_power_of_two().max(1); coeff_count.trailing_zeros() as usize } + + fn exact_integer_coeff_l2_sq(&self) -> Option { + self.digits.iter().try_fold(0u128, |sum, &digit| { + let magnitude = u128::from(digit.unsigned_abs()); + magnitude + .checked_mul(magnitude) + .and_then(|square| sum.checked_add(square)) + }) + } } impl RootCommitSource for RecursiveWitnessFlat diff --git a/crates/akita-prover/src/compute/poly.rs b/crates/akita-prover/src/compute/poly.rs index 7bf84e0f7..9970bf792 100644 --- a/crates/akita-prover/src/compute/poly.rs +++ b/crates/akita-prover/src/compute/poly.rs @@ -43,6 +43,16 @@ where fn onehot_chunk_size(&self) -> Option { None } + + /// Exact squared L2 norm when this source is already represented by + /// centered integer coefficients. + /// + /// This is diagnostic metadata for honest-response modeling. Root field + /// polynomials generally return `None`; recursive digit witnesses can + /// expose the exact quantity without converting field elements. + fn exact_integer_coeff_l2_sq(&self) -> Option { + None + } } /// Shape metadata every root polynomial exposes, keyed on the const ring @@ -571,4 +581,8 @@ where fn onehot_chunk_size(&self) -> Option { RootPolyMeta::onehot_chunk_size(*self) } + + fn exact_integer_coeff_l2_sq(&self) -> Option { + RootPolyMeta::exact_integer_coeff_l2_sq(*self) + } } diff --git a/crates/akita-prover/src/compute/requirements.rs b/crates/akita-prover/src/compute/requirements.rs index 74ebf0f15..cd8a43860 100644 --- a/crates/akita-prover/src/compute/requirements.rs +++ b/crates/akita-prover/src/compute/requirements.rs @@ -682,7 +682,13 @@ mod tests { #[test] #[cfg(feature = "schedules-default")] fn dense_small_field_nv26_cache_plan_matches_adaptive_geometry() { - for (schedule, expected_root_d, expected_root_basis, expected_root_cache_len) in [ + for ( + schedule, + expected_root_d, + expected_root_basis, + expected_root_cache_len, + expects_i16_tail, + ) in [ ( fp32::Dense::runtime_schedule(AkitaScheduleLookupKey::single( PolynomialGroupLayout::singleton(26), @@ -691,6 +697,7 @@ mod tests { 1024, 8, 4096, + false, ), ( fp64::Dense::runtime_schedule(AkitaScheduleLookupKey::single( @@ -698,8 +705,9 @@ mod tests { )) .expect("generated fp64 dense schedule"), 512, - 6, - 11_264, + 10, + 7_168, + true, ), ] { let root = &schedule.root.params.final_group.commitment; @@ -708,16 +716,28 @@ mod tests { let requirements = NttExecutionRequirements::from_commit_and_prove_schedule(&schedule) .expect("compile complete small-field NTT requirements"); - assert!(requirements.entries().iter().all(|entry| matches!( - entry.key.domain, - NttTransformDomain::Negacyclic | NttTransformDomain::Cyclic - ))); + let has_i16_tail = requirements.entries().iter().any(|entry| { + matches!( + entry.key.domain, + NttTransformDomain::I16TailBothTransforms + | NttTransformDomain::ExactNegacyclicI16 { .. } + ) + }); + assert_eq!(has_i16_tail, expects_i16_tail); assert!(requirements.entries().iter().any(|entry| { + let expected_commit_domain = if expects_i16_tail { + matches!( + entry.key.domain, + NttTransformDomain::ExactNegacyclicI16 { .. } + ) + } else { + entry.key.domain == NttTransformDomain::Negacyclic + }; entry.fold_level == 0 && entry.cluster == NttOperationCluster::Commit && entry.key.ring_d == expected_root_d && entry.key.num_ring_elements == expected_root_cache_len - && entry.key.domain == NttTransformDomain::Negacyclic + && expected_commit_domain })); } } diff --git a/crates/akita-prover/src/kernels/decompose_fold_avx.rs b/crates/akita-prover/src/kernels/decompose_fold_avx.rs index fa80b3ebc..54b95ff29 100644 --- a/crates/akita-prover/src/kernels/decompose_fold_avx.rs +++ b/crates/akita-prover/src/kernels/decompose_fold_avx.rs @@ -13,10 +13,9 @@ use std::arch::x86_64::*; /// /// For each challenge term `(pos, coeff)`, rotates the `digit_plane` by `pos` /// positions in the negacyclic ring (X^D + 1) and adds or subtracts the -/// widened `i8` values into the `i32` `acc`. Small magnitudes like `±2` reuse -/// the unit add/sub kernel multiple times so two-magnitude families -/// (e.g. exact-shell challenges with `max_abs_coeff <= 2`) stay on the SIMD -/// fast path. +/// widened `i8` values into the `i32` `acc`. Coefficients `±2` use one +/// widened, doubled add/sub pass so two-magnitude challenge families stay on +/// the SIMD fast path without repeating a full rotation. /// /// # Safety /// @@ -40,14 +39,8 @@ pub(crate) unsafe fn sparse_mul_acc_avx( match coeff { 1 => acc_rotated_add(digit_plane, acc, d, p, split), -1 => acc_rotated_sub(digit_plane, acc, d, p, split), - 2 => { - acc_rotated_add(digit_plane, acc, d, p, split); - acc_rotated_add(digit_plane, acc, d, p, split); - } - -2 => { - acc_rotated_sub(digit_plane, acc, d, p, split); - acc_rotated_sub(digit_plane, acc, d, p, split); - } + 2 => acc_rotated_add_twice(digit_plane, acc, p, split), + -2 => acc_rotated_sub_twice(digit_plane, acc, p, split), _ => { for _ in 0..coeff.unsigned_abs() { if coeff > 0 { @@ -61,6 +54,31 @@ pub(crate) unsafe fn sparse_mul_acc_avx( } } +/// Branch-free AVX2 kernel for a prepared ±1-only challenge. +/// +/// # Safety +/// +/// `digit_plane` and `acc` must each address `d` valid elements, every +/// position must be below `d`, and `d` must be a multiple of 16. +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn sparse_mul_acc_pm1_avx( + digit_plane: *const i8, + acc: *mut i32, + d: usize, + positive: &[u32], + negative: &[u32], +) { + debug_assert!(d.is_multiple_of(16)); + for &position in positive { + let position = position as usize; + acc_rotated_add(digit_plane, acc, d, position, d - position); + } + for &position in negative { + let position = position as usize; + acc_rotated_sub(digit_plane, acc, d, position, d - position); + } +} + /// Signed-i16 variant used by large inner decomposition bases. /// /// # Safety @@ -82,18 +100,79 @@ pub(crate) unsafe fn sparse_mul_acc_i16_avx( for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { let p = pos as usize; let split = d - p; - for _ in 0..coeff.unsigned_abs() { - if coeff > 0 { + match coeff { + 1 => { acc_segment_i16_add(digit_plane, acc.add(p), split); if p > 0 { acc_segment_i16_sub(digit_plane.add(split), acc, p); } - } else { + } + -1 => { acc_segment_i16_sub(digit_plane, acc.add(p), split); if p > 0 { acc_segment_i16_add(digit_plane.add(split), acc, p); } } + 2 => { + acc_segment_i16_add_twice(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_sub_twice(digit_plane.add(split), acc, p); + } + } + -2 => { + acc_segment_i16_sub_twice(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_add_twice(digit_plane.add(split), acc, p); + } + } + _ => { + for _ in 0..coeff.unsigned_abs() { + if coeff > 0 { + acc_segment_i16_add(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_sub(digit_plane.add(split), acc, p); + } + } else { + acc_segment_i16_sub(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_add(digit_plane.add(split), acc, p); + } + } + } + } + } + } +} + +/// Branch-free AVX2 i16 kernel for a prepared ±1-only challenge. +/// +/// # Safety +/// +/// `digit_plane` and `acc` must each address `d` valid elements, every +/// position must be below `d`, and `d` must be a multiple of 8. +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn sparse_mul_acc_i16_pm1_avx( + digit_plane: *const i16, + acc: *mut i32, + d: usize, + positive: &[u32], + negative: &[u32], +) { + debug_assert!(d.is_multiple_of(8)); + for &position in positive { + let position = position as usize; + let split = d - position; + acc_segment_i16_add(digit_plane, acc.add(position), split); + if position > 0 { + acc_segment_i16_sub(digit_plane.add(split), acc, position); + } + } + for &position in negative { + let position = position as usize; + let split = d - position; + acc_segment_i16_sub(digit_plane, acc.add(position), split); + if position > 0 { + acc_segment_i16_add(digit_plane.add(split), acc, position); } } } @@ -128,6 +207,36 @@ unsafe fn acc_segment_i16_sub(src: *const i16, dst: *mut i32, len: usize) { } } +#[inline(always)] +unsafe fn acc_segment_i16_add_twice(src: *const i16, dst: *mut i32, len: usize) { + let chunks = len / 8; + for i in 0..chunks { + let offset = i * 8; + let values = _mm_loadu_si128(src.add(offset).cast()); + let widened = _mm256_slli_epi32::<1>(_mm256_cvtepi16_epi32(values)); + let current = _mm256_loadu_si256(dst.add(offset).cast()); + _mm256_storeu_si256(dst.add(offset).cast(), _mm256_add_epi32(current, widened)); + } + for i in chunks * 8..len { + *dst.add(i) += 2 * i32::from(*src.add(i)); + } +} + +#[inline(always)] +unsafe fn acc_segment_i16_sub_twice(src: *const i16, dst: *mut i32, len: usize) { + let chunks = len / 8; + for i in 0..chunks { + let offset = i * 8; + let values = _mm_loadu_si128(src.add(offset).cast()); + let widened = _mm256_slli_epi32::<1>(_mm256_cvtepi16_epi32(values)); + let current = _mm256_loadu_si256(dst.add(offset).cast()); + _mm256_storeu_si256(dst.add(offset).cast(), _mm256_sub_epi32(current, widened)); + } + for i in chunks * 8..len { + *dst.add(i) -= 2 * i32::from(*src.add(i)); + } +} + /// `acc[i+p] += digits[i]` for `i in [0, split)`, /// `acc[i-split] -= digits[i]` for `i in [split, D)` (negacyclic wrap). // @@ -156,6 +265,22 @@ unsafe fn acc_rotated_sub(digits: *const i8, acc: *mut i32, d: usize, p: usize, let _ = d; } +#[inline(always)] +unsafe fn acc_rotated_add_twice(digits: *const i8, acc: *mut i32, p: usize, split: usize) { + acc_segment_add_twice(digits, acc.add(p), split); + if p > 0 { + acc_segment_sub_twice(digits.add(split), acc, p); + } +} + +#[inline(always)] +unsafe fn acc_rotated_sub_twice(digits: *const i8, acc: *mut i32, p: usize, split: usize) { + acc_segment_sub_twice(digits, acc.add(p), split); + if p > 0 { + acc_segment_add_twice(digits.add(split), acc, p); + } +} + /// Widen `i8` source values to `i32` and add into accumulator. /// Processes 16 elements per outer iteration (two 8-wide `__m256i` chunks), /// then handles any remainder scalar. @@ -214,3 +339,39 @@ unsafe fn acc_segment_sub(src: *const i8, dst: *mut i32, len: usize) { *dst.add(base + i) -= val; } } + +#[inline(always)] +unsafe fn acc_segment_add_twice(src: *const i8, dst: *mut i32, len: usize) { + let chunks = len / 16; + for i in 0..chunks { + let offset = i * 16; + let values = _mm_loadu_si128(src.add(offset).cast()); + let low = _mm256_slli_epi32::<1>(_mm256_cvtepi8_epi32(values)); + let high = _mm256_slli_epi32::<1>(_mm256_cvtepi8_epi32(_mm_srli_si128::<8>(values))); + let dst_low = _mm256_loadu_si256(dst.add(offset).cast()); + let dst_high = _mm256_loadu_si256(dst.add(offset + 8).cast()); + _mm256_storeu_si256(dst.add(offset).cast(), _mm256_add_epi32(dst_low, low)); + _mm256_storeu_si256(dst.add(offset + 8).cast(), _mm256_add_epi32(dst_high, high)); + } + for i in chunks * 16..len { + *dst.add(i) += 2 * i32::from(*src.add(i)); + } +} + +#[inline(always)] +unsafe fn acc_segment_sub_twice(src: *const i8, dst: *mut i32, len: usize) { + let chunks = len / 16; + for i in 0..chunks { + let offset = i * 16; + let values = _mm_loadu_si128(src.add(offset).cast()); + let low = _mm256_slli_epi32::<1>(_mm256_cvtepi8_epi32(values)); + let high = _mm256_slli_epi32::<1>(_mm256_cvtepi8_epi32(_mm_srli_si128::<8>(values))); + let dst_low = _mm256_loadu_si256(dst.add(offset).cast()); + let dst_high = _mm256_loadu_si256(dst.add(offset + 8).cast()); + _mm256_storeu_si256(dst.add(offset).cast(), _mm256_sub_epi32(dst_low, low)); + _mm256_storeu_si256(dst.add(offset + 8).cast(), _mm256_sub_epi32(dst_high, high)); + } + for i in chunks * 16..len { + *dst.add(i) -= 2 * i32::from(*src.add(i)); + } +} diff --git a/crates/akita-prover/src/kernels/decompose_fold_neon.rs b/crates/akita-prover/src/kernels/decompose_fold_neon.rs index 4e4f38862..5fdcce547 100644 --- a/crates/akita-prover/src/kernels/decompose_fold_neon.rs +++ b/crates/akita-prover/src/kernels/decompose_fold_neon.rs @@ -12,10 +12,9 @@ use std::arch::aarch64::*; /// /// For each challenge term `(pos, coeff)`, rotates the `digit_plane` by `pos` /// positions in the negacyclic ring (X^D + 1) and adds or subtracts the -/// widened i8 values into the i32 `acc`. Small magnitudes like `+/-2` reuse -/// the unit add/sub kernel multiple times so two-magnitude families -/// (e.g. exact-shell challenges with `max_abs_coeff <= 2`) stay on the NEON -/// fast path. +/// widened i8 values into the i32 `acc`. Coefficients `+/-2` use one widened, +/// doubled add/sub pass so two-magnitude challenge families stay on the NEON +/// fast path without repeating a full rotation. /// /// # Safety /// @@ -39,14 +38,8 @@ pub(crate) unsafe fn sparse_mul_acc_neon( match coeff { 1 => acc_rotated_add(digit_plane, acc, d, p, split), -1 => acc_rotated_sub(digit_plane, acc, d, p, split), - 2 => { - acc_rotated_add(digit_plane, acc, d, p, split); - acc_rotated_add(digit_plane, acc, d, p, split); - } - -2 => { - acc_rotated_sub(digit_plane, acc, d, p, split); - acc_rotated_sub(digit_plane, acc, d, p, split); - } + 2 => acc_rotated_add_twice(digit_plane, acc, p, split), + -2 => acc_rotated_sub_twice(digit_plane, acc, p, split), _ => { for _ in 0..coeff.unsigned_abs() { if coeff > 0 { @@ -60,6 +53,31 @@ pub(crate) unsafe fn sparse_mul_acc_neon( } } +/// Branch-free NEON kernel for a prepared ±1-only challenge. +/// +/// # Safety +/// +/// `digit_plane` and `acc` must each address `d` valid elements, every +/// position must be below `d`, and `d` must be a multiple of 16. +#[target_feature(enable = "neon")] +pub(crate) unsafe fn sparse_mul_acc_pm1_neon( + digit_plane: *const i8, + acc: *mut i32, + d: usize, + positive: &[u32], + negative: &[u32], +) { + debug_assert!(d.is_multiple_of(16)); + for &position in positive { + let position = position as usize; + acc_rotated_add(digit_plane, acc, d, position, d - position); + } + for &position in negative { + let position = position as usize; + acc_rotated_sub(digit_plane, acc, d, position, d - position); + } +} + /// Signed-i16 variant used by large inner decomposition bases. /// /// # Safety @@ -81,18 +99,79 @@ pub(crate) unsafe fn sparse_mul_acc_i16_neon( for (&pos, &coeff) in positions.iter().zip(coeffs.iter()) { let p = pos as usize; let split = d - p; - for _ in 0..coeff.unsigned_abs() { - if coeff > 0 { + match coeff { + 1 => { acc_segment_i16_add(digit_plane, acc.add(p), split); if p > 0 { acc_segment_i16_sub(digit_plane.add(split), acc, p); } - } else { + } + -1 => { acc_segment_i16_sub(digit_plane, acc.add(p), split); if p > 0 { acc_segment_i16_add(digit_plane.add(split), acc, p); } } + 2 => { + acc_segment_i16_add_twice(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_sub_twice(digit_plane.add(split), acc, p); + } + } + -2 => { + acc_segment_i16_sub_twice(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_add_twice(digit_plane.add(split), acc, p); + } + } + _ => { + for _ in 0..coeff.unsigned_abs() { + if coeff > 0 { + acc_segment_i16_add(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_sub(digit_plane.add(split), acc, p); + } + } else { + acc_segment_i16_sub(digit_plane, acc.add(p), split); + if p > 0 { + acc_segment_i16_add(digit_plane.add(split), acc, p); + } + } + } + } + } + } +} + +/// Branch-free NEON i16 kernel for a prepared ±1-only challenge. +/// +/// # Safety +/// +/// `digit_plane` and `acc` must each address `d` valid elements, every +/// position must be below `d`, and `d` must be a multiple of 8. +#[target_feature(enable = "neon")] +pub(crate) unsafe fn sparse_mul_acc_i16_pm1_neon( + digit_plane: *const i16, + acc: *mut i32, + d: usize, + positive: &[u32], + negative: &[u32], +) { + debug_assert!(d.is_multiple_of(8)); + for &position in positive { + let position = position as usize; + let split = d - position; + acc_segment_i16_add(digit_plane, acc.add(position), split); + if position > 0 { + acc_segment_i16_sub(digit_plane.add(split), acc, position); + } + } + for &position in negative { + let position = position as usize; + let split = d - position; + acc_segment_i16_sub(digit_plane, acc.add(position), split); + if position > 0 { + acc_segment_i16_add(digit_plane.add(split), acc, position); } } } @@ -133,6 +212,42 @@ unsafe fn acc_segment_i16_sub(src: *const i16, dst: *mut i32, len: usize) { } } +#[inline(always)] +unsafe fn acc_segment_i16_add_twice(src: *const i16, dst: *mut i32, len: usize) { + let chunks = len / 8; + for i in 0..chunks { + let offset = i * 8; + let values = vld1q_s16(src.add(offset)); + let low = vshlq_n_s32::<1>(vmovl_s16(vget_low_s16(values))); + let high = vshlq_n_s32::<1>(vmovl_s16(vget_high_s16(values))); + let dst_low = vld1q_s32(dst.add(offset)); + let dst_high = vld1q_s32(dst.add(offset + 4)); + vst1q_s32(dst.add(offset), vaddq_s32(dst_low, low)); + vst1q_s32(dst.add(offset + 4), vaddq_s32(dst_high, high)); + } + for i in chunks * 8..len { + *dst.add(i) += 2 * i32::from(*src.add(i)); + } +} + +#[inline(always)] +unsafe fn acc_segment_i16_sub_twice(src: *const i16, dst: *mut i32, len: usize) { + let chunks = len / 8; + for i in 0..chunks { + let offset = i * 8; + let values = vld1q_s16(src.add(offset)); + let low = vshlq_n_s32::<1>(vmovl_s16(vget_low_s16(values))); + let high = vshlq_n_s32::<1>(vmovl_s16(vget_high_s16(values))); + let dst_low = vld1q_s32(dst.add(offset)); + let dst_high = vld1q_s32(dst.add(offset + 4)); + vst1q_s32(dst.add(offset), vsubq_s32(dst_low, low)); + vst1q_s32(dst.add(offset + 4), vsubq_s32(dst_high, high)); + } + for i in chunks * 8..len { + *dst.add(i) -= 2 * i32::from(*src.add(i)); + } +} + /// Add rotated digit plane: acc[i+p] += digits[i] for i in [0, split), /// acc[i-split] -= digits[i] for i in [split, D) (negacyclic wrap). #[inline(always)] @@ -159,6 +274,22 @@ unsafe fn acc_rotated_sub(digits: *const i8, acc: *mut i32, d: usize, p: usize, let _ = d; } +#[inline(always)] +unsafe fn acc_rotated_add_twice(digits: *const i8, acc: *mut i32, p: usize, split: usize) { + acc_segment_add_twice(digits, acc.add(p), split); + if p > 0 { + acc_segment_sub_twice(digits.add(split), acc, p); + } +} + +#[inline(always)] +unsafe fn acc_rotated_sub_twice(digits: *const i8, acc: *mut i32, p: usize, split: usize) { + acc_segment_sub_twice(digits, acc.add(p), split); + if p > 0 { + acc_segment_add_twice(digits.add(split), acc, p); + } +} + /// Widen i8 source values to i32 and ADD into accumulator. /// Handles arbitrary length (processes 16 at a time, then remainder). #[inline(always)] @@ -236,3 +367,51 @@ unsafe fn acc_segment_sub(src: *const i8, dst: *mut i32, len: usize) { *dst.add(base + i) -= val; } } + +#[inline(always)] +unsafe fn acc_segment_add_twice(src: *const i8, dst: *mut i32, len: usize) { + let chunks = len / 16; + for i in 0..chunks { + let offset = i * 16; + let values = vld1q_s8(src.add(offset)); + let low = vmovl_s8(vget_low_s8(values)); + let high = vmovl_s8(vget_high_s8(values)); + let lanes = [ + vshlq_n_s32::<1>(vmovl_s16(vget_low_s16(low))), + vshlq_n_s32::<1>(vmovl_s16(vget_high_s16(low))), + vshlq_n_s32::<1>(vmovl_s16(vget_low_s16(high))), + vshlq_n_s32::<1>(vmovl_s16(vget_high_s16(high))), + ]; + for (lane, values) in lanes.into_iter().enumerate() { + let lane_dst = dst.add(offset + lane * 4); + vst1q_s32(lane_dst, vaddq_s32(vld1q_s32(lane_dst), values)); + } + } + for i in chunks * 16..len { + *dst.add(i) += 2 * i32::from(*src.add(i)); + } +} + +#[inline(always)] +unsafe fn acc_segment_sub_twice(src: *const i8, dst: *mut i32, len: usize) { + let chunks = len / 16; + for i in 0..chunks { + let offset = i * 16; + let values = vld1q_s8(src.add(offset)); + let low = vmovl_s8(vget_low_s8(values)); + let high = vmovl_s8(vget_high_s8(values)); + let lanes = [ + vshlq_n_s32::<1>(vmovl_s16(vget_low_s16(low))), + vshlq_n_s32::<1>(vmovl_s16(vget_high_s16(low))), + vshlq_n_s32::<1>(vmovl_s16(vget_low_s16(high))), + vshlq_n_s32::<1>(vmovl_s16(vget_high_s16(high))), + ]; + for (lane, values) in lanes.into_iter().enumerate() { + let lane_dst = dst.add(offset + lane * 4); + vst1q_s32(lane_dst, vsubq_s32(vld1q_s32(lane_dst), values)); + } + } + for i in chunks * 16..len { + *dst.add(i) -= 2 * i32::from(*src.add(i)); + } +} diff --git a/crates/akita-prover/src/protocol/core/fold/mod.rs b/crates/akita-prover/src/protocol/core/fold/mod.rs index 65ab98837..6949485e9 100644 --- a/crates/akita-prover/src/protocol/core/fold/mod.rs +++ b/crates/akita-prover/src/protocol/core/fold/mod.rs @@ -9,14 +9,30 @@ use crate::compute::{ use crate::protocol::sumcheck::relation_range_image::PreparedProverEvaluationTrace; use crate::protocol::sumcheck::DigitRangeProver; use crate::RecursiveWitnessFlat; +use akita_algebra::offset_eq::{materialize_eq_tensor_left, OffsetEqWindow}; use akita_field::unreduced::ReduceTo; use akita_field::AdditiveGroup; use akita_types::{ - dispatch_for_field, DigitRangeEqualityPoint, DigitRangePlan, OpeningClaimsLayout, - RelationRangeImagePlan, + dispatch_for_field, DigitRangeEqualityPoint, DigitRangePlan, InnerCommitSecurityRoute, + OpeningClaimsLayout, PhysicalResponsePlan, RelationRangeImagePlan, }; +pub(in crate::protocol::core) struct PhysicalL2ProverReplay { + plan: PhysicalResponsePlan, + point: Vec, + virtual_evaluations: Vec, + batching: Vec, + claim: E, +} + +type Stage1ProveOutput = ( + AkitaStage1Proof, + Vec, + E, + Option>, +); + pub(in crate::protocol::core) use extension_claim::{ prepare_extension_claim_fold, ExtensionOpeningSource, }; @@ -428,12 +444,27 @@ where rs.alpha, prepared_fold.instance.rhs(), )?; - let (stage1_proof, stage1_point, range_image_evaluation) = - prove_stage1::(transcript, &mut rs, &relation_range_image_plan)?; + let (stage1_proof, stage1_point, range_image_evaluation, physical_l2) = + prove_stage1::(transcript, &mut rs, lp, &relation_range_image_plan)?; transcript.append_serde( ABSORB_RANGE_IMAGE_EVALUATION, &stage1_proof.range_image_evaluation, ); + let physical_l2 = physical_l2.map(|mut replay| { + let eta = sample_ext_challenge::( + transcript, + akita_transcript::labels::CHALLENGE_L2_VIRTUAL_BATCH, + ); + let mut power = E::one(); + replay.batching = Vec::with_capacity(replay.virtual_evaluations.len()); + replay.claim = E::zero(); + for &evaluation in &replay.virtual_evaluations { + replay.batching.push(power); + replay.claim += evaluation * power; + power *= eta; + } + replay + }); let stage1_proof = Some(stage1_proof); let binary_batching = lp .payload_mode @@ -488,6 +519,7 @@ where range_image_evaluation, relation_claim, binary_batching, + physical_l2, evaluation_trace, trace_opening_claim, relation_range_image_plan, @@ -581,8 +613,9 @@ where pub(in crate::protocol::core) fn prove_stage1( transcript: &mut T, rs: &mut RingSwitchOutput, + lp: &CommittedGroupParams, plan: &RelationRangeImagePlan, -) -> Result<(AkitaStage1Proof, Vec, E), AkitaError> +) -> Result, AkitaError> where F: FieldCore + CanonicalField, E: ExtField + HasUnreducedOps + HasOptimizedFold + FromPrimitiveInt + AkitaSerialize, @@ -614,9 +647,52 @@ where domain, equality_point, )?; - let (stage1_proof, stage1_point) = stage1_prover.prove::(transcript)?; + let physical_plan = PhysicalResponsePlan::new(lp, plan)?; + let (stage1_proof, stage1_point) = + stage1_prover.prove::(transcript, physical_plan.as_ref())?; let range_image_evaluation = stage1_proof.range_image_evaluation; - Ok((stage1_proof, stage1_point, range_image_evaluation)) + let physical_l2 = match physical_plan { + Some(physical_plan) => { + let norm_proof = stage1_proof + .norm_proof + .as_ref() + .ok_or(AkitaError::InvalidProof)?; + let InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, .. + } = lp.inner_commit_matrix.security_route() + else { + return Err(AkitaError::InvalidSetup( + "physical L2 plan disagrees with the A security route".into(), + )); + }; + if norm_proof.response_l2_sq > response_l2_sq_cap { + return Err(AkitaError::InvalidInput( + "folded response exceeds the scheduled L2 cap".into(), + )); + } + Some(PhysicalL2ProverReplay { + plan: physical_plan, + point: stage1_point.clone(), + virtual_evaluations: norm_proof.virtual_evaluations.clone(), + batching: Vec::new(), + claim: E::zero(), + }) + } + None => { + if stage1_proof.norm_proof.is_some() { + return Err(AkitaError::InvalidInput( + "L-infinity route produced an L2 norm proof".into(), + )); + } + None + } + }; + Ok(( + stage1_proof, + stage1_point, + range_image_evaluation, + physical_l2, + )) } #[allow(clippy::too_many_arguments)] @@ -629,6 +705,7 @@ fn prove_stage2( range_image_evaluation: E, relation_claim: E, binary_batching: Option, + physical_l2: Option>, evaluation_trace: PreparedProverEvaluationTrace, trace_opening_claim: E, plan: RelationRangeImagePlan, @@ -662,23 +739,45 @@ where common_alpha_factor.len(), ))); } - let additional_relation_terms = rs - .compression_relation_weights - .map(|weights| { - let compression_domain_len = weights.physical_field_len(); - let binary_support = - NegativeBinarySupport::new(plan.witness_layout(), compression_domain_len)?; + let domain_len = domain.domain_len(); + let mut linear_weights = Vec::new(); + let mut binary_intervals = Vec::new(); + if let Some(weights) = rs.compression_relation_weights { + if weights.physical_field_len() != domain_len { + return Err(AkitaError::InvalidSetup( + "compression relation domain disagrees with Stage 2".into(), + )); + } + linear_weights = weights.into_sparse_entries()?; + binary_intervals = NegativeBinarySupport::new(plan.witness_layout(), domain_len)? + .intervals() + .to_vec(); + } + let physical_l2_claim = physical_l2.as_ref().map_or_else(E::zero, |norm| norm.claim); + if let Some(norm) = &physical_l2 { + let families = norm.plan.virtualization_families(&norm.batching)?; + let equality = OffsetEqWindow::new(&norm.point)?; + linear_weights.extend( + materialize_eq_tensor_left(&equality, &families, domain.live_len())? + .into_iter() + .enumerate() + .filter(|(_, weight)| !weight.is_zero()), + ); + linear_weights.sort_unstable_by_key(|(index, _)| *index); + } + let additional_relation_terms = (!linear_weights.is_empty() || !binary_intervals.is_empty()) + .then(|| { AdditionalRelationTerms::new( rs.w_evals_compact.as_ref(), - compression_domain_len, - weights.into_sparse_entries()?, - binary_support.intervals(), + domain_len, + linear_weights, + &binary_intervals, stage1_point, - binary_batching.ok_or(AkitaError::InvalidProof)?, + binary_batching.unwrap_or_else(E::zero), ) }) .transpose()?; - let ordinary_relation_claim = relation_claim + let ordinary_relation_claim = relation_claim + physical_l2_claim - additional_relation_terms .as_ref() .map_or_else(E::zero, AdditionalRelationTerms::input_claim); diff --git a/crates/akita-prover/src/protocol/core/root_group.rs b/crates/akita-prover/src/protocol/core/root_group.rs index df9c0c37c..8c80dbee4 100644 --- a/crates/akita-prover/src/protocol/core/root_group.rs +++ b/crates/akita-prover/src/protocol/core/root_group.rs @@ -20,6 +20,7 @@ pub(crate) struct PreparedGroupOpening { pub(crate) trait RootProverGroupMeta { fn num_polynomials(&self) -> usize; fn num_vars(&self) -> Result; + fn exact_integer_coeff_l2_sq(&self) -> Option; } pub(crate) trait RootProverGroupOpening: RootProverGroupMeta @@ -47,7 +48,7 @@ where challenges: &Challenges, root_params: &CommittedGroupParams, params: &(impl LevelParamsLike + ?Sized), - ) -> Result, AkitaError>; + ) -> Result, AkitaError>; } pub(crate) trait RootProverGroupTensor: RootProverGroupMeta @@ -108,6 +109,13 @@ where } Ok(num_vars) } + + fn exact_integer_coeff_l2_sq(&self) -> Option { + self.polynomial_refs().iter().try_fold(0u128, |sum, poly| { + crate::compute::RootPolyMeta::::exact_integer_coeff_l2_sq(*poly) + .and_then(|energy| sum.checked_add(energy)) + }) + } } impl RootProverGroupOpening for PreparedProverGroup<'_, P> @@ -174,7 +182,7 @@ where challenges: &Challenges, root_params: &CommittedGroupParams, params: &(impl LevelParamsLike + ?Sized), - ) -> Result, AkitaError> { + ) -> Result, AkitaError> { let ring_dimension = params.inner_commit_matrix_params().ring_dimension(); dispatch_for_field!( ProtocolDispatchSlot::Role(RingRole::Inner), @@ -192,7 +200,7 @@ where root_params, params, )?; - Ok::<_, AkitaError>(crate::protocol::fold_grind::FoldGrindGroupOutput { + Ok::<_, AkitaError>(crate::protocol::fold_grind::FoldProbeOutput { witness, centered_per_chunk: centered .into_iter() diff --git a/crates/akita-prover/src/protocol/fold_grind.rs b/crates/akita-prover/src/protocol/fold_grind.rs index 84959e549..da7fb421e 100644 --- a/crates/akita-prover/src/protocol/fold_grind.rs +++ b/crates/akita-prover/src/protocol/fold_grind.rs @@ -10,8 +10,9 @@ use akita_field::{AkitaError, CanonicalField, FieldCore, FromPrimitiveInt}; use akita_transcript::{AkitaTranscript, FoldChallengeSeedPreview, Transcript, TranscriptSponge}; use akita_types::{ dyadic_block_ranges, golomb_rice_total_wire_bits, golomb_rice_values_within_cap, - golomb_rice_zigzag_width, CommittedGroupParams, FoldLinfProtocolBinding, LevelParamsLike, - OpeningClaimsLayout, TerminalCommittedGroupParams, TerminalResponseShape, + golomb_rice_zigzag_width, CommittedGroupParams, FoldLinfProtocolBinding, + InnerCommitSecurityRoute, LevelParamsLike, OpeningClaimsLayout, TerminalCommittedGroupParams, + TerminalResponseShape, }; use super::ring_relation::{ @@ -47,15 +48,18 @@ where struct FoldGrindAcceptanceCtx { digit_negative_abs_bound: u128, digit_positive_bound: u128, + response_l2_sq_cap: Option, } fn fold_grind_acceptance_ctx( digit_negative_abs_bound: u128, digit_positive_bound: u128, + response_l2_sq_cap: Option, ) -> FoldGrindAcceptanceCtx { FoldGrindAcceptanceCtx { digit_negative_abs_bound, digit_positive_bound, + response_l2_sq_cap, } } @@ -73,35 +77,69 @@ fn accepts_fold_witness( witness: &DecomposeFoldWitness, z_folded_centered_per_chunk: &[Vec<[i32; D]>], ) -> bool { - for coeff in z_folded_centered_per_chunk + let coefficients = z_folded_centered_per_chunk .iter() .flat_map(|chunk| chunk.iter()) - .flat_map(|coeffs| coeffs.iter()) - { - if !coeff_within_digit_bounds(*coeff, ctx) { + .flat_map(|coeffs| coeffs.iter()); + if ctx.response_l2_sq_cap.is_none() { + return coefficients + .into_iter() + .all(|&coeff| coeff_within_digit_bounds(coeff, ctx)); + } + let mut response_l2_sq = 0u128; + for &coeff in coefficients { + if !coeff_within_digit_bounds(coeff, ctx) { return false; } + let magnitude = u128::from(coeff.unsigned_abs()); + let Some(next) = magnitude + .checked_mul(magnitude) + .and_then(|square| response_l2_sq.checked_add(square)) + else { + return false; + }; + response_l2_sq = next; } let _ = witness; - true + ctx.response_l2_sq_cap + .is_some_and(|cap| response_l2_sq <= cap) } fn accepts_fold_witness_flat( ctx: &FoldGrindAcceptanceCtx, witness: &DecomposeFoldWitness, centered_per_chunk: &[Vec>], -) -> bool { +) -> Option> { + let measure_response_l2 = ctx.response_l2_sq_cap.is_some() + || tracing::enabled!( + target: "akita_prover::protocol::fold_response_model", + tracing::Level::INFO + ); let coefficients = centered_per_chunk .iter() .flat_map(|chunk| chunk.iter()) .flat_map(|row| row.iter()); + if !measure_response_l2 { + return coefficients + .into_iter() + .all(|&coefficient| coeff_within_digit_bounds(coefficient, ctx)) + .then_some(None); + } + let mut response_l2_sq = 0u128; for &coefficient in coefficients { if !coeff_within_digit_bounds(coefficient, ctx) { - return false; + return None; } + let magnitude = u128::from(coefficient.unsigned_abs()); + let next = magnitude + .checked_mul(magnitude) + .and_then(|square| response_l2_sq.checked_add(square))?; + response_l2_sq = next; } let _ = witness; - true + ctx.response_l2_sq_cap + .is_none_or(|cap| response_l2_sq <= cap) + .then_some(Some(response_l2_sq)) } pub(crate) struct FoldGrindGroup<'params, 'group, G> { @@ -118,7 +156,7 @@ impl Clone for FoldGrindGroup<'_, '_, G> { } } -pub(crate) struct FoldGrindGroupOutput { +pub(crate) struct FoldProbeOutput { pub(crate) witness: DecomposeFoldWitness, pub(crate) centered_per_chunk: Vec>>, pub(crate) challenges: Challenges, @@ -144,7 +182,7 @@ pub(crate) fn sample_terminal_fold_response( where F: FieldCore + CanonicalField + FromPrimitiveInt + HasWide + 'static, ::Wide: From + ReduceTo, - P: RuntimeOpeningSource, + P: RuntimeOpeningSource + crate::compute::RootPolyMeta, B: crate::compute::ComputeBackendSetup + RuntimeOpeningProveBackendFor, T: Transcript + ProverTranscriptGrind, { @@ -169,19 +207,31 @@ where "terminal response cap exceeds its fixed matrix capacity".into(), )); } + let response_l2_sq_cap = params.response_l2_sq_cap(); + let operator_rejection = if response_l2_sq_cap.is_some() { + Some( + akita_challenges::selective_l2_operator_norm_rejection(params.d_a(), sparse) + .ok_or_else(|| { + AkitaError::InvalidSetup("unsupported terminal L2 challenge policy".into()) + })?, + ) + } else { + None + }; let binding = FoldLinfProtocolBinding::CURRENT; let polys = [poly]; let point_indices = [0usize]; let (nonce, (witness, challenges)) = first_jointly_accepted_nonce(binding.max_grind_attempts, |nonce| { let mut preview = PreviewFoldDraw::new(transcript); - let challenges = preview.draw_folding_challenges( + let challenges = preview.draw_folding_challenges_with_rejection( params.d_a(), 0, params.num_live_blocks, 1, sparse, nonce, + operator_rejection, )?; let witness = dispatch_for_field!( akita_types::ProtocolDispatchSlot::Role(akita_types::RingRole::Inner), @@ -208,6 +258,11 @@ where if golomb_rice_values_within_cap(¢ered, admission_cap).is_err() { return Ok(None); } + if response_l2_sq_cap.is_some_and(|cap| { + akita_types::sis::checked_centered_l2_sq(¢ered).is_none_or(|norm| norm > cap) + }) { + return Ok(None); + } let zigzag_width = golomb_rice_zigzag_width(admission_cap); let wire_bits = golomb_rice_total_wire_bits( ¢ered, @@ -220,13 +275,51 @@ where Ok(Some((witness, challenges))) })?; let mut live = LiveFoldDraw::::new(transcript); - let live_challenges = - live.draw_folding_challenges(params.d_a(), 0, params.num_live_blocks, 1, sparse, nonce)?; + let live_challenges = live.draw_folding_challenges_with_rejection( + params.d_a(), + 0, + params.num_live_blocks, + 1, + sparse, + nonce, + operator_rejection, + )?; if live_challenges != challenges { return Err(AkitaError::InvalidInput( "terminal grind preview did not match live transcript replay".into(), )); } + if tracing::enabled!( + target: "akita_prover::protocol::fold_response_model", + tracing::Level::INFO + ) { + let source_l2_sq = crate::compute::RootPolyMeta::exact_integer_coeff_l2_sq(poly); + let conditional_mean_l2_sq = + source_l2_sq.and_then(|energy| energy.checked_mul(sparse.challenge_l2_sq_max())); + let response_l2_sq = + akita_types::sis::checked_centered_l2_sq(witness.centered_coeffs_flat()); + tracing::info!( + target: "akita_prover::protocol::fold_response_model", + terminal = true, + nonce, + attempts = nonce + 1, + ring_dimension = params.d_a(), + num_live_blocks = params.num_live_blocks, + num_positions_per_block = params.num_positions_per_block, + response_coeffs = witness.centered_coeffs_flat().len(), + log_basis_inner = params.log_basis_inner, + num_digits_inner = params.num_digits_inner, + challenge_weight = sparse.weight(), + challenge_l1 = sparse.l1_norm(), + challenge_l2_sq = sparse.challenge_l2_sq_max(), + challenge_linf = sparse.infinity_norm(), + source_l2_sq = ?source_l2_sq, + conditional_mean_l2_sq = ?conditional_mean_l2_sq, + response_l2_sq = ?response_l2_sq, + response_l2_sq_cap = ?response_l2_sq_cap, + "terminal fold response model sample" + ); + } Ok(TerminalFoldGrindOutput { witness, nonce }) } @@ -326,7 +419,7 @@ fn sample_multi_group_fold_decompose_witnesses_native( root_lp: &CommittedGroupParams, groups: &[PreparedFoldGrindGroup<'_, '_, G>], max_grind_attempts: u32, -) -> Result<(Vec>, u32), AkitaError> +) -> Result<(Vec>, u32), AkitaError> where F: FieldCore + CanonicalField + FromPrimitiveInt + HasWide + 'static, ::Wide: From + ReduceTo, @@ -350,52 +443,124 @@ where for prepared_group in groups { let group = &prepared_group.input; let ring_d = group.params.inner_commit_matrix_params().ring_dimension(); - let challenges = preview.draw_folding_challenges( + let challenge_config = group.params.fold_challenge_config(); + let rejection = matches!( + group.params.inner_commit_matrix_params().security_route(), + InnerCommitSecurityRoute::L2 { .. } + ) + .then(|| { + akita_challenges::selective_l2_operator_norm_rejection( + ring_d, + &challenge_config, + ) + }) + .flatten(); + let challenges = preview.draw_folding_challenges_with_rejection( ring_d, group.group_index, group.params.num_live_blocks(), group.group.num_polynomials(), - &group.params.fold_challenge_config(), + &challenge_config, nonce, + rejection, )?; let output = group .group .probe_fold(opening_ctx, &challenges, root_lp, group.params)?; - let candidate = accepts_fold_witness_flat( + let observed_l2_sq = accepts_fold_witness_flat( &prepared_group.acceptance, &output.witness, &output.centered_per_chunk, - ) - .then_some(output); - let Some(candidate) = candidate else { + ); + let Some(observed_l2_sq) = observed_l2_sq else { return Ok(None); }; - candidate_outputs.push(candidate); + candidate_outputs.push((output, observed_l2_sq)); } } Ok(Some(candidate_outputs)) })?; let mut live = LiveFoldDraw::::new(transcript); - for (prepared_group, output) in groups.iter().zip(candidate_outputs.iter_mut()) { + for (prepared_group, (output, observed_l2_sq)) in + groups.iter().zip(candidate_outputs.iter_mut()) + { let group = &prepared_group.input; let ring_d = group.params.inner_commit_matrix_params().ring_dimension(); - let challenges = live.draw_folding_challenges( + let challenge_config = group.params.fold_challenge_config(); + let rejection = matches!( + group.params.inner_commit_matrix_params().security_route(), + InnerCommitSecurityRoute::L2 { .. } + ) + .then(|| akita_challenges::selective_l2_operator_norm_rejection(ring_d, &challenge_config)) + .flatten(); + let challenges = live.draw_folding_challenges_with_rejection( ring_d, group.group_index, group.params.num_live_blocks(), group.group.num_polynomials(), - &group.params.fold_challenge_config(), + &challenge_config, nonce, + rejection, )?; if challenges != output.challenges { return Err(AkitaError::InvalidInput( "fold grind preview did not match live transcript replay".to_string(), )); } + tracing::info!( + group_index = group.group_index, + nonce, + attempts = nonce + 1, + response_l2_sq = ?observed_l2_sq, + response_l2_sq_cap = ?prepared_group.acceptance.response_l2_sq_cap, + "selected physical fold response" + ); + if let Some(response_l2_sq) = *observed_l2_sq { + let source_l2_sq = group.group.exact_integer_coeff_l2_sq(); + let conditional_mean_l2_sq = source_l2_sq + .and_then(|energy| energy.checked_mul(challenge_config.challenge_l2_sq_max())); + let response_coeffs = output + .centered_per_chunk + .iter() + .flat_map(|chunk| chunk.iter()) + .map(Vec::len) + .sum::(); + tracing::info!( + target: "akita_prover::protocol::fold_response_model", + group_index = group.group_index, + nonce, + attempts = nonce + 1, + ring_dimension = ring_d, + num_polynomials = group.group.num_polynomials(), + num_live_blocks = group.params.num_live_blocks(), + num_positions_per_block = group.params.num_positions_per_block(), + num_chunks = output.centered_per_chunk.len(), + response_coeffs, + log_basis_inner = group.params.log_basis_inner(), + num_digits_inner = group.params.num_digits_inner(), + log_basis_response = group.params.log_basis_open(), + num_digits_response = group.params.num_digits_fold(), + challenge_weight = challenge_config.weight(), + challenge_l1 = challenge_config.l1_norm(), + challenge_l2_sq = challenge_config.challenge_l2_sq_max(), + challenge_linf = challenge_config.infinity_norm(), + source_l2_sq = ?source_l2_sq, + conditional_mean_l2_sq = ?conditional_mean_l2_sq, + response_l2_sq, + response_l2_sq_cap = ?prepared_group.acceptance.response_l2_sq_cap, + "fold response model sample" + ); + } } - Ok((candidate_outputs, nonce)) + Ok(( + candidate_outputs + .into_iter() + .map(|(output, _)| output) + .collect(), + nonce, + )) } /// Probe all root groups off-sponge and commit the first jointly accepted nonce. @@ -411,7 +576,7 @@ pub(crate) fn sample_multi_group_fold_decompose_witnesses( opening_batch: &OpeningClaimsLayout, groups: &[FoldGrindGroup<'_, '_, G>], _tail_t_vectors: Option, -) -> Result<(Vec>, u32), AkitaError> +) -> Result<(Vec>, u32), AkitaError> where F: FieldCore + CanonicalField + FromPrimitiveInt + HasWide + 'static, ::Wide: From + ReduceTo, @@ -447,9 +612,26 @@ where group.params.log_basis_open(), delta_fold, ); + let response_l2_sq_cap = match group.params.inner_commit_matrix_params().security_route() { + InnerCommitSecurityRoute::Linf(_) => None, + InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, .. + } => { + if groups.len() != 1 || group.group_index != 0 { + return Err(AkitaError::InvalidSetup( + "L2 fold grinding requires one scalar group".into(), + )); + } + Some(response_l2_sq_cap) + } + }; prepared_groups.push(PreparedFoldGrindGroup { input: *group, - acceptance: fold_grind_acceptance_ctx(digit_negative_abs_bound, digit_positive_bound), + acceptance: fold_grind_acceptance_ctx( + digit_negative_abs_bound, + digit_positive_bound, + response_l2_sq_cap, + ), }); } sample_multi_group_fold_decompose_witnesses_native::( @@ -518,7 +700,7 @@ mod tests { ); let chunks = vec![vec![[129, 0, 0, 0]], vec![[-12; D]]]; let (neg_bound, pos_bound) = akita_types::sis::fold_witness_representable_linf_bounds(4, 2); - let acceptance = fold_grind_acceptance_ctx(neg_bound, pos_bound); + let acceptance = fold_grind_acceptance_ctx(neg_bound, pos_bound, None); assert!(!accepts_fold_witness::( &acceptance, &witness, @@ -538,7 +720,7 @@ mod tests { let (neg_bound, pos_bound) = akita_types::sis::fold_witness_representable_linf_bounds(6, 2); assert_eq!(neg_bound, 2080); assert_eq!(pos_bound, 2015); - let acceptance = fold_grind_acceptance_ctx(neg_bound, pos_bound); + let acceptance = fold_grind_acceptance_ctx(neg_bound, pos_bound, None); assert!(!accepts_fold_witness::( &acceptance, &witness, @@ -550,7 +732,7 @@ mod tests { fn digit_interval_accepts_both_endpoints_and_rejects_neighbors() { let (negative_abs, positive) = akita_types::sis::fold_witness_representable_linf_bounds(4, 2); - let acceptance = fold_grind_acceptance_ctx(negative_abs, positive); + let acceptance = fold_grind_acceptance_ctx(negative_abs, positive, None); let negative_abs = i32::try_from(negative_abs).unwrap(); let positive = i32::try_from(positive).unwrap(); @@ -559,4 +741,20 @@ mod tests { assert!(!coeff_within_digit_bounds(-negative_abs - 1, &acceptance)); assert!(!coeff_within_digit_bounds(positive + 1, &acceptance)); } + + #[test] + fn joint_grind_applies_the_l2_cap_to_the_complete_physical_response() { + const D: usize = 4; + let witness = DecomposeFoldWitness::from_parts::( + vec![CyclotomicRing::::zero()], + vec![[3, 4, 0, 0]], + 4, + ); + let chunks = vec![vec![[3, 4, 0, 0]]]; + let acceptance = fold_grind_acceptance_ctx(8, 7, Some(25)); + assert!(accepts_fold_witness::(&acceptance, &witness, &chunks)); + + let too_small = fold_grind_acceptance_ctx(8, 7, Some(24)); + assert!(!accepts_fold_witness::(&too_small, &witness, &chunks)); + } } diff --git a/crates/akita-prover/src/protocol/ring_switch/coeffs.rs b/crates/akita-prover/src/protocol/ring_switch/coeffs.rs index 6d3858542..7399c0df3 100644 --- a/crates/akita-prover/src/protocol/ring_switch/coeffs.rs +++ b/crates/akita-prover/src/protocol/ring_switch/coeffs.rs @@ -80,6 +80,102 @@ fn emit_compression_witness( Ok(()) } +fn integer_slice_l2_sq(values: &[i8]) -> u128 { + values.iter().fold(0u128, |sum, &value| { + let magnitude = u128::from(value.unsigned_abs()); + // A witness is indexed by `usize`, while each i8 square is at most + // 2^14. Consequently this sum cannot overflow u128 on a supported + // host, even for the largest addressable witness. + sum + magnitude * magnitude + }) +} + +fn trace_witness_source_moments(witness: &[i8], layout: &WitnessLayout, lp: &CommittedGroupParams) { + if !tracing::enabled!( + target: "akita_prover::protocol::fold_response_model", + tracing::Level::INFO + ) { + return; + } + + let mut z_coeffs = 0usize; + let mut e_coeffs = 0usize; + let mut t_coeffs = 0usize; + let mut z_l2_sq = 0u128; + let mut e_l2_sq = 0u128; + let mut t_l2_sq = 0u128; + for unit in layout.units() { + for (range, coeffs, energy) in [ + (unit.z_range(), &mut z_coeffs, &mut z_l2_sq), + (unit.e_range(), &mut e_coeffs, &mut e_l2_sq), + (unit.t_range(), &mut t_coeffs, &mut t_l2_sq), + ] { + *coeffs += range.len(); + *energy += integer_slice_l2_sq(&witness[range]); + } + } + + let mut r_coeffs = 0usize; + let mut r_l2_sq = 0u128; + for row in layout.r_rows() { + let range = row.range(); + r_coeffs += range.len(); + r_l2_sq += integer_slice_l2_sq(&witness[range]); + } + + let mut compression_coeffs = 0usize; + let mut compression_l2_sq = 0u128; + for layer in layout.compression_layers() { + for (_, span) in layer.f_spans() { + let range = span.range(); + compression_coeffs += range.len(); + compression_l2_sq += integer_slice_l2_sq(&witness[range]); + } + let range = layer.h_span().range(); + compression_coeffs += range.len(); + compression_l2_sq += integer_slice_l2_sq(&witness[range]); + } + + let alignment_coeffs = layout + .compression_alignment_ranges() + .iter() + .map(std::ops::Range::len) + .sum::(); + let classified_coeffs = + z_coeffs + e_coeffs + t_coeffs + r_coeffs + compression_coeffs + alignment_coeffs; + debug_assert_eq!(classified_coeffs, witness.len()); + let source_l2_sq = z_l2_sq + e_l2_sq + t_l2_sq + r_l2_sq + compression_l2_sq; + + tracing::info!( + target: "akita_prover::protocol::fold_response_model", + source_coeffs = witness.len(), + source_l2_sq, + z_coeffs, + z_l2_sq, + e_coeffs, + e_l2_sq, + t_coeffs, + t_l2_sq, + r_coeffs, + r_l2_sq, + compression_coeffs, + compression_l2_sq, + alignment_coeffs, + log_basis_inner = lp.log_basis_inner, + log_basis_outer = lp.log_basis_outer, + log_basis_open = lp.log_basis_open, + num_digits_inner = lp.num_digits_inner, + num_digits_outer = lp.num_digits_outer, + num_digits_open = lp.num_digits_open, + num_digits_fold = lp.num_digits_fold, + d_a = lp.role_dims().d_a(), + d_b = lp.role_dims().d_b(), + d_d = lp.role_dims().d_d(), + compressed = lp.payload_mode.is_compressed(), + "recursive witness source moments" + ); +} + /// Emit one group's physical Z, E, and T planes through the canonical layout. fn emit_group_witness_segments( out: &mut [i8], @@ -404,6 +500,7 @@ where actual: out.len(), }); } + trace_witness_source_moments(&out, &witness_layout, lp); // Every segment of the generated witness is balanced, but grouped // roots may mix decomposition bases. The whole-buffer certificate diff --git a/crates/akita-prover/src/protocol/sumcheck/digit_range/class_indexed_range_leaf.rs b/crates/akita-prover/src/protocol/sumcheck/digit_range/class_indexed_range_leaf.rs index d507ed8bd..d2a1f5d55 100644 --- a/crates/akita-prover/src/protocol/sumcheck/digit_range/class_indexed_range_leaf.rs +++ b/crates/akita-prover/src/protocol/sumcheck/digit_range/class_indexed_range_leaf.rs @@ -53,7 +53,7 @@ fn accumulate_round( } /// Final equality-factored quartic over the virtual range-image table. -pub(super) struct ClassIndexedRangeLeafProver { +pub(in crate::protocol::sumcheck) struct ClassIndexedRangeLeafProver { range_image: RangeImageTableState, split_eq: GruenSplitEq, input_claim: E, @@ -63,7 +63,7 @@ pub(super) struct ClassIndexedRangeLeafProver { } impl ClassIndexedRangeLeafProver { - pub(super) fn new( + pub(in crate::protocol::sumcheck) fn new( source: CompactDigitSource, equality_point: &[E], input_claim: E, @@ -98,7 +98,7 @@ impl ClassIndexedRangeLeafProver { }) } - pub(super) fn final_range_image_eval(&self) -> E { + pub(in crate::protocol::sumcheck) fn final_range_image_eval(&self) -> E { self.range_image .final_value() .expect("range-image leaf was not fully folded") @@ -106,29 +106,19 @@ impl ClassIndexedRangeLeafProver { } impl - EqFactoredSumcheckInstanceProver for ClassIndexedRangeLeafProver + ClassIndexedRangeLeafProver { - fn num_rounds(&self) -> usize { - self.num_rounds - } - - fn degree_bound(&self) -> usize { - self.polynomial_coefficients.len().saturating_sub(1) - } - - fn input_claim(&self) -> E { - self.input_claim - } - - fn current_linear_factor_evals(&self) -> (E, E) { - self.split_eq.linear_factor_evals() - } - - fn compute_round_eq_factored(&mut self, round: usize) -> EqFactoredUniPoly { + /// Compute the existing equality-factored leaf's inner polynomial in + /// coefficient form. Both the ordinary eq-factored driver and the L2 fused + /// driver consume this one kernel. + pub(in crate::protocol::sumcheck) fn round_q_coefficients( + &mut self, + round: usize, + ) -> [E; MAX_TREE_STAGE_Q_DEGREE + 1] { debug_assert_eq!(round, self.rounds_completed); let (equality_prefix_weights, equality_suffix_weights) = self.split_eq.remaining_eq_tables(); - let coefficients = match &self.range_image { + match &self.range_image { RangeImageTableState::Compact(CompactRangeLeafState { source, pair_coefficients, @@ -186,7 +176,43 @@ impl &self.polynomial_coefficients, ) } - }; + } + } + + pub(in crate::protocol::sumcheck) fn final_range_claim(&self) -> E { + let range_image = self.final_range_image_eval(); + let leaf = self + .polynomial_coefficients + .iter() + .rev() + .fold(E::zero(), |acc, &coefficient| { + acc * range_image + coefficient + }); + self.split_eq.current_scalar() * leaf + } +} + +impl + EqFactoredSumcheckInstanceProver for ClassIndexedRangeLeafProver +{ + fn num_rounds(&self) -> usize { + self.num_rounds + } + + fn degree_bound(&self) -> usize { + self.polynomial_coefficients.len().saturating_sub(1) + } + + fn input_claim(&self) -> E { + self.input_claim + } + + fn current_linear_factor_evals(&self) -> (E, E) { + self.split_eq.linear_factor_evals() + } + + fn compute_round_eq_factored(&mut self, round: usize) -> EqFactoredUniPoly { + let coefficients = self.round_q_coefficients(round); EqFactoredUniPoly::from_q_coeffs(coefficients[..=self.degree_bound()].to_vec()) } diff --git a/crates/akita-prover/src/protocol/sumcheck/digit_range/compact_digit_source.rs b/crates/akita-prover/src/protocol/sumcheck/digit_range/compact_digit_source.rs index c01080110..f1877246b 100644 --- a/crates/akita-prover/src/protocol/sumcheck/digit_range/compact_digit_source.rs +++ b/crates/akita-prover/src/protocol/sumcheck/digit_range/compact_digit_source.rs @@ -38,7 +38,7 @@ impl RangeImageClass { /// Ring-switch decomposition owns the balanced-digit invariant. This type checks only /// layout and derives range-image classes without rescanning honest-prover digits. #[derive(Clone)] -pub(super) struct CompactDigitSource { +pub(in crate::protocol::sumcheck) struct CompactDigitSource { digits: Arc<[i8]>, ordered_range_class_pairs: Arc<[u16]>, domain: FlatBooleanDomain, diff --git a/crates/akita-prover/src/protocol/sumcheck/digit_range/exact_prefix.rs b/crates/akita-prover/src/protocol/sumcheck/digit_range/exact_prefix.rs index e7824cbb4..8147cff86 100644 --- a/crates/akita-prover/src/protocol/sumcheck/digit_range/exact_prefix.rs +++ b/crates/akita-prover/src/protocol/sumcheck/digit_range/exact_prefix.rs @@ -3,14 +3,18 @@ use akita_field::{parallel::*, AkitaError, FieldCore}; const EXACT_PREFIX_SEQUENTIAL_LEN: usize = 1 << 12; /// Explicit prefix of a power-of-two table followed by one implicit default value. -pub(super) struct ExactPrefixTable { +pub(in crate::protocol::sumcheck) struct ExactPrefixTable { domain_len: usize, explicit: Vec, default: T, } impl ExactPrefixTable { - pub(super) fn new(domain_len: usize, explicit: Vec, default: T) -> Result { + pub(in crate::protocol::sumcheck) fn new( + domain_len: usize, + explicit: Vec, + default: T, + ) -> Result { if domain_len == 0 || !domain_len.is_power_of_two() { return Err(AkitaError::InvalidInput(format!( "exact-prefix domain length must be a nonzero power of two; got {domain_len}" @@ -29,24 +33,24 @@ impl ExactPrefixTable { }) } - pub(super) fn domain_len(&self) -> usize { + pub(in crate::protocol::sumcheck) fn domain_len(&self) -> usize { self.domain_len } - pub(super) fn explicit_len(&self) -> usize { + pub(in crate::protocol::sumcheck) fn explicit_len(&self) -> usize { self.explicit.len() } - pub(super) fn default_value(&self) -> T { + pub(in crate::protocol::sumcheck) fn default_value(&self) -> T { self.default } #[inline(always)] - pub(super) fn value_or_default(&self, index: usize) -> T { + pub(in crate::protocol::sumcheck) fn value_or_default(&self, index: usize) -> T { self.explicit.get(index).copied().unwrap_or(self.default) } - pub(super) fn fold_in_place( + pub(in crate::protocol::sumcheck) fn fold_in_place( &mut self, fold_pair: impl Fn(T, T) -> T + Sync, ) -> Result<(), AkitaError> @@ -98,7 +102,7 @@ impl ExactPrefixTable { Ok(()) } - pub(super) fn final_value(&self) -> Option { + pub(in crate::protocol::sumcheck) fn final_value(&self) -> Option { (self.domain_len == 1).then(|| self.value_or_default(0)) } } diff --git a/crates/akita-prover/src/protocol/sumcheck/digit_range/mod.rs b/crates/akita-prover/src/protocol/sumcheck/digit_range/mod.rs index 6e2e475a1..12e69c9b2 100644 --- a/crates/akita-prover/src/protocol/sumcheck/digit_range/mod.rs +++ b/crates/akita-prover/src/protocol/sumcheck/digit_range/mod.rs @@ -15,11 +15,11 @@ //! bound. mod class_indexed_product; -mod class_indexed_range_leaf; +pub(in crate::protocol::sumcheck) mod class_indexed_range_leaf; mod class_indexed_state; mod compact_digit_source; pub(crate) mod direct_range_leaf; -mod exact_prefix; +pub(in crate::protocol::sumcheck) mod exact_prefix; mod range_class_tables; mod round_accumulation; use akita_field::unreduced::{HasOptimizedFold, HasUnreducedOps}; @@ -30,7 +30,7 @@ use akita_transcript::labels; use akita_transcript::{sample_ext_challenge, Transcript}; use akita_types::{ append_digit_range_child_claims, AkitaStage1Proof, AkitaStage1StageProof, - DigitRangeEqualityPoint, DigitRangePlan, FlatBooleanDomain, + DigitRangeEqualityPoint, DigitRangePlan, FlatBooleanDomain, PhysicalResponsePlan, }; use class_indexed_product::ClassIndexedProductSubcheckProver; use class_indexed_range_leaf::ClassIndexedRangeLeafProver; @@ -82,6 +82,82 @@ where )) } +struct ProductPrefix { + digit_source: CompactDigitSource, + plan: DigitRangePlan, + leaf_coeffs: Vec>, + stage_proofs: Vec>, + equality_point: Vec, + claim: E, + weights: Vec, +} + +fn prove_product_prefix( + digit_source: CompactDigitSource, + plan: DigitRangePlan, + equality_point: Vec, + transcript: &mut T, +) -> Result, AkitaError> +where + F: FieldCore + CanonicalField, + E: ExtField + FromPrimitiveInt + HasOptimizedFold + HasUnreducedOps + AkitaSerialize, + T: Transcript, +{ + let leaf_coeffs = plan.leaf_coeffs::(); + let mut stage_proofs = Vec::with_capacity(plan.product_stage_arities().len()); + let mut current_equality_point = equality_point; + let mut current_claim = E::zero(); + let mut current_weights = vec![E::one()]; + for (stage_index, &arity) in plan.product_stage_arities().iter().enumerate() { + let lane_count = plan + .product_stage_lane_count(stage_index) + .ok_or(AkitaError::InvalidProof)?; + let _stage_span = tracing::info_span!( + "digit_range_product_substage", + basis = plan.basis(), + stage_index, + arity, + lane_count, + live_len = digit_source.live_len(), + domain_len = digit_source.domain_len(), + ) + .entered(); + let product_input = ProductSubcheckInput { + source: digit_source.clone(), + plan, + leaf_polynomials: &leaf_coeffs, + stage_index, + parent_weights: current_weights, + equality_point: ¤t_equality_point, + input_claim: current_claim, + }; + let (stage_proof, next_equality_point) = match lane_count { + 2 => prove_class_indexed_product_subcheck::(product_input, transcript)?, + 4 => prove_class_indexed_product_subcheck::(product_input, transcript)?, + 8 => prove_class_indexed_product_subcheck::(product_input, transcript)?, + _ => return Err(AkitaError::InvalidProof), + }; + append_digit_range_child_claims::(&stage_proof.child_claims, transcript); + let gamma = sample_ext_challenge::( + transcript, + labels::CHALLENGE_SUMCHECK_INTERSTAGE_BATCH, + ); + current_weights = plan.interstage_batch_weights(gamma, stage_proof.child_claims.len()); + current_claim = plan.batch_claims(¤t_weights, &stage_proof.child_claims)?; + current_equality_point = next_equality_point; + stage_proofs.push(stage_proof); + } + Ok(ProductPrefix { + digit_source, + plan, + leaf_coeffs, + stage_proofs, + equality_point: current_equality_point, + claim: current_claim, + weights: current_weights, + }) +} + fn compose_small_poly_with_affine(coeffs: &[E], offset: E, slope: E) -> [E; 5] { debug_assert!(coeffs.len() <= MAX_TREE_STAGE_Q_DEGREE + 1); let [constant, linear, quadratic, cubic, quartic] = match coeffs { @@ -177,12 +253,18 @@ impl { /// Produce the full stage-1 tree proof and return the final `stage1_point`. + /// An optional physical-response plan adds the scheduled norm identity to + /// the existing final range leaf. /// /// # Errors /// /// Propagates any transcript or sumcheck failure from the internal root /// and leaf-stage proofs. - pub fn prove(self, transcript: &mut T) -> Result, AkitaError> + pub fn prove( + self, + transcript: &mut T, + physical_plan: Option<&PhysicalResponsePlan>, + ) -> Result, AkitaError> where F: FieldCore + CanonicalField, E: ExtField, @@ -202,7 +284,16 @@ impl(); - let mut stage_proofs = Vec::with_capacity(plan.stage_count()); - let mut current_equality_point = equality_point; - let mut current_claim = E::zero(); - let mut current_weights = vec![E::one()]; - - for (stage_index, &arity) in plan.product_stage_arities().iter().enumerate() { - let lane_count = plan - .product_stage_lane_count(stage_index) - .ok_or(AkitaError::InvalidProof)?; - let _stage_span = tracing::info_span!( - "digit_range_product_substage", - basis = plan.basis(), - stage_index, - arity, - lane_count, - live_len = digit_source.live_len(), - domain_len = digit_source.domain_len(), - ) - .entered(); - let product_input = ProductSubcheckInput { - source: digit_source.clone(), - plan, - leaf_polynomials: &leaf_coeffs, - stage_index, - parent_weights: current_weights, - equality_point: ¤t_equality_point, - input_claim: current_claim, - }; - let (stage_proof, next_equality_point) = match lane_count { - 2 => prove_class_indexed_product_subcheck::(product_input, transcript)?, - 4 => prove_class_indexed_product_subcheck::(product_input, transcript)?, - 8 => prove_class_indexed_product_subcheck::(product_input, transcript)?, - _ => return Err(AkitaError::InvalidProof), - }; - let child_claims = &stage_proof.child_claims; - append_digit_range_child_claims::(child_claims, transcript); - let gamma = sample_ext_challenge::( - transcript, - labels::CHALLENGE_SUMCHECK_INTERSTAGE_BATCH, - ); - current_weights = plan.interstage_batch_weights(gamma, child_claims.len()); - current_claim = plan.batch_claims(¤t_weights, child_claims)?; - current_equality_point = next_equality_point; - stage_proofs.push(stage_proof); + let prefix = + prove_product_prefix::(digit_source, plan, equality_point, transcript)?; + let batched_leaf_coeffs = prefix + .plan + .batch_leaf_polynomials(&prefix.weights, &prefix.leaf_coeffs)?; + if let Some(physical_plan) = physical_plan { + let compact_witness = prefix.digit_source.digits(); + let range_leaf = ClassIndexedRangeLeafProver::new( + prefix.digit_source, + &prefix.equality_point, + prefix.claim, + batched_leaf_coeffs, + )?; + let (norm_proof, stage1_point, range_image_evaluation) = + super::physical_l2_norm::prove_physical_l2_norm::( + physical_plan, + compact_witness.as_ref(), + range_leaf, + transcript, + )?; + return Ok(( + AkitaStage1Proof { + stages: prefix.stage_proofs, + range_image_evaluation, + norm_proof: Some(norm_proof), + }, + stage1_point, + )); } - - let batched_leaf_coeffs = plan.batch_leaf_polynomials(¤t_weights, &leaf_coeffs)?; let _leaf_span = tracing::info_span!("digit_range_polynomial_leaf").entered(); let mut leaf_stage = ClassIndexedRangeLeafProver::new( - digit_source, - ¤t_equality_point, - current_claim, + prefix.digit_source, + &prefix.equality_point, + prefix.claim, batched_leaf_coeffs, )?; let (leaf_sumcheck, stage1_point, _leaf_final_claim) = leaf_stage .prove::(transcript, |tr| { sample_ext_challenge::(tr, labels::CHALLENGE_SUMCHECK_ROUND) })?; + let mut stage_proofs = prefix.stage_proofs; stage_proofs.push(AkitaStage1StageProof { sumcheck_proof: leaf_sumcheck, child_claims: Vec::new(), @@ -295,6 +369,7 @@ impl { + Direct { + response: ExactPrefixTable, + }, + LimbGram { + limbs: Vec>, + selectors: Vec>, + pairs: Vec<(usize, usize)>, + }, +} + +impl PhysicalNormTerm { + #[inline(always)] + fn affine_pair(table: &ExactPrefixTable, pair_index: usize) -> (E, E) { + let left = table.value_or_default(2 * pair_index); + (left, table.value_or_default(2 * pair_index + 1) - left) + } + + fn round_coefficients(&self) -> [E; NORM_MAX_DEGREE + 1] { + match self { + Self::Direct { response } => cfg_fold_reduce!( + 0..response.explicit_len().div_ceil(2), + || [E::zero(); NORM_MAX_DEGREE + 1], + |mut sum, pair_index| { + let (value, delta) = Self::affine_pair(response, pair_index); + sum[0] += value * value; + sum[1] += (value + value) * delta; + sum[2] += delta * delta; + sum + }, + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + *left += right; + } + left + } + ), + Self::LimbGram { + limbs, + selectors, + pairs, + } => { + let pair_count = limbs + .first() + .map_or(0, |table| table.explicit_len().div_ceil(2)); + cfg_fold_reduce!( + 0..pair_count, + || [E::zero(); NORM_MAX_DEGREE + 1], + |mut sum, pair_index| { + for (selector, &(left, right)) in selectors.iter().zip(pairs) { + let (selector, selector_delta) = + Self::affine_pair(selector, pair_index); + let (left, left_delta) = Self::affine_pair(&limbs[left], pair_index); + let (right, right_delta) = Self::affine_pair(&limbs[right], pair_index); + let product_constant = left * right; + let product_linear = left * right_delta + left_delta * right; + let product_quadratic = left_delta * right_delta; + sum[0] += selector * product_constant; + sum[1] += selector * product_linear + selector_delta * product_constant; + sum[2] += + selector * product_quadratic + selector_delta * product_linear; + sum[3] += selector_delta * product_quadratic; + } + sum + }, + |mut left, right| { + for (left, right) in left.iter_mut().zip(right) { + *left += right; + } + left + } + ) + } + } + } + + fn bind(&mut self, challenge: E) -> Result<(), AkitaError> { + let context = E::precompute_fold(challenge); + let fold = |left, right| E::fold_one(&context, left, right); + match self { + Self::Direct { response } => response.fold_in_place(fold), + Self::LimbGram { + limbs, selectors, .. + } => { + for table in limbs.iter_mut().chain(selectors) { + table.fold_in_place(fold)?; + } + Ok(()) + } + } + } + + fn virtual_evaluations(&self) -> Result, AkitaError> { + match self { + Self::Direct { response } => response + .final_value() + .map(|value| vec![value]) + .ok_or(AkitaError::InvalidProof), + Self::LimbGram { limbs, .. } => limbs + .iter() + .map(|table| table.final_value().ok_or(AkitaError::InvalidProof)) + .collect(), + } + } + + fn final_claim(&self) -> Result { + match self { + Self::Direct { response } => { + let value = response.final_value().ok_or(AkitaError::InvalidProof)?; + Ok(value * value) + } + Self::LimbGram { + limbs, + selectors, + pairs, + } => selectors.iter().zip(pairs).try_fold( + E::zero(), + |sum, (selector, &(left, right))| { + let selector = selector.final_value().ok_or(AkitaError::InvalidProof)?; + let left = limbs + .get(left) + .and_then(ExactPrefixTable::final_value) + .ok_or(AkitaError::InvalidProof)?; + let right = limbs + .get(right) + .and_then(ExactPrefixTable::final_value) + .ok_or(AkitaError::InvalidProof)?; + Ok(sum + selector * left * right) + }, + ), + } + } +} + +struct FusedRangeNormProver { + range: ClassIndexedRangeLeafProver, + norm: PhysicalNormTerm, + norm_merge: E, + input_claim: E, + rounds_completed: usize, +} + +impl SumcheckInstanceProver + for FusedRangeNormProver +{ + fn num_rounds(&self) -> usize { + EqFactoredSumcheckInstanceProver::num_rounds(&self.range) + } + + fn degree_bound(&self) -> usize { + EqFactoredSumcheckInstanceProver::degree_bound(&self.range) + 1 + } + + fn input_claim(&self) -> E { + self.input_claim + } + + fn compute_round_univariate(&mut self, round: usize, _previous_claim: E) -> UniPoly { + debug_assert_eq!(round, self.rounds_completed); + let q_coefficients = self.range.round_q_coefficients(round); + let (factor_at_zero, factor_at_one) = self.range.current_linear_factor_evals(); + let factor_delta = factor_at_one - factor_at_zero; + let mut coefficients = [E::zero(); FUSED_MAX_DEGREE + 1]; + for (degree, coefficient) in q_coefficients + .into_iter() + .take(EqFactoredSumcheckInstanceProver::degree_bound(&self.range) + 1) + .enumerate() + { + coefficients[degree] += factor_at_zero * coefficient; + coefficients[degree + 1] += factor_delta * coefficient; + } + for (destination, coefficient) in + coefficients.iter_mut().zip(self.norm.round_coefficients()) + { + *destination += self.norm_merge * coefficient; + } + UniPoly::from_coeffs(coefficients[..=self.degree_bound()].to_vec()) + } + + fn ingest_challenge(&mut self, round: usize, challenge: E) { + debug_assert_eq!(round, self.rounds_completed); + self.range.ingest_challenge(round, challenge); + self.norm + .bind(challenge) + .expect("validated physical norm prefix can fold"); + self.rounds_completed += 1; + } +} + +fn exact_claims( + plan: &PhysicalResponsePlan, + integers: &[Vec], +) -> Result<(u128, Vec), AkitaError> { + match plan.shape() { + PhysicalL2NormProofShape::Direct { .. } => { + let response = integers.first().ok_or(AkitaError::InvalidProof)?; + let response_l2_sq = response.iter().try_fold(0u128, |sum, &value| { + let magnitude = value.unsigned_abs(); + sum.checked_add(magnitude.checked_mul(magnitude).ok_or_else(|| { + AkitaError::InvalidInput("physical response square overflow".into()) + })?) + .ok_or_else(|| AkitaError::InvalidInput("physical response norm overflow".into())) + })?; + Ok((response_l2_sq, Vec::new())) + } + shape @ PhysicalL2NormProofShape::LimbGram { .. } => { + let layout = shape.limb_gram_layout()?.ok_or(AkitaError::InvalidProof)?; + let mut integer_claims = Vec::with_capacity(layout.subclaim_count()); + for block in layout.block_ranges() { + for (left, right) in layout.limb_pairs() { + let left_values = integers.get(left).ok_or(AkitaError::InvalidProof)?; + let right_values = integers.get(right).ok_or(AkitaError::InvalidProof)?; + let claim = block.clone().try_fold(0i128, |sum, index| { + let product = left_values + .get(index) + .copied() + .ok_or(AkitaError::InvalidProof)? + .checked_mul( + right_values + .get(index) + .copied() + .ok_or(AkitaError::InvalidProof)?, + ) + .ok_or_else(|| { + AkitaError::InvalidInput("limb product overflow".into()) + })?; + sum.checked_add(product).ok_or_else(|| { + AkitaError::InvalidInput("limb inner product overflow".into()) + }) + })?; + integer_claims.push(claim); + } + } + let response_l2_sq = + reconstruct_l2_sq_from_gram(plan.shape(), plan.fold_basis(), &integer_claims)?; + Ok(( + response_l2_sq, + integer_claims.into_iter().map(E::from_i128).collect(), + )) + } + } +} + +fn prepare_norm_term( + plan: &PhysicalResponsePlan, + integers: Vec>, + subclaim_weights: &[E], +) -> Result, AkitaError> { + let domain_len = plan.domain().domain_len(); + let tables = integers + .into_iter() + .map(|values| { + ExactPrefixTable::new( + domain_len, + values.into_iter().map(E::from_i128).collect(), + E::zero(), + ) + }) + .collect::, _>>()?; + match plan.shape() { + PhysicalL2NormProofShape::Direct { .. } => { + let mut tables = tables.into_iter(); + let response = tables.next().ok_or(AkitaError::InvalidProof)?; + if tables.next().is_some() || !subclaim_weights.is_empty() { + return Err(AkitaError::InvalidProof); + } + Ok(PhysicalNormTerm::Direct { response }) + } + shape @ PhysicalL2NormProofShape::LimbGram { .. } => { + let layout = shape.limb_gram_layout()?.ok_or(AkitaError::InvalidProof)?; + if subclaim_weights.len() != layout.subclaim_count() { + return Err(AkitaError::InvalidSize { + expected: layout.subclaim_count(), + actual: subclaim_weights.len(), + }); + } + let mut selectors = Vec::with_capacity(layout.pair_count()); + for (left, right) in layout.limb_pairs() { + let mut values = Vec::with_capacity(layout.physical_response_len()); + for (block_index, block) in layout.block_ranges().enumerate() { + let weight_index = layout + .subclaim_index(block_index, left, right) + .ok_or(AkitaError::InvalidProof)?; + let weight = *subclaim_weights + .get(weight_index) + .ok_or(AkitaError::InvalidProof)?; + values.resize(block.end, weight); + } + selectors.push(ExactPrefixTable::new(domain_len, values, E::zero())?); + } + Ok(PhysicalNormTerm::LimbGram { + limbs: tables, + selectors, + pairs: layout.limb_pairs().collect(), + }) + } + } +} + +/// Add the scheduled physical norm identity to the existing optimized final +/// range leaf and prove the resulting standard sumcheck. +pub(in crate::protocol::sumcheck) fn prove_physical_l2_norm( + plan: &PhysicalResponsePlan, + compact_witness: &[i8], + range: ClassIndexedRangeLeafProver, + transcript: &mut T, +) -> Result<(PhysicalL2NormProof, Vec, E), AkitaError> +where + F: FieldCore + CanonicalField, + E: ExtField + FromPrimitiveInt + HasOptimizedFold + HasUnreducedOps + AkitaSerialize, + T: Transcript, +{ + if EqFactoredSumcheckInstanceProver::num_rounds(&range) != plan.domain().num_vars() { + return Err(AkitaError::InvalidSetup( + "fused Stage-1 leaf has inconsistent range geometry".into(), + )); + } + let integers = plan.materialize_virtual_integers(compact_witness)?; + let (response_l2_sq, subclaims) = exact_claims::(plan, &integers)?; + transcript.append_serde(ABSORB_L2_NORM_INTEGER, &response_l2_sq); + for claim in &subclaims { + transcript.append_serde(ABSORB_L2_NORM_SUBCLAIM, claim); + } + + let (norm_input_claim, subclaim_weights) = match plan.shape() { + PhysicalL2NormProofShape::Direct { .. } => (E::from_u128(response_l2_sq), Vec::new()), + PhysicalL2NormProofShape::LimbGram { .. } => { + let gamma = sample_ext_challenge::(transcript, CHALLENGE_L2_NORM_BATCH); + let mut power = E::one(); + let mut weights = Vec::with_capacity(subclaims.len()); + let mut claim = E::zero(); + for &subclaim in &subclaims { + weights.push(power); + claim += power * subclaim; + power *= gamma; + } + (claim, weights) + } + }; + let norm = prepare_norm_term(plan, integers, &subclaim_weights)?; + let norm_merge = sample_ext_challenge::(transcript, CHALLENGE_L2_NORM_MERGE); + let range_input_claim = EqFactoredSumcheckInstanceProver::input_claim(&range); + let mut prover = FusedRangeNormProver { + range, + norm, + norm_merge, + input_claim: range_input_claim + norm_merge * norm_input_claim, + rounds_completed: 0, + }; + let (sumcheck, point, final_claim) = prover.prove::(transcript, |tr| { + sample_ext_challenge::(tr, CHALLENGE_SUMCHECK_ROUND) + })?; + let expected_final_claim = + prover.range.final_range_claim() + norm_merge * prover.norm.final_claim()?; + if final_claim != expected_final_claim { + return Err(AkitaError::InvalidInput( + "fused range/norm prover final claim mismatch".into(), + )); + } + let range_image_evaluation = prover.range.final_range_image_eval(); + let virtual_evaluations = prover.norm.virtual_evaluations()?; + for evaluation in &virtual_evaluations { + transcript.append_serde(ABSORB_L2_VIRTUAL_EVALUATION, evaluation); + } + Ok(( + PhysicalL2NormProof { + response_l2_sq, + subclaims, + virtual_evaluations, + sumcheck, + }, + point, + range_image_evaluation, + )) +} diff --git a/crates/akita-prover/src/types/opening_data.rs b/crates/akita-prover/src/types/opening_data.rs index 167bae45c..33bf44df0 100644 --- a/crates/akita-prover/src/types/opening_data.rs +++ b/crates/akita-prover/src/types/opening_data.rs @@ -410,7 +410,10 @@ mod tests { let inner = &pre.inner_commit_matrix; pre.inner_commit_matrix = akita_types::InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("test matrix is L infinity") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), diff --git a/crates/akita-schedules/src/audit.rs b/crates/akita-schedules/src/audit.rs index 604d3a5e6..1ce8f2e2e 100644 --- a/crates/akita-schedules/src/audit.rs +++ b/crates/akita-schedules/src/audit.rs @@ -4,7 +4,8 @@ use akita_field::AkitaError; use akita_types::sis::{ decomposed_t_ring_count, decomposed_w_ring_count, num_digits_inner, num_digits_open, rounded_up_collision_inf_norm, rounded_up_role_a_inf_norm, InnerCommitMatrixParams, - OpenCommitMatrixParams, OuterCommitMatrixParams, SisMatrixRole, SisTableKey, + InnerCommitSecurityRoute, OpenCommitMatrixParams, OuterCommitMatrixParams, SisMatrixRole, + SisTableKey, }; use akita_types::{ shared_d_digit_log_basis, validate_role_dims, CommittedGroupBatchProfile, CommittedGroupParams, @@ -12,6 +13,7 @@ use akita_types::{ TerminalResponseShape, }; +use crate::candidate::{selective_l2_inner_matrix, SelectiveL2CandidateGeometry}; use crate::runtime::validate_policy; use crate::PlannerPolicy; @@ -44,7 +46,23 @@ fn audit_inner_matrix( policy: &PlannerPolicy, ) -> Result<(), AkitaError> { matrix.validate()?; - audit_sis_key(label, matrix.sis_table_key(), SisMatrixRole::Inner, policy) + match matrix.security_route() { + InnerCommitSecurityRoute::Linf(key) => { + audit_sis_key(label, key, SisMatrixRole::Inner, policy) + } + InnerCommitSecurityRoute::L2 { table_key, .. } => { + if table_key.policy != policy.sis_security_policy + || table_key.table_digest != policy.sis_l2_table_digest + || table_key.modulus_profile != policy.sis_modulus_profile + { + return Err(invalid( + label, + "A matrix L2 policy, table, or modulus profile disagrees with catalog policy", + )); + } + Ok(()) + } + } } fn audit_outer_matrix( @@ -110,9 +128,19 @@ fn audit_precommitted_group( )); } + let declared_a_bound = params + .layout + .inner_commit_matrix + .coeff_linf_bound() + .ok_or_else(|| { + invalid( + label, + "precommitted groups cannot use an L2 A security route", + ) + })?; audit_bound( label, - params.layout.inner_commit_matrix.coeff_linf_bound(), + declared_a_bound, rounded_up_role_a_inf_norm( policy.sis_security_policy, policy.sis_table_digest, @@ -121,7 +149,6 @@ fn audit_precommitted_group( params.log_basis_open, ¶ms.fold_challenge_config, params.num_digits_fold, - policy.ring_subfield_norm_bound, ), )?; audit_bound( @@ -165,6 +192,7 @@ fn audit_committed_params( label: &str, params: &CommittedGroupParams, num_claims: usize, + fold_level: usize, policy: &PlannerPolicy, ) -> Result<(), AkitaError> { if num_claims == 0 { @@ -221,20 +249,55 @@ fn audit_committed_params( )); } - audit_bound( - label, - params.inner_commit_matrix.coeff_linf_bound(), - rounded_up_role_a_inf_norm( - policy.sis_security_policy, - policy.sis_table_digest, - policy.sis_modulus_profile, - dims.d_a(), - params.log_basis_open, - ¶ms.fold_challenge_config, - params.num_digits_fold, - policy.ring_subfield_norm_bound, - ), - )?; + match params.inner_commit_matrix.security_route() { + InnerCommitSecurityRoute::Linf(key) => audit_bound( + label, + key.coeff_linf_bound, + rounded_up_role_a_inf_norm( + policy.sis_security_policy, + policy.sis_table_digest, + policy.sis_modulus_profile, + dims.d_a(), + params.log_basis_open, + ¶ms.fold_challenge_config, + params.num_digits_fold, + ), + )?, + InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, .. + } => { + let fold_basis = 1usize + .checked_shl(params.log_basis_open) + .ok_or_else(|| invalid(label, "L2 balanced digit basis overflow"))?; + let expected = selective_l2_inner_matrix( + policy, + SelectiveL2CandidateGeometry { + fold_level, + num_claims, + num_chunks: params.witness_chunk.num_chunks, + inner_width: expected_a_width, + ring_dimension: dims.d_a(), + fold_basis, + fold_digit_count: params.num_digits_fold, + fold_challenge_config: ¶ms.fold_challenge_config, + response_l2_sq_cap: Some(response_l2_sq_cap), + norm_proof_shape: None, + }, + )? + .ok_or_else(|| { + invalid( + label, + "L2 route is not admitted by the frozen suffix response cap", + ) + })?; + if params.inner_commit_matrix != expected { + return Err(invalid( + label, + "L2 A matrix disagrees with canonical cap, proof shape, table, or rank", + )); + } + } + } audit_bound( label, params.outer_commit_matrix.coeff_linf_bound(), @@ -259,10 +322,16 @@ fn audit_committed_params( ) } +#[derive(Clone, Copy)] +struct TerminalL2ModelState { + fold_level: usize, +} + fn audit_terminal( params: &TerminalCommittedGroupParams, sparse: &akita_challenges::SparseChallengeConfig, response_shape: &TerminalResponseShape, + model_state: TerminalL2ModelState, policy: &PlannerPolicy, ) -> Result<(), AkitaError> { let label = "terminal fold"; @@ -270,7 +339,9 @@ fn audit_terminal( sparse .validate_for_ring_dim(params.d_a()) .map_err(|message| invalid(label, message))?; - if params.num_live_ring_elements_per_claim == 0 + if params.fold_log_basis == 0 + || params.fold_digit_count == 0 + || params.num_live_ring_elements_per_claim == 0 || params.num_positions_per_block == 0 || !params.num_positions_per_block.is_power_of_two() || params.num_live_blocks @@ -278,7 +349,7 @@ fn audit_terminal( .num_live_ring_elements_per_claim .div_ceil(params.num_positions_per_block) { - return Err(invalid(label, "invalid terminal block geometry")); + return Err(invalid(label, "invalid terminal fold or block geometry")); } let expected_digits = num_digits_inner( @@ -324,6 +395,46 @@ fn audit_terminal( .checked_add(expected_e_field_elems) .and_then(|value| value.checked_add(expected_t_field_elems)) .ok_or_else(|| invalid(label, "terminal response coordinates overflow"))?; + if matches!( + params.inner_commit_matrix.security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ) { + if akita_challenges::selective_l2_operator_norm_rejection(d, sparse).is_none() { + return Err(invalid(label, "terminal L2 challenge is not certified")); + } + let fold_basis = 1usize + .checked_shl(params.fold_log_basis) + .ok_or_else(|| invalid(label, "L2 balanced digit basis overflow"))?; + let expected = selective_l2_inner_matrix( + policy, + SelectiveL2CandidateGeometry { + fold_level: model_state.fold_level, + num_claims: 1, + num_chunks: 1, + inner_width: expected_width, + ring_dimension: d, + fold_basis, + fold_digit_count: params.fold_digit_count, + fold_challenge_config: sparse, + response_l2_sq_cap: params.response_l2_sq_cap(), + norm_proof_shape: Some(akita_types::PhysicalL2NormProofShape::Direct { + physical_response_len: expected_z_coords, + }), + }, + )? + .ok_or_else(|| { + invalid( + label, + "L2 route is not admitted by the frozen terminal response cap", + ) + })?; + if params.inner_commit_matrix != expected { + return Err(invalid( + label, + "L2 A matrix disagrees with canonical cap, proof shape, table, or rank", + )); + } + } if response_shape.layout.groups.len() != 1 || response_shape.layout.ring_dimension != d || group.z_coords != expected_z_coords @@ -361,6 +472,15 @@ pub(crate) fn audit_resolved_schedule( let root = &schedule.root.params; let final_params = &root.final_group.commitment; + if !matches!( + final_params.inner_commit_matrix.security_route(), + InnerCommitSecurityRoute::Linf(_) + ) { + return Err(invalid( + "root final group", + "root cannot use an L2 A security route", + )); + } if profiles.final_group != akita_types::CommittedGroupProfile::from_params(profiles.final_group.group, final_params) || profiles.precommitteds.len() != root.precommitted_groups.len() @@ -400,6 +520,7 @@ pub(crate) fn audit_resolved_schedule( "root final group", final_params, profiles.final_group.group.num_polynomials(), + 0, policy, )?; for (index, step) in schedule.recursive_folds.iter().enumerate() { @@ -407,6 +528,7 @@ pub(crate) fn audit_resolved_schedule( &format!("recursive fold {index}"), &step.params.witness, 1, + index + 1, policy, )?; if step.params.open_commit_matrix != step.params.witness.open_commit_matrix { @@ -420,6 +542,165 @@ pub(crate) fn audit_resolved_schedule( &schedule.terminal.params.witness, &schedule.terminal.params.sparse_challenge_config, &schedule.terminal.params.response_shape, + TerminalL2ModelState { + fold_level: schedule.recursive_folds.len() + 1, + }, policy, ) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::generated::{ + GeneratedBlockGeometry, GeneratedInnerCommitMatrix, GeneratedTerminalFold, + }; + use crate::{PlannerCostModelId, RingDimensionScheduleMode, SelectionPolicyId}; + use akita_types::{ + ChunkedWitnessCfg, SisL2TableDigest, SisModulusProfileId, SisSecurityPolicyId, + SisTableDigest, + }; + + const INPUT_WITNESS_LEN: usize = 1_024; + const INNER_WIDTH: usize = 16; + const RESPONSE_CAP: u128 = 500_000_000; + fn policy() -> PlannerPolicy { + PlannerPolicy { + cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: crate::SelectiveL2ResponseModelId::Disabled, + selection_policy: SelectionPolicyId::MinEstimatedProofPayload, + recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::Exhaustive, + setup_field_budget: None, + min_offloaded_witness_contraction: 3, + uniform_ring_dimension: 64, + setup_prefix_inner_ring_dimension: 64, + ring_dimension_schedule_mode: RingDimensionScheduleMode::UniformDimension { + ring_dimension: 64, + }, + decomposition: DecompositionParams { + log_basis: 4, + log_commit_bound: 1, + log_open_bound: Some(128), + }, + sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, + sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, + sis_table_digest: SisTableDigest::CURRENT, + sis_l2_table_digest: SisL2TableDigest::CURRENT, + claim_ext_degree: 1, + chal_ext_degree: 1, + inner_basis_range: (3, 16), + opening_basis_range: (3, 6), + witness_chunk: ChunkedWitnessCfg::default(), + recursive_setup_planning: false, + } + } + + #[test] + fn terminal_l2_expansion_and_audit_bind_stored_fold_geometry() { + let policy = policy(); + let sparse = akita_challenges::selective_l2_challenge_config(64) + .expect("certified D64 L2 challenge"); + let expected = selective_l2_inner_matrix( + &policy, + SelectiveL2CandidateGeometry { + fold_level: 3, + num_claims: 1, + num_chunks: 1, + inner_width: INNER_WIDTH, + ring_dimension: 64, + fold_basis: 16, + fold_digit_count: 3, + fold_challenge_config: &sparse, + response_l2_sq_cap: Some(RESPONSE_CAP), + norm_proof_shape: Some(akita_types::PhysicalL2NormProofShape::Direct { + physical_response_len: INNER_WIDTH * 64, + }), + }, + ) + .expect("candidate construction") + .expect("exact terminal calibration"); + let generated = GeneratedTerminalFold { + geometry: GeneratedBlockGeometry { + live_ring_elements_per_claim: 16, + positions_per_block: 16, + live_blocks: 1, + }, + inner_commit_matrix: GeneratedInnerCommitMatrix { + ring_dimension: 64, + log_basis: 4, + }, + num_digits_inner: 1, + fold_log_basis: 4, + fold_digit_count: 3, + inner_output_rank: expected.output_rank() as u32, + inner_coeff_linf_bound: 0, + response_l2_sq_cap: Some(RESPONSE_CAP), + z_admission_linf_cap: 10, + z_rice_low_bits: 1, + z_payload_bytes: 1, + }; + let mut terminal = generated + .expand_to_level_params(&policy, |_| Ok(sparse), 3, INPUT_WITNESS_LEN) + .expect("terminal must use its stored fold geometry"); + let wrong_fold_digits = GeneratedTerminalFold { + fold_digit_count: num_digits_open(DecompositionParams { + log_basis: 4, + ..policy.decomposition + }) as u32, + ..generated + }; + let expanded_wrong_fold_digits = wrong_fold_digits + .expand_to_level_params(&policy, |_| Ok(sparse), 3, INPUT_WITNESS_LEN) + .expect("frozen cap expansion must preserve stored fold digits"); + assert_eq!( + expanded_wrong_fold_digits.fold_digit_count, + wrong_fold_digits.fold_digit_count as usize + ); + assert_ne!( + expanded_wrong_fold_digits.fold_digit_count, + terminal.fold_digit_count + ); + let wrong_fold_basis = GeneratedTerminalFold { + fold_log_basis: 3, + ..generated + }; + assert!(wrong_fold_basis + .expand_to_level_params(&policy, |_| Ok(sparse), 3, INPUT_WITNESS_LEN) + .is_err()); + + let response_shape = + TerminalResponseShape::derive(&terminal, 10).expect("valid terminal response shape"); + audit_terminal( + &terminal, + &sparse, + &response_shape, + TerminalL2ModelState { fold_level: 3 }, + &policy, + ) + .expect("canonical terminal matrix"); + + let (table_key, norm_proof_shape) = match terminal.inner_commit_matrix.security_route() { + InnerCommitSecurityRoute::L2 { + table_key, + norm_proof_shape, + .. + } => (table_key, norm_proof_shape), + InnerCommitSecurityRoute::Linf(_) => panic!("expected L2 terminal"), + }; + terminal.inner_commit_matrix = InnerCommitMatrixParams::try_new_l2_with_min_rank( + table_key, + INNER_WIDTH, + RESPONSE_CAP * 16, + norm_proof_shape, + ) + .expect("locally well-formed matrix with a stale table bucket"); + assert!(audit_terminal( + &terminal, + &sparse, + &response_shape, + TerminalL2ModelState { fold_level: 3 }, + &policy, + ) + .is_err()); + } +} diff --git a/crates/akita-schedules/src/candidate.rs b/crates/akita-schedules/src/candidate.rs index dc4092648..0c08649da 100644 --- a/crates/akita-schedules/src/candidate.rs +++ b/crates/akita-schedules/src/candidate.rs @@ -1,8 +1,99 @@ //! Shared candidate-construction helpers. use crate::runtime::PlannerPolicy; -use akita_types::sis::{projected_role_ring_count, rounded_up_collision_inf_norm, SisTableKey}; -use akita_types::SisMatrixRole; +use akita_challenges::SparseChallengeConfig; +use akita_field::AkitaError; +use akita_types::sis::{ + min_secure_l2_rank, projected_role_ring_count, role_a_collision_l2_sq_for_response_bound, + rounded_up_collision_inf_norm, sis_l2_table_key_for_collision_sq, FoldChallengeNorms, + SisTableKey, +}; +use akita_types::{InnerCommitMatrixParams, PhysicalL2NormProofShape, SisMatrixRole}; + +/// Exact public geometry that may admit one selective physical-L2 A matrix. +#[derive(Clone, Copy, Debug)] +pub struct SelectiveL2CandidateGeometry<'a> { + pub fold_level: usize, + pub num_claims: usize, + pub num_chunks: usize, + pub inner_width: usize, + pub ring_dimension: usize, + pub fold_basis: usize, + pub fold_digit_count: usize, + pub fold_challenge_config: &'a SparseChallengeConfig, + /// Planner-frozen response cap. Generated schedule expansion and resolved + /// schedule audit replay this exact public value instead of rerunning an + /// offline response model. + pub response_l2_sq_cap: Option, + /// Override the recursive proof shape when the response is checked in the + /// clear, as it is at the terminal boundary. + pub norm_proof_shape: Option, +} + +/// Derive the one canonical L2 A-matrix candidate for an exact fold geometry. +pub fn selective_l2_inner_matrix( + policy: &PlannerPolicy, + geometry: SelectiveL2CandidateGeometry<'_>, +) -> Result, AkitaError> { + // The physical-L2 route is validated end to end only for + // response bases 16 and above. Basis 8 reaches a different stage-2 + // geometry and is not an eligible planning candidate. + if geometry.fold_level < 3 + || geometry.num_claims != 1 + || geometry.num_chunks != 1 + || geometry.fold_basis < 16 + { + return Ok(None); + } + let physical_response_len = geometry + .inner_width + .checked_mul(geometry.ring_dimension) + .ok_or_else(|| AkitaError::InvalidSetup("L2 physical response length overflow".into()))?; + let Some(response_l2_sq_cap) = geometry.response_l2_sq_cap else { + return Ok(None); + }; + let norm_proof_shape = match geometry.norm_proof_shape { + Some(shape) => shape, + None => PhysicalL2NormProofShape::derive( + policy.sis_modulus_profile, + physical_response_len, + geometry.fold_basis, + geometry.fold_digit_count, + )?, + }; + let challenge_mass = akita_challenges::selective_l2_operator_norm_rejection( + geometry.ring_dimension, + geometry.fold_challenge_config, + ) + .map_or_else( + || FoldChallengeNorms::new(geometry.fold_challenge_config).l1_norm, + |rejection| u128::from(rejection.threshold), + ); + let collision_l2_sq = + role_a_collision_l2_sq_for_response_bound(challenge_mass, response_l2_sq_cap) + .ok_or_else(|| AkitaError::InvalidSetup("L2 collision bound overflow".into()))?; + let Some(table_key) = sis_l2_table_key_for_collision_sq( + policy.sis_security_policy, + policy.sis_l2_table_digest, + policy.sis_modulus_profile, + geometry.ring_dimension as u32, + collision_l2_sq, + ) else { + return Ok(None); + }; + let width = u64::try_from(geometry.inner_width) + .map_err(|_| AkitaError::InvalidSetup("L2 A matrix input width exceeds u64".into()))?; + if min_secure_l2_rank(table_key, width).is_none() { + return Ok(None); + } + InnerCommitMatrixParams::try_new_l2_with_min_rank( + table_key, + geometry.inner_width, + response_l2_sq_cap, + norm_proof_shape, + ) + .map(Some) +} /// Construct the canonical SIS-table key for one role and ring dimension. pub fn sis_key_at_dimension( @@ -50,3 +141,158 @@ pub fn projected_collision_role_price( physical_width, )) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{PlannerCostModelId, SelectionPolicyId}; + use akita_types::{ + ChunkedWitnessCfg, DecompositionParams, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, + }; + + #[test] + fn missing_l2_rank_is_an_ineligible_candidate() { + const INNER_WIDTH: usize = 6_400_000_000_001; + const RING_DIMENSION: usize = 64; + let policy = PlannerPolicy { + cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: crate::SelectiveL2ResponseModelId::Disabled, + selection_policy: SelectionPolicyId::MinEstimatedProofPayload, + recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::Exhaustive, + setup_field_budget: None, + min_offloaded_witness_contraction: 1, + uniform_ring_dimension: RING_DIMENSION, + setup_prefix_inner_ring_dimension: RING_DIMENSION, + ring_dimension_schedule_mode: crate::RingDimensionScheduleMode::UniformDimension { + ring_dimension: RING_DIMENSION, + }, + decomposition: DecompositionParams { + log_basis: 1, + log_commit_bound: 1, + log_open_bound: Some(1), + }, + sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, + sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, + sis_table_digest: SisTableDigest::CURRENT, + sis_l2_table_digest: SisL2TableDigest::CURRENT, + claim_ext_degree: 1, + chal_ext_degree: 1, + inner_basis_range: (1, 1), + opening_basis_range: (1, 1), + witness_chunk: ChunkedWitnessCfg::default(), + recursive_setup_planning: false, + }; + let challenge = akita_challenges::D64_SELECTIVE_L2_CHALLENGE_CONFIG; + + let candidate = selective_l2_inner_matrix( + &policy, + SelectiveL2CandidateGeometry { + fold_level: 3, + num_claims: 1, + num_chunks: 1, + inner_width: INNER_WIDTH, + ring_dimension: RING_DIMENSION, + fold_basis: 16, + fold_digit_count: 3, + fold_challenge_config: &challenge, + response_l2_sq_cap: Some(1), + norm_proof_shape: None, + }, + ) + .expect("unsupported L2 rank must not abort the L-infinity frontier"); + + assert!(candidate.is_none()); + } + + #[test] + fn d128_l2_candidate_prices_the_certified_operator_threshold() { + const INNER_WIDTH: usize = 128; + const RING_DIMENSION: usize = 128; + const RESPONSE_CAP: u128 = 1 << 20; + let policy = PlannerPolicy { + cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: crate::SelectiveL2ResponseModelId::Disabled, + selection_policy: SelectionPolicyId::MinEstimatedProofPayload, + recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::Exhaustive, + setup_field_budget: None, + min_offloaded_witness_contraction: 1, + uniform_ring_dimension: RING_DIMENSION, + setup_prefix_inner_ring_dimension: RING_DIMENSION, + ring_dimension_schedule_mode: crate::RingDimensionScheduleMode::UniformDimension { + ring_dimension: RING_DIMENSION, + }, + decomposition: DecompositionParams { + log_basis: 4, + log_commit_bound: 128, + log_open_bound: None, + }, + sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, + sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, + sis_table_digest: SisTableDigest::CURRENT, + sis_l2_table_digest: SisL2TableDigest::CURRENT, + claim_ext_degree: 1, + chal_ext_degree: 1, + inner_basis_range: (4, 4), + opening_basis_range: (4, 4), + witness_chunk: ChunkedWitnessCfg::default(), + recursive_setup_planning: false, + }; + let challenge = akita_challenges::D128_SELECTIVE_L2_CHALLENGE_CONFIG; + let basis_eight = selective_l2_inner_matrix( + &policy, + SelectiveL2CandidateGeometry { + fold_level: 3, + num_claims: 1, + num_chunks: 1, + inner_width: INNER_WIDTH, + ring_dimension: RING_DIMENSION, + fold_basis: 8, + fold_digit_count: 4, + fold_challenge_config: &challenge, + response_l2_sq_cap: Some(RESPONSE_CAP), + norm_proof_shape: None, + }, + ) + .expect("basis-eight eligibility check"); + assert!(basis_eight.is_none()); + let candidate = selective_l2_inner_matrix( + &policy, + SelectiveL2CandidateGeometry { + fold_level: 3, + num_claims: 1, + num_chunks: 1, + inner_width: INNER_WIDTH, + ring_dimension: RING_DIMENSION, + fold_basis: 16, + fold_digit_count: 3, + fold_challenge_config: &challenge, + response_l2_sq_cap: Some(RESPONSE_CAP), + norm_proof_shape: None, + }, + ) + .expect("D128 L2 candidate") + .expect("D128 L2 table coverage"); + let akita_types::InnerCommitSecurityRoute::L2 { table_key, .. } = + candidate.security_route() + else { + panic!("expected L2 route") + }; + let exact_collision = role_a_collision_l2_sq_for_response_bound( + u128::from(akita_challenges::OperatorNormRejection::D128_SELECTIVE_L2.threshold), + RESPONSE_CAP, + ) + .expect("collision bound"); + assert_eq!( + table_key.collision_l2_sq, + exact_collision.next_power_of_two() + ); + + let l1_collision = role_a_collision_l2_sq_for_response_bound( + FoldChallengeNorms::new(&challenge).l1_norm, + RESPONSE_CAP, + ) + .expect("L1 collision bound"); + assert!(table_key.collision_l2_sq < l1_collision.next_power_of_two()); + } +} diff --git a/crates/akita-schedules/src/catalog_identity.rs b/crates/akita-schedules/src/catalog_identity.rs index d3d192ae4..7cda3c063 100644 --- a/crates/akita-schedules/src/catalog_identity.rs +++ b/crates/akita-schedules/src/catalog_identity.rs @@ -46,11 +46,12 @@ pub fn policy_digest(policy: &PlannerPolicy) -> [u8; 32] { h.write_u64(sis_modulus_profile_tag(policy.sis_modulus_profile)); h.write_u64(u64::from(policy.sis_security_policy.tag())); h.write_bytes(&policy.sis_table_digest.0); + h.write_bytes(&policy.sis_l2_table_digest.0); + h.write_u64(u64::from(policy.selective_l2_response_model.tag())); h.write_u64(policy.uniform_ring_dimension as u64); h.write_u64(policy.setup_prefix_inner_ring_dimension as u64); write_ring_dimension_schedule_mode(&mut h, policy.ring_dimension_schedule_mode); write_decomposition(&mut h, policy.decomposition); - h.write_u64(u64::from(policy.ring_subfield_norm_bound)); h.write_u64(policy.claim_ext_degree as u64); h.write_u64(policy.chal_ext_degree as u64); h.write_u64(u64::from(policy.inner_basis_range.0)); @@ -79,10 +80,11 @@ pub fn identity_digest(identity: &GeneratedScheduleCatalogIdentity) -> [u8; 32] h.write_u64(sis_modulus_profile_tag(identity.sis_modulus_profile)); h.write_u64(u64::from(identity.sis_security_policy.tag())); h.write_bytes(&identity.sis_table_digest.0); + h.write_bytes(&identity.sis_l2_table_digest.0); + h.write_u64(u64::from(identity.selective_l2_response_model.tag())); h.write_u64(identity.uniform_ring_dimension as u64); h.write_u64(identity.setup_prefix_inner_ring_dimension as u64); write_decomposition(&mut h, identity.decomposition); - h.write_u64(u64::from(identity.ring_subfield_norm_bound)); h.write_u64(identity.claim_ext_degree as u64); h.write_u64(identity.chal_ext_degree as u64); h.write_u64(u64::from(identity.inner_basis_range.0)); @@ -130,6 +132,7 @@ struct CatalogIdentityExpectation { family_name: &'static str, protocol_epoch: u32, cost_model: crate::PlannerCostModelId, + selective_l2_response_model: crate::SelectiveL2ResponseModelId, selection_policy: crate::SelectionPolicyId, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy, setup_field_budget: Option, @@ -137,10 +140,10 @@ struct CatalogIdentityExpectation { sis_modulus_profile: akita_types::SisModulusProfileId, sis_security_policy: akita_types::SisSecurityPolicyId, sis_table_digest: akita_types::SisTableDigest, + sis_l2_table_digest: akita_types::SisL2TableDigest, uniform_ring_dimension: usize, setup_prefix_inner_ring_dimension: usize, decomposition: akita_types::DecompositionParams, - ring_subfield_norm_bound: u32, claim_ext_degree: usize, chal_ext_degree: usize, inner_basis_range: (u32, u32), @@ -162,6 +165,7 @@ impl CatalogIdentityExpectation { family_name: identity.family_name, protocol_epoch: identity.protocol_epoch, cost_model: identity.cost_model, + selective_l2_response_model: identity.selective_l2_response_model, selection_policy: identity.selection_policy, recursive_split_search_policy: identity.recursive_split_search_policy, setup_field_budget: identity.setup_field_budget, @@ -169,10 +173,10 @@ impl CatalogIdentityExpectation { sis_modulus_profile: identity.sis_modulus_profile, sis_security_policy: identity.sis_security_policy, sis_table_digest: identity.sis_table_digest, + sis_l2_table_digest: identity.sis_l2_table_digest, uniform_ring_dimension: identity.uniform_ring_dimension, setup_prefix_inner_ring_dimension: identity.setup_prefix_inner_ring_dimension, decomposition: identity.decomposition, - ring_subfield_norm_bound: identity.ring_subfield_norm_bound, claim_ext_degree: identity.claim_ext_degree, chal_ext_degree: identity.chal_ext_degree, inner_basis_range: identity.inner_basis_range, @@ -208,6 +212,7 @@ fn catalog_identity_expectation( family_name, protocol_epoch: AKITA_INSTANCE_DESCRIPTOR_VERSION, cost_model: policy.cost_model, + selective_l2_response_model: policy.selective_l2_response_model, selection_policy: policy.selection_policy, recursive_split_search_policy: policy.recursive_split_search_policy, setup_field_budget: policy.setup_field_budget, @@ -215,10 +220,10 @@ fn catalog_identity_expectation( sis_modulus_profile: policy.sis_modulus_profile, sis_security_policy: policy.sis_security_policy, sis_table_digest: policy.sis_table_digest, + sis_l2_table_digest: policy.sis_l2_table_digest, uniform_ring_dimension: policy.uniform_ring_dimension, setup_prefix_inner_ring_dimension: policy.setup_prefix_inner_ring_dimension, decomposition: policy.decomposition, - ring_subfield_norm_bound: policy.ring_subfield_norm_bound, claim_ext_degree: policy.claim_ext_degree, chal_ext_degree: policy.chal_ext_degree, inner_basis_range: policy.inner_basis_range, @@ -248,6 +253,7 @@ pub fn expected_catalog_identity( family_name: expected.family_name, protocol_epoch: expected.protocol_epoch, cost_model: expected.cost_model, + selective_l2_response_model: expected.selective_l2_response_model, selection_policy: expected.selection_policy, recursive_split_search_policy: expected.recursive_split_search_policy, setup_field_budget: expected.setup_field_budget, @@ -255,10 +261,10 @@ pub fn expected_catalog_identity( sis_modulus_profile: expected.sis_modulus_profile, sis_security_policy: expected.sis_security_policy, sis_table_digest: expected.sis_table_digest, + sis_l2_table_digest: expected.sis_l2_table_digest, uniform_ring_dimension: expected.uniform_ring_dimension, setup_prefix_inner_ring_dimension: expected.setup_prefix_inner_ring_dimension, decomposition: expected.decomposition, - ring_subfield_norm_bound: expected.ring_subfield_norm_bound, claim_ext_degree: expected.claim_ext_degree, chal_ext_degree: expected.chal_ext_degree, inner_basis_range: expected.inner_basis_range, @@ -557,6 +563,8 @@ fn entries_key_digest(entries: &[GeneratedFoldScheduleEntry]) -> u64 { write_generated_geometry(&mut h, entry.terminal.geometry); h.write_u64(u64::from(entry.terminal.inner_commit_matrix.ring_dimension)); h.write_u64(u64::from(entry.terminal.inner_commit_matrix.log_basis)); + h.write_u64(u64::from(entry.terminal.fold_log_basis)); + h.write_u64(u64::from(entry.terminal.fold_digit_count)); } h.finish() } diff --git a/crates/akita-schedules/src/generated/expand.rs b/crates/akita-schedules/src/generated/expand.rs index ea1373cbe..c538aa8d9 100644 --- a/crates/akita-schedules/src/generated/expand.rs +++ b/crates/akita-schedules/src/generated/expand.rs @@ -13,6 +13,7 @@ use akita_challenges::SparseChallengeConfig; use akita_field::AkitaError; +use crate::candidate::{selective_l2_inner_matrix, SelectiveL2CandidateGeometry}; use crate::generated::{ GeneratedCommittedGroup, GeneratedFoldScheduleEntry, GeneratedOpenCommitMatrix, GeneratedPrecommittedProfile, GeneratedSetupPrefixInput, GeneratedTerminalFold, @@ -156,7 +157,6 @@ impl GeneratedSetupPrefixInput { log_basis_open, &ring_challenge_cfg, num_digits_fold, - policy.ring_subfield_norm_bound, ) .ok_or_else(|| no_layout("A"))?; let n_a = secure_rank( @@ -366,6 +366,7 @@ impl GeneratedCommittedGroup { fold_level: usize, exact_num_digits_inner: Option, generated_num_digits_fold: u32, + response_l2_sq_cap: Option, input_witness_len: usize, num_claims: usize, open_commit_matrix: GeneratedOpenCommitMatrix, @@ -445,7 +446,12 @@ impl GeneratedCommittedGroup { log_basis: log_basis_open, ..policy.decomposition }; - let ring_challenge_cfg = ring_challenge_config(ring_d)?; + let ring_challenge_cfg = if response_l2_sq_cap.is_some() { + akita_challenges::selective_l2_challenge_config(ring_d) + .unwrap_or(ring_challenge_config(ring_d)?) + } else { + ring_challenge_config(ring_d)? + }; let num_digits_inner = if let Some(num_digits_inner) = exact_num_digits_inner { usize::try_from(num_digits_inner).map_err(|_| { AkitaError::InvalidSetup( @@ -478,10 +484,9 @@ impl GeneratedCommittedGroup { log_basis_open, &ring_challenge_cfg, num_digits_fold, - policy.ring_subfield_norm_bound, ) .ok_or_else(|| no_layout("A"))?; - let n_a = secure_rank( + let linf_n_a = secure_rank( "a", sis_key( policy, @@ -491,6 +496,54 @@ impl GeneratedCommittedGroup { ), inner_width, )?; + let inner_commit_matrix = if let Some(response_l2_sq_cap) = response_l2_sq_cap { + let fold_basis = 1usize + .checked_shl(log_basis_open) + .ok_or_else(|| AkitaError::InvalidSetup("generated L2 basis overflow".into()))?; + let matrix = selective_l2_inner_matrix( + policy, + SelectiveL2CandidateGeometry { + fold_level, + num_claims, + num_chunks: policy.chunks_at_level(fold_level), + inner_width, + ring_dimension: ring_d, + fold_basis, + fold_digit_count: num_digits_fold, + fold_challenge_config: &ring_challenge_cfg, + response_l2_sq_cap: Some(response_l2_sq_cap), + norm_proof_shape: None, + }, + )? + .ok_or_else(|| { + AkitaError::InvalidSetup( + "generated L2 route is not admitted by the calibrated response model".into(), + ) + })?; + if !matches!( + matrix.security_route(), + akita_types::InnerCommitSecurityRoute::L2 { + response_l2_sq_cap: canonical_cap, + .. + } if canonical_cap == response_l2_sq_cap + ) { + return Err(AkitaError::InvalidSetup( + "generated L2 cap disagrees with canonical candidate policy".into(), + )); + } + matrix + } else { + InnerCommitMatrixParams::try_new( + sis_policy, + policy.sis_table_digest, + sis_modulus_profile, + linf_n_a, + inner_width, + a_bucket, + ring_d, + )? + }; + let n_a = inner_commit_matrix.output_rank(); let b_bucket = rounded_up_collision_inf_norm( sis_policy, @@ -586,15 +639,7 @@ impl GeneratedCommittedGroup { log_basis_inner, log_basis_outer, log_basis_open, - inner_commit_matrix: InnerCommitMatrixParams::try_new( - sis_policy, - policy.sis_table_digest, - sis_modulus_profile, - n_a, - inner_width, - a_bucket, - ring_d, - )?, + inner_commit_matrix, outer_commit_matrix: OuterCommitMatrixParams::try_new( sis_policy, policy.sis_table_digest, @@ -722,7 +767,6 @@ impl GeneratedCommittedGroup { log_basis_open, &ring_challenge_cfg, num_digits_fold, - policy.ring_subfield_norm_bound, ) .ok_or_else(|| no_layout("A"))?; let n_a = secure_rank( @@ -849,7 +893,7 @@ impl GeneratedTerminalFold { &self, policy: &PlannerPolicy, ring_challenge_config: impl Fn(usize) -> Result, - _fold_level: usize, + fold_level: usize, input_witness_len: usize, ) -> Result { let ring_dimension = self.inner_commit_matrix.ring_dimension as usize; @@ -891,30 +935,99 @@ impl GeneratedTerminalFold { "generated terminal inner digit depth must be nonzero".into(), )); } + let fold_digit_count = usize::try_from(self.fold_digit_count).map_err(|_| { + AkitaError::InvalidSetup( + "generated terminal fold digit count does not fit the target platform".into(), + ) + })?; + if self.fold_log_basis == 0 || fold_digit_count == 0 { + return Err(AkitaError::InvalidSetup( + "generated terminal fold basis and digit count must be nonzero".into(), + )); + } let inner_width = decomposed_s_block_ring_count(num_positions_per_block, num_digits_inner) .ok_or_else(|| AkitaError::InvalidSetup("terminal A width overflow".to_string()))?; - let sparse = ring_challenge_config(ring_dimension)?; + let sparse = if self.response_l2_sq_cap.is_some() { + akita_challenges::selective_l2_challenge_config(ring_dimension).ok_or_else(|| { + AkitaError::InvalidSetup( + "generated terminal L2 route has no certified operator-norm challenge".into(), + ) + })? + } else { + ring_challenge_config(ring_dimension)? + }; let output_rank = usize::try_from(self.inner_output_rank).map_err(|_| { AkitaError::InvalidSetup( "generated terminal inner rank does not fit the target platform".into(), ) })?; - if output_rank == 0 || self.inner_coeff_linf_bound == 0 { + if output_rank == 0 + || (self.response_l2_sq_cap.is_none() && self.inner_coeff_linf_bound == 0) + { return Err(AkitaError::InvalidSetup( "generated terminal matrix contract must be nonzero".into(), )); } - let inner_commit_matrix = InnerCommitMatrixParams::try_new( - policy.sis_security_policy, - policy.sis_table_digest, - policy.sis_modulus_profile, - output_rank, - inner_width, - self.inner_coeff_linf_bound, - ring_dimension, - )?; + let inner_commit_matrix = if let Some(response_l2_sq_cap) = self.response_l2_sq_cap { + let fold_basis = 1usize + .checked_shl(self.fold_log_basis) + .ok_or_else(|| AkitaError::InvalidSetup("terminal L2 basis overflow".into()))?; + let matrix = selective_l2_inner_matrix( + policy, + SelectiveL2CandidateGeometry { + fold_level, + num_claims: 1, + num_chunks: 1, + inner_width, + ring_dimension, + fold_basis, + fold_digit_count, + fold_challenge_config: &sparse, + response_l2_sq_cap: Some(response_l2_sq_cap), + norm_proof_shape: Some(akita_types::PhysicalL2NormProofShape::Direct { + physical_response_len: inner_width.checked_mul(ring_dimension).ok_or_else( + || { + AkitaError::InvalidSetup( + "terminal L2 response length overflow".into(), + ) + }, + )?, + }), + }, + )? + .ok_or_else(|| { + AkitaError::InvalidSetup( + "generated terminal L2 route has no canonical source model".into(), + ) + })?; + let cap_matches = matches!( + matrix.security_route(), + akita_types::InnerCommitSecurityRoute::L2 { + response_l2_sq_cap: cap, + .. + } if cap == response_l2_sq_cap + ); + if matrix.output_rank() != output_rank || !cap_matches { + return Err(AkitaError::InvalidSetup( + "generated terminal L2 matrix disagrees with its canonical source model".into(), + )); + } + matrix + } else { + InnerCommitMatrixParams::try_new( + policy.sis_security_policy, + policy.sis_table_digest, + policy.sis_modulus_profile, + output_rank, + inner_width, + self.inner_coeff_linf_bound, + ring_dimension, + )? + }; let terminal = TerminalCommittedGroupParams { log_basis_inner, + fold_log_basis: self.fold_log_basis, + fold_digit_count, inner_commit_matrix, num_live_ring_elements_per_claim, num_positions_per_block, @@ -968,6 +1081,7 @@ mod tests { fn recursive_fp128_policy() -> PlannerPolicy { PlannerPolicy { cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: crate::SelectiveL2ResponseModelId::Disabled, selection_policy: SelectionPolicyId::MinFirstDirectSetupThenPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::Exhaustive, setup_field_budget: None, @@ -985,7 +1099,7 @@ mod tests { sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest::CURRENT, - ring_subfield_norm_bound: 1, + sis_l2_table_digest: akita_types::SisL2TableDigest::CURRENT, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 16), diff --git a/crates/akita-schedules/src/generated/fp128_dense.rs b/crates/akita-schedules/src/generated/fp128_dense.rs index 3a9eafcd9..39766fa4e 100644 --- a/crates/akita-schedules/src/generated/fp128_dense.rs +++ b/crates/akita-schedules/src/generated/fp128_dense.rs @@ -8,25 +8,26 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ GeneratedFoldScheduleEntry { root: GeneratedRootFold { - final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(14, 1), num_digits_inner: 22, num_digits_fold: 4, - commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 64, positions_per_block: 8, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } } }, + final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(14, 1), num_digits_inner: 26, num_digits_fold: 4, + commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 64, positions_per_block: 8, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } } }, precommitted_groups: &[], open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6351, positions_per_block: 512, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3236, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2096, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3432, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5575, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2976, positions_per_block: 512, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(944489104), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2498, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(719099659), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -37,12 +38,12 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6472, positions_per_block: 512, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7123, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3366, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2124, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6472, positions_per_block: 512, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7123, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4824, positions_per_block: 512, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(434679645), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3352, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(284420015), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(633237013), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -53,28 +54,28 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5700, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11055, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4000, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11400, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9937, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5592, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(423946814), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { - final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(17, 4), num_digits_inner: 19, num_digits_fold: 5, - commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 7 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } } }, + final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(17, 4), num_digits_inner: 12, num_digits_fold: 6, + commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 11 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } } }, precommitted_groups: &[], open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 41787, positions_per_block: 2048, live_blocks: 21 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10776, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 35899, positions_per_block: 2048, live_blocks: 18 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10200, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5592, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -85,13 +86,13 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 226747, positions_per_block: 4096, live_blocks: 56 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 31529, positions_per_block: 1024, live_blocks: 31 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9624, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3881, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 226747, positions_per_block: 4096, live_blocks: 56 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 31529, positions_per_block: 1024, live_blocks: 31 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 12791, positions_per_block: 1024, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(311252091), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5272, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(407847568), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(297836053), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -102,13 +103,13 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 501691, positions_per_block: 4096, live_blocks: 123 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 48815, positions_per_block: 2048, live_blocks: 24 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7738, positions_per_block: 1024, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3617, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 501691, positions_per_block: 4096, live_blocks: 123 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 48815, positions_per_block: 2048, live_blocks: 24 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 15081, positions_per_block: 1024, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(330034545), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5528, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(440046060), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -119,13 +120,13 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1002427, positions_per_block: 8192, live_blocks: 123 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 65199, positions_per_block: 4096, live_blocks: 16 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10794, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1002427, positions_per_block: 8192, live_blocks: 123 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 48792, positions_per_block: 2048, live_blocks: 24 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11352, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1019618919), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -136,14 +137,13 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2102203, positions_per_block: 8192, live_blocks: 257 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 99771, positions_per_block: 2048, live_blocks: 49 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 21531, positions_per_block: 1024, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10469, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4000, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2102203, positions_per_block: 8192, live_blocks: 257 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 99771, positions_per_block: 2048, live_blocks: 49 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 21531, positions_per_block: 1024, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(531275121), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6424, positions_per_block: 512, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(563473613), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3392, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(327351337), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -154,33 +154,31 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4203622, positions_per_block: 16384, live_blocks: 257 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 132539, positions_per_block: 4096, live_blocks: 33 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 25595, positions_per_block: 1024, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11243, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4000, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4203622, positions_per_block: 16384, live_blocks: 257 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 132539, positions_per_block: 4096, live_blocks: 33 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 25595, positions_per_block: 1024, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(547374367), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6808, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(606404936), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3520, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(340767376), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { - final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(44, 1), num_digits_inner: 43, num_digits_fold: 6, - commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 68719476736, positions_per_block: 262144, live_blocks: 262144 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } } }, + final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(44, 1), num_digits_inner: 32, num_digits_fold: 6, + commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 68719476736, positions_per_block: 262144, live_blocks: 262144 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } } }, precommitted_groups: &[], open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 450889149, positions_per_block: 131072, live_blocks: 3441 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 5, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1840018, positions_per_block: 8192, live_blocks: 225 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 91515, positions_per_block: 2048, live_blocks: 45 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 20499, positions_per_block: 1024, live_blocks: 21 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10211, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3870, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 381683133, positions_per_block: 131072, live_blocks: 2913 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 5, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1658386, positions_per_block: 8192, live_blocks: 203 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 64152, positions_per_block: 2048, live_blocks: 32 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(6353835787), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11832, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1084015903), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -191,15 +189,14 @@ pub(crate) static FP128_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3607102909, positions_per_block: 524288, live_blocks: 6881 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 5, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4989458, positions_per_block: 16384, live_blocks: 305 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 144923, positions_per_block: 4096, live_blocks: 36 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 26369, positions_per_block: 1024, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5950, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3956, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3607102909, positions_per_block: 524288, live_blocks: 6881 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 5, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4989458, positions_per_block: 16384, live_blocks: 305 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 144923, positions_per_block: 4096, live_blocks: 36 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 26369, positions_per_block: 1024, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(574206444), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6936, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(622504182), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3520, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(340767376), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -218,6 +215,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_dense", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -225,10 +223,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 128, log_open_bound: None }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -239,5 +237,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 11, - key_digest: 5668780911062700539, + key_digest: 438345492401275134, }; diff --git a/crates/akita-schedules/src/generated/fp128_dense_multi_chunk.rs b/crates/akita-schedules/src/generated/fp128_dense_multi_chunk.rs index f96c903b3..e7d558820 100644 --- a/crates/akita-schedules/src/generated/fp128_dense_multi_chunk.rs +++ b/crates/akita-schedules/src/generated/fp128_dense_multi_chunk.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -22,13 +23,13 @@ pub(crate) static FP128_DENSE_MULTI_CHUNK_SCHEDULES: &[GeneratedFoldScheduleEntr witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9604, positions_per_block: 256, live_blocks: 38 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 24888, positions_per_block: 1024, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5861, positions_per_block: 1024, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3353, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2124, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9604, positions_per_block: 256, live_blocks: 38 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 24888, positions_per_block: 1024, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5861, positions_per_block: 1024, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3353, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2461, positions_per_block: 512, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(2919329956), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1728, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -47,6 +48,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_dense_multi_chunk", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -54,10 +56,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 128, log_open_bound: None }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -68,5 +70,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 1, - key_digest: 2223761945083775517, + key_digest: 1882502595964671658, }; diff --git a/crates/akita-schedules/src/generated/fp128_onehot.rs b/crates/akita-schedules/src/generated/fp128_onehot.rs index bb9a8b224..678a805da 100644 --- a/crates/akita-schedules/src/generated/fp128_onehot.rs +++ b/crates/akita-schedules/src/generated/fp128_onehot.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -22,9 +23,9 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1909, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1909, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -35,9 +36,9 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1942, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1942, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -48,9 +49,9 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1898, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1898, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -61,10 +62,10 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2499, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2103, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2499, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2103, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -75,9 +76,9 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1983, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1983, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1883, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -91,12 +92,12 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7059, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7381, positions_per_block: 512, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3496, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2124, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7060, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7381, positions_per_block: 512, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5016, positions_per_block: 512, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(456145306), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3352, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(284420015), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(633237013), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -107,10 +108,10 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1377, positions_per_block: 256, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2508, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1377, positions_per_block: 256, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2508, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1766, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1766, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -121,9 +122,9 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2104, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2104, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2976, positions_per_block: 256, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2976, positions_per_block: 256, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -134,12 +135,11 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6607, positions_per_block: 512, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3236, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2096, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3816, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5833, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2766, positions_per_block: 512, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(998153257), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2498, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(719099659), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -152,12 +152,11 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4483, positions_per_block: 512, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6091, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3106, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2096, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4484, positions_per_block: 512, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6091, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2766, positions_per_block: 512, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(998153257), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2498, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(719099659), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -168,11 +167,12 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5192, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2596, positions_per_block: 256, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7639, positions_per_block: 512, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5016, positions_per_block: 512, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(456145306), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3352, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(284420015), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(633237013), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -185,12 +185,12 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5687, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6865, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3366, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2124, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5688, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6865, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4824, positions_per_block: 512, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(434679645), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3352, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(284420015), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(633237013), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -201,12 +201,12 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3620, positions_per_block: 256, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9015, positions_per_block: 1024, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3740, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3620, positions_per_block: 256, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7576, positions_per_block: 512, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5016, positions_per_block: 512, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3352, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(284420015), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(633237013), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -220,12 +220,11 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4116, positions_per_block: 256, live_blocks: 17 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9703, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3870, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 16464, positions_per_block: 1024, live_blocks: 17 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4780, positions_per_block: 512, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2520, positions_per_block: 512, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(3520368477), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1728, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -240,12 +239,11 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4363, positions_per_block: 256, live_blocks: 18 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10047, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3870, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 17452, positions_per_block: 1024, live_blocks: 18 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4910, positions_per_block: 512, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2520, positions_per_block: 512, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(3520368477), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1728, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -256,13 +254,12 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 110351, positions_per_block: 2048, live_blocks: 54 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 22821, positions_per_block: 1024, live_blocks: 23 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10727, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4000, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 110351, positions_per_block: 2048, live_blocks: 54 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 17112, positions_per_block: 1024, live_blocks: 17 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6936, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(633237013), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3520, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(340767376), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -273,13 +270,13 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 285455, positions_per_block: 2048, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 45009, positions_per_block: 2048, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10968, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 285455, positions_per_block: 2048, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 45009, positions_per_block: 2048, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 14565, positions_per_block: 1024, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(313935299), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5528, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(440046060), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -290,13 +287,13 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 570127, positions_per_block: 4096, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 53201, positions_per_block: 2048, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7998, positions_per_block: 1024, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3617, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 570127, positions_per_block: 4096, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 53201, positions_per_block: 2048, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11736, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1041084580), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -307,13 +304,13 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 570127, positions_per_block: 4096, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 53201, positions_per_block: 2048, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7998, positions_per_block: 1024, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3617, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 570127, positions_per_block: 4096, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 53201, positions_per_block: 2048, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11736, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1041084580), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -327,13 +324,13 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 749437, positions_per_block: 4096, live_blocks: 183 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 64295, positions_per_block: 4096, live_blocks: 16 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10794, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 749440, positions_per_block: 8192, live_blocks: 92 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 57201, positions_per_block: 2048, live_blocks: 28 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 12120, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1084015903), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -344,13 +341,13 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1139471, positions_per_block: 8192, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 69585, positions_per_block: 4096, live_blocks: 17 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10924, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1139471, positions_per_block: 8192, live_blocks: 140 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 52056, positions_per_block: 2048, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11736, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1073283072), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -361,14 +358,13 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2196582, positions_per_block: 8192, live_blocks: 269 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 102867, positions_per_block: 2048, live_blocks: 51 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 22047, positions_per_block: 1024, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10469, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4000, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2196582, positions_per_block: 8192, live_blocks: 269 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 102867, positions_per_block: 2048, live_blocks: 51 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 22047, positions_per_block: 1024, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(547374367), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6424, positions_per_block: 512, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(563473613), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3392, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(327351337), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -379,14 +375,14 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5259913, positions_per_block: 16384, live_blocks: 322 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 242623, positions_per_block: 4096, live_blocks: 60 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 32561, positions_per_block: 2048, live_blocks: 16 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9816, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3881, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5259913, positions_per_block: 16384, live_blocks: 322 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 242623, positions_per_block: 4096, live_blocks: 60 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 32561, positions_per_block: 2048, live_blocks: 16 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 13017, positions_per_block: 1024, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(262954353), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5272, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(402481152), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(297836053), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -397,14 +393,14 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 12616005, positions_per_block: 16384, live_blocks: 771 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 660935, positions_per_block: 8192, live_blocks: 81 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 54363, positions_per_block: 2048, live_blocks: 27 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 8128, positions_per_block: 1024, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3617, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 12616005, positions_per_block: 16384, live_blocks: 771 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 660935, positions_per_block: 8192, live_blocks: 81 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 54363, positions_per_block: 2048, live_blocks: 27 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11928, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1062550242), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -415,15 +411,14 @@ pub(crate) static FP128_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 403703057, positions_per_block: 131072, live_blocks: 3081 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 5, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1716178, positions_per_block: 8192, live_blocks: 210 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 87645, positions_per_block: 2048, live_blocks: 43 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 19983, positions_per_block: 1024, live_blocks: 20 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9953, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3870, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 403703057, positions_per_block: 131072, live_blocks: 3081 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 5, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1716178, positions_per_block: 8192, live_blocks: 210 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 65496, positions_per_block: 2048, live_blocks: 32 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(6525561078), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11832, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1084015903), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -442,6 +437,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_onehot", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -449,10 +445,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(128) }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -463,5 +459,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 25, - key_digest: 9301922067497857147, + key_digest: 12590252781461170853, }; diff --git a/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk.rs b/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk.rs index ef72295bd..f3839883b 100644 --- a/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk.rs +++ b/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -22,14 +23,14 @@ pub(crate) static FP128_ONEHOT_MULTI_CHUNK_SCHEDULES: &[GeneratedFoldScheduleEnt witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 568516, positions_per_block: 2048, live_blocks: 278 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 406547, positions_per_block: 4096, live_blocks: 100 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 42881, positions_per_block: 2048, live_blocks: 21 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10776, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 568516, positions_per_block: 2048, live_blocks: 278 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 406547, positions_per_block: 4096, live_blocks: 100 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 42881, positions_per_block: 2048, live_blocks: 21 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 14307, positions_per_block: 1024, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(303202468), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5400, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(423946814), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -43,14 +44,14 @@ pub(crate) static FP128_ONEHOT_MULTI_CHUNK_SCHEDULES: &[GeneratedFoldScheduleEnt witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 613750, positions_per_block: 2048, live_blocks: 300 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 417899, positions_per_block: 4096, live_blocks: 103 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 43655, positions_per_block: 2048, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10968, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 613750, positions_per_block: 2048, live_blocks: 300 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 417899, positions_per_block: 4096, live_blocks: 103 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 43655, positions_per_block: 2048, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 14565, positions_per_block: 1024, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(311252091), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5528, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(440046060), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -69,6 +70,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_onehot_multi_chunk", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -76,10 +78,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(128) }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -90,5 +92,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 2, - key_digest: 17334720321742528059, + key_digest: 6677116910439513529, }; diff --git a/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w2r2.rs b/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w2r2.rs index 981d9e8f3..faf589464 100644 --- a/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w2r2.rs +++ b/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w2r2.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -22,11 +23,11 @@ pub(crate) static FP128_ONEHOT_MULTI_CHUNK_W2R2_SCHEDULES: &[GeneratedFoldSchedu witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3309, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3236, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2096, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3309, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3236, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2096, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -39,11 +40,11 @@ pub(crate) static FP128_ONEHOT_MULTI_CHUNK_W2R2_SCHEDULES: &[GeneratedFoldSchedu witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3320, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3236, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2096, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3320, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3236, positions_per_block: 256, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2096, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, response_l2_sq_cap: None, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -54,14 +55,13 @@ pub(crate) static FP128_ONEHOT_MULTI_CHUNK_W2R2_SCHEDULES: &[GeneratedFoldSchedu witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 240836, positions_per_block: 2048, live_blocks: 118 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 127379, positions_per_block: 2048, live_blocks: 63 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 25143, positions_per_block: 1024, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11243, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4000, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 240836, positions_per_block: 2048, live_blocks: 118 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 2 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 127379, positions_per_block: 2048, live_blocks: 63 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 25143, positions_per_block: 1024, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(633237013), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6808, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(611771352), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3520, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(340767376), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -80,6 +80,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_onehot_multi_chunk_w2r2", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -87,10 +88,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(128) }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -101,5 +102,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 3, - key_digest: 15993269577012611718, + key_digest: 11158377409947375287, }; diff --git a/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w4r2.rs b/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w4r2.rs index 27139a331..068f11c68 100644 --- a/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w4r2.rs +++ b/crates/akita-schedules/src/generated/fp128_onehot_multi_chunk_w4r2.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -22,14 +23,13 @@ pub(crate) static FP128_ONEHOT_MULTI_CHUNK_W4R2_SCHEDULES: &[GeneratedFoldSchedu witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 4 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1225487, positions_per_block: 4096, live_blocks: 300 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 4 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 143633, positions_per_block: 4096, live_blocks: 36 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 26369, positions_per_block: 1024, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5950, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3956, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1225487, positions_per_block: 4096, live_blocks: 300 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 4 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 143633, positions_per_block: 4096, live_blocks: 36 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 26369, positions_per_block: 1024, live_blocks: 26 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(574206444), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6936, positions_per_block: 512, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(622504182), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3520, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(340767376), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -48,6 +48,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_onehot_multi_chunk_w4r2", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -55,10 +56,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(128) }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -69,5 +70,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 1, - key_digest: 13570015983847967009, + key_digest: 12882065207577545601, }; diff --git a/crates/akita-schedules/src/generated/fp128_onehot_recursive.rs b/crates/akita-schedules/src/generated/fp128_onehot_recursive.rs index 628677d22..07f966311 100644 --- a/crates/akita-schedules/src/generated/fp128_onehot_recursive.rs +++ b/crates/akita-schedules/src/generated/fp128_onehot_recursive.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -25,14 +26,14 @@ pub(crate) static FP128_ONEHOT_RECURSIVE_SCHEDULES: &[GeneratedFoldScheduleEntry witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 187360, positions_per_block: 2048, live_blocks: 92 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: Some(GeneratedSetupPrefixInput { natural_len: 11294208, num_digits_fold: 4, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 65536, positions_per_block: 256, live_blocks: 256 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } } }), witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 225124, positions_per_block: 4096, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 23448, positions_per_block: 1024, live_blocks: 23 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 8088, positions_per_block: 1024, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3610, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 187360, positions_per_block: 2048, live_blocks: 92 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: Some(GeneratedSetupPrefixInput { natural_len: 11294208, num_digits_fold: 4, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 65536, positions_per_block: 256, live_blocks: 256 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } } }), witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 225124, positions_per_block: 4096, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 23448, positions_per_block: 1024, live_blocks: 23 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 8088, positions_per_block: 1024, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5208, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(434679645), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -43,14 +44,14 @@ pub(crate) static FP128_ONEHOT_RECURSIVE_SCHEDULES: &[GeneratedFoldScheduleEntry witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 549146, positions_per_block: 2048, live_blocks: 269 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: Some(GeneratedSetupPrefixInput { natural_len: 45088768, num_digits_fold: 4, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 262144, positions_per_block: 512, live_blocks: 512 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 7 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } } }), witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 481988, positions_per_block: 8192, live_blocks: 59 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 36504, positions_per_block: 2048, live_blocks: 18 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10200, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3881, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 549146, positions_per_block: 2048, live_blocks: 269 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: Some(GeneratedSetupPrefixInput { natural_len: 45088768, num_digits_fold: 4, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 262144, positions_per_block: 512, live_blocks: 512 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 7 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } } }), witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 481988, positions_per_block: 8192, live_blocks: 59 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 36504, positions_per_block: 2048, live_blocks: 18 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10200, positions_per_block: 1024, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5592, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -69,6 +70,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_onehot_recursive", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinFirstDirectSetupThenPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -76,10 +78,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(128) }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -90,5 +92,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 2, - key_digest: 10667364833644303292, + key_digest: 11419798877552006256, }; diff --git a/crates/akita-schedules/src/generated/fp128_onehot_recursive_multi_chunk_w8r2.rs b/crates/akita-schedules/src/generated/fp128_onehot_recursive_multi_chunk_w8r2.rs index cdc7a4b95..6ef5434dd 100644 --- a/crates/akita-schedules/src/generated/fp128_onehot_recursive_multi_chunk_w8r2.rs +++ b/crates/akita-schedules/src/generated/fp128_onehot_recursive_multi_chunk_w8r2.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -25,14 +26,14 @@ pub(crate) static FP128_ONEHOT_RECURSIVE_MULTI_CHUNK_W8R2_SCHEDULES: &[Generated witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 }, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 613793, positions_per_block: 4096, live_blocks: 150 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: Some(GeneratedSetupPrefixInput { natural_len: 11316224, num_digits_fold: 4, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 65536, positions_per_block: 128, live_blocks: 512 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 7 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } } }), witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 960420, positions_per_block: 8192, live_blocks: 118 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 46626, positions_per_block: 2048, live_blocks: 23 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10904, positions_per_block: 1024, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4013, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2256, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 613793, positions_per_block: 4096, live_blocks: 150 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: Some(GeneratedSetupPrefixInput { natural_len: 11316224, num_digits_fold: 4, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 65536, positions_per_block: 128, live_blocks: 512 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 7 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } } }), witness_partition: GeneratedWitnessPartition::Distributed { num_chunks: 8 } }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 960420, positions_per_block: 8192, live_blocks: 118 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 59832, positions_per_block: 2048, live_blocks: 30 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(4980033455), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11512, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1041084580), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5560, positions_per_block: 512, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(477610968), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3480, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(300519261), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1656, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1908, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 3, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(638603428), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -51,6 +52,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp128_onehot_recursive_multi_chunk_w8r2", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinFirstDirectSetupThenPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -58,10 +60,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(128) }, - ring_subfield_norm_bound: 1, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 11), @@ -72,5 +74,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 3458533356553718245, key_count: 1, - key_digest: 6202599996876915373, + key_digest: 6988733398984024709, }; diff --git a/crates/akita-schedules/src/generated/fp32_dense.rs b/crates/akita-schedules/src/generated/fp32_dense.rs index e240684bd..3f19fa199 100644 --- a/crates/akita-schedules/src/generated/fp32_dense.rs +++ b/crates/akita-schedules/src/generated/fp32_dense.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -22,12 +23,12 @@ pub(crate) static FP32_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7475, positions_per_block: 256, live_blocks: 30 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3394, positions_per_block: 256, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1605, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1016, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7475, positions_per_block: 256, live_blocks: 30 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 5680, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1951, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1022, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1792239626), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 712, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1348615957), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -38,13 +39,13 @@ pub(crate) static FP32_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 66291, positions_per_block: 1024, live_blocks: 65 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 12684, positions_per_block: 512, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3820, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1790, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1016, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 132582, positions_per_block: 2048, live_blocks: 65 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 15673, positions_per_block: 512, live_blocks: 31 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3015, positions_per_block: 256, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1384105850), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1251, positions_per_block: 256, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1934199201), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 824, positions_per_block: 128, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1366360903), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 616, positions_per_block: 128, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1135676595), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -63,6 +64,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp32_dense", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -70,10 +72,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q32Offset99, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 32, log_open_bound: None }, - ring_subfield_norm_bound: 2, claim_ext_degree: 4, chal_ext_degree: 4, inner_basis_range: (3, 10), @@ -84,5 +86,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 12423973825851036286, key_count: 2, - key_digest: 11360209369772851366, + key_digest: 8356767431622902133, }; diff --git a/crates/akita-schedules/src/generated/fp32_dense_precommitted.rs b/crates/akita-schedules/src/generated/fp32_dense_precommitted.rs index 868aac5de..f984bda6a 100644 --- a/crates/akita-schedules/src/generated/fp32_dense_precommitted.rs +++ b/crates/akita-schedules/src/generated/fp32_dense_precommitted.rs @@ -6,10 +6,10 @@ use super::{ #[rustfmt::skip] pub(crate) static FP32_DENSE_SCHEDULES_PRECOMMITTED_PROFILES: &[GeneratedPrecommittedProfile] = &[ - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 32, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 32, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 32, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 64, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 32, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 32, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 32, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 64, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 4, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 11, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, ]; diff --git a/crates/akita-schedules/src/generated/fp32_onehot.rs b/crates/akita-schedules/src/generated/fp32_onehot.rs index eacb257d0..388f8c388 100644 --- a/crates/akita-schedules/src/generated/fp32_onehot.rs +++ b/crates/akita-schedules/src/generated/fp32_onehot.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -16,16 +17,17 @@ pub(crate) static FP32_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ GeneratedFoldScheduleEntry { root: GeneratedRootFold { final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(14, 1), num_digits_inner: 1, num_digits_fold: 2, - commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 64, positions_per_block: 8, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } } }, + commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 32, positions_per_block: 4, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 512, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } } }, precommitted_groups: &[], open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 }, witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1002, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 959, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1002, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 959, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1455085637), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 616, positions_per_block: 128, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1135676595), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -36,10 +38,11 @@ pub(crate) static FP32_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1006, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 959, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1006, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 959, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1455085637), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 616, positions_per_block: 128, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1135676595), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -50,10 +53,11 @@ pub(crate) static FP32_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 985, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 959, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 985, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 959, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1455085637), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 616, positions_per_block: 128, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1135676595), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -64,28 +68,28 @@ pub(crate) static FP32_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2742, positions_per_block: 256, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1383, positions_per_block: 128, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 928, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1371, positions_per_block: 256, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2287, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1100, positions_per_block: 128, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(501294747), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 700, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1313126063), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(20, 1), num_digits_inner: 1, num_digits_fold: 2, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4096, positions_per_block: 256, live_blocks: 16 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } } }, precommitted_groups: &[ - GeneratedRootPrecommittedGroup { descriptor: CommittedGroupProfile { version: CommittedGroupProfile::VERSION, group: PolynomialGroupLayout::new(14, 1), num_live_ring_elements_per_claim: 128, num_positions_per_block: 64, num_live_blocks: 2, log_basis_inner: 3, num_digits_inner: 1, inner_commit_matrix: InnerCommitMatrixParams::new_unchecked(SisSecurityPolicyId::Quantum128BitADPS16, SisTableDigest([242, 228, 119, 109, 33, 25, 231, 43, 203, 140, 11, 93, 57, 15, 147, 234, 80, 167, 7, 242, 178, 210, 29, 149, 120, 103, 249, 50, 46, 32, 225, 109]), SisModulusProfileId::Q32Offset99, 4, 64, 2047, 128), log_basis_outer: 3, num_digits_outer: 11, outer_commit_matrix: OuterCommitMatrixParams::new_unchecked(SisSecurityPolicyId::Quantum128BitADPS16, SisTableDigest([242, 228, 119, 109, 33, 25, 231, 43, 203, 140, 11, 93, 57, 15, 147, 234, 80, 167, 7, 242, 178, 210, 29, 149, 120, 103, 249, 50, 46, 32, 225, 109]), SisModulusProfileId::Q32Offset99, 1, 88, 7, 128) }, num_digits_fold: 1, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 64, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } } }, + GeneratedRootPrecommittedGroup { descriptor: CommittedGroupProfile { version: CommittedGroupProfile::VERSION, group: PolynomialGroupLayout::new(14, 1), num_live_ring_elements_per_claim: 128, num_positions_per_block: 64, num_live_blocks: 2, log_basis_inner: 3, num_digits_inner: 1, inner_commit_matrix: InnerCommitMatrixParams::new_unchecked(SisSecurityPolicyId::Quantum128BitADPS16, SisTableDigest([242, 228, 119, 109, 33, 25, 231, 43, 203, 140, 11, 93, 57, 15, 147, 234, 80, 167, 7, 242, 178, 210, 29, 149, 120, 103, 249, 50, 46, 32, 225, 109]), SisModulusProfileId::Q32Offset99, 3, 64, 1023, 128), log_basis_outer: 3, num_digits_outer: 11, outer_commit_matrix: OuterCommitMatrixParams::new_unchecked(SisSecurityPolicyId::Quantum128BitADPS16, SisTableDigest([242, 228, 119, 109, 33, 25, 231, 43, 203, 140, 11, 93, 57, 15, 147, 234, 80, 167, 7, 242, 178, 210, 29, 149, 120, 103, 249, 50, 46, 32, 225, 109]), SisModulusProfileId::Q32Offset99, 1, 66, 7, 128) }, num_digits_fold: 1, commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 64, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } } }, ], open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 }, witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1497, positions_per_block: 128, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2918, positions_per_block: 256, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1268, positions_per_block: 128, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1481, positions_per_block: 256, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2287, positions_per_block: 256, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1100, positions_per_block: 128, live_blocks: 9 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(501294747), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 874, positions_per_block: 128, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 700, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1313126063), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -96,13 +100,12 @@ pub(crate) static FP32_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 27847, positions_per_block: 512, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11710, positions_per_block: 512, live_blocks: 23 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3660, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1790, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1016, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 27847, positions_per_block: 512, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 10478, positions_per_block: 512, live_blocks: 21 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2455, positions_per_block: 256, live_blocks: 10 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1064696808), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 998, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1739004786), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 712, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1348615957), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -113,13 +116,13 @@ pub(crate) static FP32_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 55495, positions_per_block: 512, live_blocks: 109 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 13836, positions_per_block: 512, live_blocks: 28 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4060, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1790, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1016, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 55495, positions_per_block: 1024, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 15806, positions_per_block: 512, live_blocks: 31 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3015, positions_per_block: 256, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1384105850), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1251, positions_per_block: 256, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1934199201), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 824, positions_per_block: 128, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1366360903), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 128, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 766, positions_per_block: 128, live_blocks: 6 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 616, positions_per_block: 128, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 6, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(1135676595), z_admission_linf_cap: 2114, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -132,12 +135,13 @@ pub(crate) static CATALOG_POTENTIAL_B_DIMENSIONS: &[usize] = &[64, 128, 256]; #[rustfmt::skip] pub(crate) static CATALOG_POTENTIAL_D_DIMENSIONS: &[usize] = &[64, 128, 256]; #[rustfmt::skip] -pub(crate) static CATALOG_RING_DIMENSIONS: &[usize] = &[128, 256, 1024]; +pub(crate) static CATALOG_RING_DIMENSIONS: &[usize] = &[128, 256, 512, 1024]; #[rustfmt::skip] pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = GeneratedScheduleCatalogIdentity { family_name: "fp32_onehot", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -145,10 +149,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q32Offset99, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(32) }, - ring_subfield_norm_bound: 2, claim_ext_degree: 4, chal_ext_degree: 4, inner_basis_range: (3, 10), @@ -159,5 +163,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 12423973825851036286, key_count: 7, - key_digest: 1569122584199732563, + key_digest: 1571083004534005729, }; diff --git a/crates/akita-schedules/src/generated/fp32_onehot_precommitted.rs b/crates/akita-schedules/src/generated/fp32_onehot_precommitted.rs index 9c982d984..e81712e89 100644 --- a/crates/akita-schedules/src/generated/fp32_onehot_precommitted.rs +++ b/crates/akita-schedules/src/generated/fp32_onehot_precommitted.rs @@ -6,10 +6,10 @@ use super::{ #[rustfmt::skip] pub(crate) static FP32_ONEHOT_SCHEDULES_PRECOMMITTED_PROFILES: &[GeneratedPrecommittedProfile] = &[ - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 64, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 2047, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 64, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 2047, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 256, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 4, inner_coeff_linf_bound: 2047, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 128, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 64, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 3, inner_coeff_linf_bound: 1023, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 64, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 3, inner_coeff_linf_bound: 1023, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 256, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 3, inner_coeff_linf_bound: 1023, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 256, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 11, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, ]; diff --git a/crates/akita-schedules/src/generated/fp64_dense.rs b/crates/akita-schedules/src/generated/fp64_dense.rs index 808ee8090..9cb844916 100644 --- a/crates/akita-schedules/src/generated/fp64_dense.rs +++ b/crates/akita-schedules/src/generated/fp64_dense.rs @@ -8,24 +8,26 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] pub(crate) static FP64_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ GeneratedFoldScheduleEntry { root: GeneratedRootFold { - final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(14, 1), num_digits_inner: 7, num_digits_fold: 5, - commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 32, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 10 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } } }, + final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(14, 1), num_digits_inner: 13, num_digits_fold: 4, + commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 128, positions_per_block: 16, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 128, log_basis: 3, slice_count: 1 } } }, precommitted_groups: &[], open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2025, positions_per_block: 512, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3176, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2000, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 128, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2586, positions_per_block: 256, live_blocks: 11 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1744, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(3777956414), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2012, positions_per_block: 256, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, num_digits_inner: 1, inner_output_rank: 9, inner_coeff_linf_bound: 2097151, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1260, positions_per_block: 256, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 7, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(2640276358), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -36,29 +38,29 @@ pub(crate) static FP64_DENSE_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9161, positions_per_block: 512, live_blocks: 18 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11948, positions_per_block: 1024, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3961, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2395, positions_per_block: 512, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9161, positions_per_block: 512, live_blocks: 18 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11773, positions_per_block: 512, live_blocks: 23 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3572, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(2017772176), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1772, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(3305711862), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1728, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 9, inner_coeff_linf_bound: 2097151, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1260, positions_per_block: 256, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 7, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(2618810696), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { - final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(26, 1), num_digits_inner: 11, num_digits_fold: 5, - commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 131072, positions_per_block: 512, live_blocks: 256 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 512, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } } }, + final_group: GeneratedRootFinalGroup { layout: PolynomialGroupLayout::new(26, 1), num_digits_inner: 7, num_digits_fold: 6, + commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 131072, positions_per_block: 512, live_blocks: 256 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 512, log_basis: 10 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 } } }, precommitted_groups: &[], open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 3, slice_count: 1 }, witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 361764, positions_per_block: 4096, live_blocks: 89 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 38605, positions_per_block: 1024, live_blocks: 38 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 13031, positions_per_block: 1024, live_blocks: 13 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4078, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2395, positions_per_block: 512, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 308516, positions_per_block: 4096, live_blocks: 76 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 25016, positions_per_block: 1024, live_blocks: 25 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 7640, positions_per_block: 512, live_blocks: 15 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 } }, num_digits_fold: 3, response_l2_sq_cap: Some(1073283072), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 4, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3992, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 4 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(542007952), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1761, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(3219849216), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1728, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 9, inner_coeff_linf_bound: 2097151, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1260, positions_per_block: 256, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 7, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(2618810696), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -77,6 +79,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp64_dense", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -84,10 +87,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q64Offset59, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 64, log_open_bound: None }, - ring_subfield_norm_bound: 2, claim_ext_degree: 2, chal_ext_degree: 2, inner_basis_range: (3, 11), @@ -98,5 +101,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 16577217186669637934, key_count: 3, - key_digest: 13592170348540370811, + key_digest: 3920807455985822298, }; diff --git a/crates/akita-schedules/src/generated/fp64_dense_precommitted.rs b/crates/akita-schedules/src/generated/fp64_dense_precommitted.rs index e9f9b1e58..554dd1043 100644 --- a/crates/akita-schedules/src/generated/fp64_dense_precommitted.rs +++ b/crates/akita-schedules/src/generated/fp64_dense_precommitted.rs @@ -6,10 +6,10 @@ use super::{ #[rustfmt::skip] pub(crate) static FP64_DENSE_SCHEDULES_PRECOMMITTED_PROFILES: &[GeneratedPrecommittedProfile] = &[ - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 32, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 13, inner_output_rank: 9, inner_coeff_linf_bound: 2097151, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 64, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 64, live_blocks: 16 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 11, inner_coeff_linf_bound: 16777215, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 32, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 13, inner_output_rank: 8, inner_coeff_linf_bound: 1048575, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 64, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 64, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 64, live_blocks: 16 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 10, inner_coeff_linf_bound: 8388607, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 128, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 8 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 8, inner_output_rank: 11, inner_coeff_linf_bound: 8388607, num_digits_outer: 22, outer_output_rank: 2, outer_coeff_linf_bound: 7 }, ]; diff --git a/crates/akita-schedules/src/generated/fp64_onehot.rs b/crates/akita-schedules/src/generated/fp64_onehot.rs index 78d56e696..3f6b424dc 100644 --- a/crates/akita-schedules/src/generated/fp64_onehot.rs +++ b/crates/akita-schedules/src/generated/fp64_onehot.rs @@ -8,7 +8,8 @@ use super::{ GeneratedRootPrecommittedGroup, GeneratedScheduleCatalogIdentity, GeneratedSetupPrefixInput, GeneratedTerminalFold, GeneratedWitnessPartition, InnerCommitMatrixParams, OuterCommitMatrixParams, PlannerCostModelId, PolynomialGroupLayout, RingDimensionScheduleMode, - SelectionPolicyId, SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, + SelectionPolicyId, SelectiveL2ResponseModelId, SisL2TableDigest, SisModulusProfileId, + SisSecurityPolicyId, SisTableDigest, }; #[rustfmt::skip] @@ -22,12 +23,13 @@ pub(crate) static FP64_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 27933, positions_per_block: 512, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 256, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 256, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 256, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 13532, positions_per_block: 1024, live_blocks: 14 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 4079, positions_per_block: 512, live_blocks: 8 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2395, positions_per_block: 512, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 111732, positions_per_block: 2048, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 20867, positions_per_block: 1024, live_blocks: 21 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 9291, positions_per_block: 512, live_blocks: 19 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3496, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1760184239), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1772, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(3262780539), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1728, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 9, inner_coeff_linf_bound: 2097151, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1260, positions_per_block: 256, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 7, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(2618810696), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, GeneratedFoldScheduleEntry { root: GeneratedRootFold { @@ -38,12 +40,13 @@ pub(crate) static FP64_ONEHOT_SCHEDULES: &[GeneratedFoldScheduleEntry] = &[ witness_partition: GeneratedWitnessPartition::Single, }, recursive_folds: &[ - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 222324, positions_per_block: 4096, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 30291, positions_per_block: 1024, live_blocks: 30 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 6067, positions_per_block: 512, live_blocks: 12 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, - GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 2498, positions_per_block: 512, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 222324, positions_per_block: 4096, live_blocks: 55 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 29059, positions_per_block: 1024, live_blocks: 29 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_fold: 4, response_l2_sq_cap: None, open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Compressed, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 11051, positions_per_block: 512, live_blocks: 22 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(397114737), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 5, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 3509, positions_per_block: 512, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 5 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(1781649900), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, + GeneratedRecursiveFold { payload_mode: CommitmentPayloadMode::Raw, witness: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1772, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 } }, num_digits_fold: 2, response_l2_sq_cap: Some(3262780539), open_commit_matrix: GeneratedOpenCommitMatrix { ring_dimension: 64, log_basis: 6, slice_count: 1 }, incoming_setup_prefix: None, witness_partition: GeneratedWitnessPartition::Single }, ], - terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1728, positions_per_block: 256, live_blocks: 7 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, inner_output_rank: 9, inner_coeff_linf_bound: 2097151, z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, + terminal: GeneratedTerminalFold { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1260, positions_per_block: 256, live_blocks: 5 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 6 }, num_digits_inner: 1, fold_log_basis: 6, fold_digit_count: 2, inner_output_rank: 7, inner_coeff_linf_bound: 0, response_l2_sq_cap: Some(2618810696), z_admission_linf_cap: 2570, z_rice_low_bits: 9, z_payload_bytes: 26624 }, }, ]; @@ -62,6 +65,7 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated family_name: "fp64_onehot", protocol_epoch: 1, cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::BoundedBalancedExtremesV1, setup_field_budget: None, @@ -69,10 +73,10 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated sis_modulus_profile: SisModulusProfileId::Q64Offset59, sis_security_policy: SisSecurityPolicyId::Quantum128BitADPS16, sis_table_digest: SisTableDigest([0xf2, 0xe4, 0x77, 0x6d, 0x21, 0x19, 0xe7, 0x2b, 0xcb, 0x8c, 0x0b, 0x5d, 0x39, 0x0f, 0x93, 0xea, 0x50, 0xa7, 0x07, 0xf2, 0xb2, 0xd2, 0x1d, 0x95, 0x78, 0x67, 0xf9, 0x32, 0x2e, 0x20, 0xe1, 0x6d]), + sis_l2_table_digest: SisL2TableDigest([0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a]), uniform_ring_dimension: 256, setup_prefix_inner_ring_dimension: 256, decomposition: DecompositionParams { log_basis: 3, log_commit_bound: 1, log_open_bound: Some(64) }, - ring_subfield_norm_bound: 2, claim_ext_degree: 2, chal_ext_degree: 2, inner_basis_range: (3, 11), @@ -83,5 +87,5 @@ pub(crate) static CATALOG_IDENTITY: GeneratedScheduleCatalogIdentity = Generated ring_dimensions: CATALOG_RING_DIMENSIONS, ring_challenge_config_digest: 16577217186669637934, key_count: 2, - key_digest: 3910457326744101461, + key_digest: 13224114170676235699, }; diff --git a/crates/akita-schedules/src/generated/fp64_onehot_precommitted.rs b/crates/akita-schedules/src/generated/fp64_onehot_precommitted.rs index 6630a39e6..1f19ef11f 100644 --- a/crates/akita-schedules/src/generated/fp64_onehot_precommitted.rs +++ b/crates/akita-schedules/src/generated/fp64_onehot_precommitted.rs @@ -6,10 +6,10 @@ use super::{ #[rustfmt::skip] pub(crate) static FP64_ONEHOT_SCHEDULES_PRECOMMITTED_PROFILES: &[GeneratedPrecommittedProfile] = &[ - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 256, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 256, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 256, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, - GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 256, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 32767, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(14, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 256, positions_per_block: 128, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 256, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(15, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 512, positions_per_block: 256, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 1), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 256, live_blocks: 4 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, + GeneratedPrecommittedProfile { group: PolynomialGroupLayout::new(16, 2), commitment: GeneratedCommittedGroup { geometry: GeneratedBlockGeometry { live_ring_elements_per_claim: 1024, positions_per_block: 512, live_blocks: 2 }, inner_commit_matrix: GeneratedInnerCommitMatrix { ring_dimension: 64, log_basis: 3 }, outer_commit_matrix: GeneratedOuterCommitMatrix { ring_dimension: 64, log_basis: 3, slice_count: 1 } }, num_digits_inner: 1, inner_output_rank: 5, inner_coeff_linf_bound: 16383, num_digits_outer: 22, outer_output_rank: 1, outer_coeff_linf_bound: 7 }, ]; diff --git a/crates/akita-schedules/src/generated/mod.rs b/crates/akita-schedules/src/generated/mod.rs index 1bde61652..a8f9a7470 100644 --- a/crates/akita-schedules/src/generated/mod.rs +++ b/crates/akita-schedules/src/generated/mod.rs @@ -77,6 +77,7 @@ pub struct GeneratedRecursiveFold { pub payload_mode: akita_types::CommitmentPayloadMode, pub witness: GeneratedCommittedGroup, pub num_digits_fold: u32, + pub response_l2_sq_cap: Option, pub open_commit_matrix: GeneratedOpenCommitMatrix, pub incoming_setup_prefix: Option, pub witness_partition: GeneratedWitnessPartition, @@ -87,8 +88,11 @@ pub struct GeneratedTerminalFold { pub geometry: GeneratedBlockGeometry, pub inner_commit_matrix: GeneratedInnerCommitMatrix, pub num_digits_inner: u32, + pub fold_log_basis: u32, + pub fold_digit_count: u32, pub inner_output_rank: u32, pub inner_coeff_linf_bound: u128, + pub response_l2_sq_cap: Option, pub z_admission_linf_cap: u128, pub z_rice_low_bits: u32, pub z_payload_bytes: u64, @@ -133,6 +137,7 @@ pub struct GeneratedScheduleCatalogIdentity { pub family_name: &'static str, pub protocol_epoch: u32, pub cost_model: crate::PlannerCostModelId, + pub selective_l2_response_model: crate::SelectiveL2ResponseModelId, pub selection_policy: crate::SelectionPolicyId, pub recursive_split_search_policy: crate::RecursiveSplitSearchPolicy, pub setup_field_budget: Option, @@ -140,10 +145,10 @@ pub struct GeneratedScheduleCatalogIdentity { pub sis_modulus_profile: SisModulusProfileId, pub sis_security_policy: akita_types::SisSecurityPolicyId, pub sis_table_digest: akita_types::SisTableDigest, + pub sis_l2_table_digest: akita_types::SisL2TableDigest, pub uniform_ring_dimension: usize, pub setup_prefix_inner_ring_dimension: usize, pub decomposition: akita_types::DecompositionParams, - pub ring_subfield_norm_bound: u32, pub claim_ext_degree: usize, pub chal_ext_degree: usize, pub inner_basis_range: (u32, u32), @@ -174,13 +179,14 @@ pub mod validate; pub(crate) mod walk; pub use crate::{ ChunkedWitnessCfg, CommitmentRingDims, DecompositionParams, PlannerCostModelId, - RecursiveSplitSearchPolicy, RingDimensionScheduleMode, SelectionPolicyId, SisSecurityPolicyId, + RecursiveSplitSearchPolicy, RingDimensionScheduleMode, SelectionPolicyId, + SelectiveL2ResponseModelId, SisSecurityPolicyId, }; pub use akita_types::{ CommitmentPayloadMode, CommittedGroupProfile, InnerCommitMatrixParams, OuterCommitMatrixParams, PolynomialGroupLayout, }; -pub use akita_types::{SisModulusProfileId, SisTableDigest}; +pub use akita_types::{SisL2TableDigest, SisModulusProfileId, SisTableDigest}; pub use validate::{validate_generated_schedule_entry, validate_generated_schedule_table}; /// Returns true when `entries` are ordered for [`table_entry`] binary search. diff --git a/crates/akita-schedules/src/generated/walk.rs b/crates/akita-schedules/src/generated/walk.rs index 36e2a33a6..219fa649b 100644 --- a/crates/akita-schedules/src/generated/walk.rs +++ b/crates/akita-schedules/src/generated/walk.rs @@ -9,9 +9,9 @@ use akita_challenges::SparseChallengeConfig; use akita_field::AkitaError; use akita_types::{ - extension_opening_reduction_level_bytes, level_proof_bytes, terminal_response_bytes, - AkitaScheduleLookupKey, PlannedFoldSchedule, PolynomialGroupLayout, PrecommittedLevelParams, - TailSegmentGroupLayout, TailSegmentLayout, TerminalResponseShape, + extension_opening_reduction_level_bytes, level_proof_bytes, AkitaScheduleLookupKey, + PlannedFoldSchedule, PolynomialGroupLayout, PrecommittedLevelParams, TailSegmentGroupLayout, + TailSegmentLayout, TerminalResponseShape, }; use crate::generated::{validate_entry_key, GeneratedFoldScheduleEntry}; @@ -79,6 +79,7 @@ pub(crate) fn walk_generated_schedule_entry( 0, Some(entry.root.final_group.num_digits_inner), entry.root.final_group.num_digits_fold, + None, expected_root_w_len, key.final_group.num_polynomials(), entry.root.open_commit_matrix, @@ -120,6 +121,7 @@ pub(crate) fn walk_generated_schedule_entry( index + 1, None, fold.num_digits_fold, + fold.response_l2_sq_cap, input_witness_len, 1, fold.open_commit_matrix, @@ -234,7 +236,11 @@ pub(crate) fn walk_generated_schedule_entry( .ok_or_else(|| { AkitaError::InvalidSetup("terminal direct byte count overflow".to_string()) })?; - let terminal_bytes = terminal_response_bytes(field_bits, &witness_shape); + let terminal_bytes = akita_types::terminal_response_planner_bytes( + field_bits, + &witness_shape, + terminal_params.response_l2_sq_cap(), + ); total_bytes = total_bytes .checked_add(terminal_direct_bytes) .and_then(|value| value.checked_add(terminal_bytes)) @@ -283,9 +289,19 @@ pub(crate) fn walk_generated_schedule_entry( folds, CandidateTerminalResponse { params: terminal_params, - sparse_challenge_config: ring_challenge_config( - entry.terminal.inner_commit_matrix.ring_dimension as usize, - )?, + sparse_challenge_config: if entry.terminal.response_l2_sq_cap.is_some() { + akita_challenges::selective_l2_challenge_config( + entry.terminal.inner_commit_matrix.ring_dimension as usize, + ) + .ok_or_else(|| { + AkitaError::InvalidSetup( + "generated terminal L2 route has no certified operator-norm challenge" + .into(), + ) + })? + } else { + ring_challenge_config(entry.terminal.inner_commit_matrix.ring_dimension as usize)? + }, input_witness_len, estimated_direct_payload_bytes: terminal_direct_bytes, response_shape: witness_shape, diff --git a/crates/akita-schedules/src/group_batch.rs b/crates/akita-schedules/src/group_batch.rs index 757789bc0..6e0f23b02 100644 --- a/crates/akita-schedules/src/group_batch.rs +++ b/crates/akita-schedules/src/group_batch.rs @@ -32,7 +32,6 @@ pub(crate) fn multi_group_root_precommitted_groups_for_open_basis( sis_security_policy: policy.sis_security_policy, sis_table_digest: policy.sis_table_digest, sis_modulus_profile: policy.sis_modulus_profile, - ring_subfield_norm_bound: policy.ring_subfield_norm_bound, }; let groups = key .precommitteds diff --git a/crates/akita-schedules/src/lib.rs b/crates/akita-schedules/src/lib.rs index 9e3864f75..0735dd4a6 100644 --- a/crates/akita-schedules/src/lib.rs +++ b/crates/akita-schedules/src/lib.rs @@ -24,14 +24,18 @@ pub use resolve::{ ResolvedScheduleRow, }; pub use runtime::{ - default_sis_security_policy, PlannerCostModelId, PlannerPolicy, RecursiveSplitSearchPolicy, - RingDimensionScheduleMode, RuntimeSchedulePolicy, SelectionPolicyId, ADAPTIVE_SEARCH_LEVELS, + default_sis_security_policy, validate_policy, PlannerCostModelId, PlannerPolicy, + RecursiveSplitSearchPolicy, RingDimensionScheduleMode, RuntimeSchedulePolicy, + SelectionPolicyId, SelectiveL2ResponseModelId, ADAPTIVE_SEARCH_LEVELS, }; /// Shared schedule-construction primitives used by offline search and generated-row replay. #[doc(hidden)] pub mod planner_support { - pub use crate::candidate::{projected_collision_role_price, sis_key_at_dimension}; + pub use crate::candidate::{ + projected_collision_role_price, selective_l2_inner_matrix, sis_key_at_dimension, + SelectiveL2CandidateGeometry, + }; pub use crate::runtime::{ grouped_segment_rings, materialize_candidate_schedule, planned_next_witness_len, stage3_payload_bytes_for_successor, validate_policy, CandidateFoldStep, diff --git a/crates/akita-schedules/src/runtime.rs b/crates/akita-schedules/src/runtime.rs index 3dab574d7..755c951a7 100644 --- a/crates/akita-schedules/src/runtime.rs +++ b/crates/akita-schedules/src/runtime.rs @@ -18,6 +18,34 @@ pub enum PlannerCostModelId { ExactPayloadAndSetupEnvelope, } +/// Offline response-energy model used to admit selective L2 candidates. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum SelectiveL2ResponseModelId { + /// Do not derive modeled L2 caps. + Disabled, + /// Typed Z/E/T/R/compression moment propagation with extension tensor + /// packing and a Markov-backed grinding cap. + TypedProtocolMomentsV1, +} + +impl SelectiveL2ResponseModelId { + /// Stable identity tag. + pub const fn tag(self) -> u32 { + match self { + Self::Disabled => 0, + Self::TypedProtocolMomentsV1 => 1, + } + } + + /// Stable identity name. + pub const fn name(self) -> &'static str { + match self { + Self::Disabled => "Disabled", + Self::TypedProtocolMomentsV1 => "TypedProtocolMomentsV1", + } + } +} + impl PlannerCostModelId { /// Stable identity tag. pub const fn tag(self) -> u32 { @@ -160,6 +188,7 @@ impl RingDimensionScheduleMode { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct PlannerPolicy { pub cost_model: PlannerCostModelId, + pub selective_l2_response_model: SelectiveL2ResponseModelId, pub selection_policy: SelectionPolicyId, pub recursive_split_search_policy: RecursiveSplitSearchPolicy, /// Optional host admission budget for materialized setup field elements. @@ -178,7 +207,7 @@ pub struct PlannerPolicy { pub sis_modulus_profile: SisModulusProfileId, pub sis_security_policy: SisSecurityPolicyId, pub sis_table_digest: akita_types::SisTableDigest, - pub ring_subfield_norm_bound: u32, + pub sis_l2_table_digest: akita_types::SisL2TableDigest, pub claim_ext_degree: usize, pub chal_ext_degree: usize, /// Inclusive A/source decomposition basis domain at every level. @@ -193,6 +222,22 @@ pub struct PlannerPolicy { pub type RuntimeSchedulePolicy = PlannerPolicy; impl PlannerPolicy { + /// Number of physical witness chunks active at one fold level. + pub const fn chunks_at_level(&self, fold_level: usize) -> usize { + if self.witness_chunk.uses_multi_chunk() + && fold_level < self.witness_chunk.num_activated_levels + { + self.witness_chunk.num_chunks + } else { + 1 + } + } + + /// Whether this family opts into the typed suffix response model. + pub fn selective_l2_response_model_enabled(&self) -> bool { + self.selective_l2_response_model == SelectiveL2ResponseModelId::TypedProtocolMomentsV1 + } + /// Whether a candidate fits the optional host setup budget. pub fn admits_setup_field_elements(&self, num_field_elements: usize) -> bool { self.setup_field_budget @@ -231,7 +276,6 @@ impl PlannerPolicy { /// Suffix-DP depth cap shared by planner search and runtime policy validation. pub const MAX_RECURSION_DEPTH: usize = 12; - /// Validate runtime policy values used by schedule expansion and validation. pub fn validate_policy(policy: &PlannerPolicy) -> Result<(), AkitaError> { policy.challenge_field_bits()?; @@ -266,6 +310,13 @@ pub fn validate_policy(policy: &PlannerPolicy) -> Result<(), AkitaError> { "minimum offloaded witness contraction must be positive".to_string(), )); } + if policy.selective_l2_response_model_enabled() + && policy.sis_l2_table_digest != akita_types::SisL2TableDigest::CURRENT + { + return Err(AkitaError::InvalidSetup( + "selective L2 planning requires the current audited Euclidean table".into(), + )); + } for (label, (min, max), supported_max) in [ ("opening", policy.opening_basis_range, MAX_I8_LOG_BASIS), ("inner", policy.inner_basis_range, MAX_I16_LOG_BASIS), @@ -656,6 +707,7 @@ mod tests { fn adaptive_policy() -> PlannerPolicy { PlannerPolicy { cost_model: PlannerCostModelId::ExactPayloadAndSetupEnvelope, + selective_l2_response_model: SelectiveL2ResponseModelId::TypedProtocolMomentsV1, selection_policy: SelectionPolicyId::MinSetupMatrixFieldElementsThenProofPayload, recursive_split_search_policy: crate::RecursiveSplitSearchPolicy::Exhaustive, setup_field_budget: None, @@ -679,7 +731,7 @@ mod tests { sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, sis_security_policy: DEFAULT_SIS_SECURITY_POLICY, sis_table_digest: akita_types::SisTableDigest::CURRENT, - ring_subfield_norm_bound: 1, + sis_l2_table_digest: akita_types::SisL2TableDigest::CURRENT, claim_ext_degree: 1, chal_ext_degree: 1, inner_basis_range: (3, 16), @@ -697,6 +749,16 @@ mod tests { .expect("individually supported D512 A must not depend on the uniform-only field"); } + #[test] + fn typed_response_model_requires_current_l2_table_identity() { + let mut policy = adaptive_policy(); + policy.sis_l2_table_digest = akita_types::SisL2TableDigest([0; 32]); + let error = validate_policy(&policy).expect_err("stale L2 table identity"); + assert!(error + .to_string() + .contains("selective L2 planning requires the current audited Euclidean table")); + } + #[test] fn adaptive_dimensions_still_require_role_specific_dispatch_support() { const UNSUPPORTED_B_DIMENSIONS: &[usize] = &[64, 512]; diff --git a/crates/akita-sis-estimator/Cargo.toml b/crates/akita-sis-estimator/Cargo.toml index 7fba675cd..f7e2a5f71 100644 --- a/crates/akita-sis-estimator/Cargo.toml +++ b/crates/akita-sis-estimator/Cargo.toml @@ -21,6 +21,7 @@ libm = "0.2" num-bigint = "0.4.6" num-traits = "0.2" rayon = { version = "1.10", optional = true } +sha2 = "0.11" sha3 = "0.10.8" thiserror = "2.0" diff --git a/crates/akita-sis-estimator/examples/euclidean_width_table.rs b/crates/akita-sis-estimator/examples/euclidean_width_table.rs index b323a9e12..002b66527 100644 --- a/crates/akita-sis-estimator/examples/euclidean_width_table.rs +++ b/crates/akita-sis-estimator/examples/euclidean_width_table.rs @@ -5,15 +5,18 @@ use akita_sis_estimator::{ }, AkitaModulusProfileId, }; +use sha2::{Digest, Sha256}; use std::{ - env, fs, - io::{self, Write}, + env, + fmt::Write as _, + fs, + io::{self, Write as _}, path::{Path, PathBuf}, process, time::Instant, }; -const TABLE_HEADER: &str = "// AUTO-GENERATED by crates/akita-sis-estimator/examples/euclidean_width_table.rs -- do not edit by hand.\n//\n// SIS width thresholds for 128-bit security (BDGL16, Euclidean norm=2).\n// Rust estimator path: akita-sis-estimator::euclidean_width_table.\n// Keys are the union of power-of-two squared-collision buckets and derived keys K = d * B^2.\n\n"; +const TABLE_HEADER: &str = "// AUTO-GENERATED by crates/akita-sis-estimator/examples/euclidean_width_table.rs -- do not edit by hand.\n//\n// SIS width thresholds for 128-bit quantum security (ADPS16, Euclidean norm=2).\n// Rust estimator path: akita-sis-estimator::euclidean_width_table.\n// Keys bound the squared norm of the complete scalar collision vector.\n\n"; #[derive(Debug)] struct Args { @@ -98,28 +101,31 @@ impl Args { } fn write_csv_rows(rows: &[EuclideanWidthRow], output: Option<&PathBuf>) -> io::Result<()> { + let source = csv_source(rows); match output { Some(path) => { if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; } let mut file = fs::File::create(path)?; - write_csv_rows_to(&mut file, rows) + file.write_all(source.as_bytes()) } None => { let stdout = io::stdout(); let mut handle = stdout.lock(); - write_csv_rows_to(&mut handle, rows) + handle.write_all(source.as_bytes()) } } } -fn write_csv_rows_to(mut writer: impl Write, rows: &[EuclideanWidthRow]) -> io::Result<()> { - writeln!(writer, "{}", EuclideanWidthRow::csv_header())?; +fn csv_source(rows: &[EuclideanWidthRow]) -> String { + let mut source = String::new(); + writeln!(&mut source, "{}", EuclideanWidthRow::csv_header()) + .expect("writing to String cannot fail"); for row in rows { - writeln!(writer, "{}", row.to_csv_record())?; + writeln!(&mut source, "{}", row.to_csv_record()).expect("writing to String cannot fail"); } - Ok(()) + source } fn write_rust_split( @@ -128,10 +134,13 @@ fn write_rust_split( output: Option<&Path>, ) -> io::Result<()> { let default_out_dir = - Path::new(env!("CARGO_MANIFEST_DIR")).join("../akita-types/src/sis/generated_sis_table"); + Path::new(env!("CARGO_MANIFEST_DIR")).join("../akita-types/src/sis/generated_l2_sis_table"); let out_dir = output.unwrap_or(default_out_dir.as_path()); fs::create_dir_all(out_dir)?; - fs::write(out_dir.join("mod.rs"), rust_mod_source())?; + let audit_source = csv_source(rows); + let table_digest: [u8; 32] = Sha256::digest(audit_source.as_bytes()).into(); + fs::write(out_dir.join("audit.csv"), audit_source)?; + fs::write(out_dir.join("mod.rs"), rust_mod_source(table_digest))?; let arms = rust_table_arms(rows, config.max_rank); for family in [ AkitaModulusProfileId::Q32Offset99, @@ -146,9 +155,21 @@ fn write_rust_split( Ok(()) } -fn rust_mod_source() -> String { +fn rust_mod_source(table_digest: [u8; 32]) -> String { + let digest = table_digest + .chunks(16) + .map(|chunk| { + let bytes = chunk + .iter() + .map(|byte| format!("0x{byte:02x}")) + .collect::>() + .join(", "); + format!(" {bytes},") + }) + .collect::>() + .join("\n"); format!( - "{TABLE_HEADER}mod q128;\nmod q32;\nmod q64;\n\nuse super::SisModulusProfileId;\n\n/// Generated SIS max-width table: for each `(family, d, collision_l2_sq)` the\n/// maximum secure ring-element width per module rank (`widths[rank - 1]`).\n#[rustfmt::skip]\npub(crate) fn sis_max_widths(\n family: SisModulusProfileId,\n d: u32,\n collision_l2_sq: u128,\n) -> Option<&'static [u64]> {{\n match family {{\n SisModulusProfileId::Q32Offset99 => q32::sis_max_widths(d, collision_l2_sq),\n SisModulusProfileId::Q64Offset59 => q64::sis_max_widths(d, collision_l2_sq),\n SisModulusProfileId::Q128OffsetA7F7 => q128::sis_max_widths(d, collision_l2_sq),\n }}\n}}\n" + "{TABLE_HEADER}mod q128;\nmod q32;\nmod q64;\n\nuse super::SisModulusProfileId;\n\n/// SHA-256 digest of the generated audit CSV, including every accepted boundary and rejected successor.\npub(crate) const TABLE_DIGEST: [u8; 32] = [\n{digest}\n];\n\n/// Generated SIS max-width table: for each `(family, d, collision_l2_sq)` the\n/// maximum secure ring-element width per module rank (`widths[rank - 1]`).\n#[rustfmt::skip]\npub(crate) fn sis_max_widths(\n family: SisModulusProfileId,\n d: u32,\n collision_l2_sq: u128,\n) -> Option<&'static [u64]> {{\n match family {{\n SisModulusProfileId::Q32Offset99 => q32::sis_max_widths(d, collision_l2_sq),\n SisModulusProfileId::Q64Offset59 => q64::sis_max_widths(d, collision_l2_sq),\n SisModulusProfileId::Q128OffsetA7F7 => q128::sis_max_widths(d, collision_l2_sq),\n }}\n}}\n" ) } diff --git a/crates/akita-sis-estimator/src/akita.rs b/crates/akita-sis-estimator/src/akita.rs index e3f6d0dac..5f4d33742 100644 --- a/crates/akita-sis-estimator/src/akita.rs +++ b/crates/akita-sis-estimator/src/akita.rs @@ -128,9 +128,13 @@ pub fn scalar_sis_from_ring_wide( /// Build Euclidean scalar SIS parameters from Akita ring coordinates. /// -/// This is the mapping used by the shipped L2 table: +/// This is the mapping used by the L2 table: /// `n = rank * d`, `m = width * d`, and -/// `length_bound = sqrt(width * collision_l2_sq)`. +/// `length_bound = sqrt(collision_l2_sq)`. +/// +/// `collision_l2_sq` bounds the complete scalar collision vector across all +/// `width` input ring rows. Multiplying it by `width` here would count those +/// rows twice. /// /// # Errors /// @@ -162,12 +166,11 @@ pub fn scalar_sis_from_ring_euclidean( field: "m", reason: "width * ring_dimension overflowed u64".to_string(), })?; - let radicand = BigUint::from(width) * BigUint::from(collision_l2_sq); SisParameters::try_new( n, family.modulus(), Some(m), - Bound::sqrt_integer(radicand), + Bound::sqrt_integer(BigUint::from(collision_l2_sq)), SisNorm::Euclidean, ) } @@ -194,8 +197,25 @@ mod tests { assert_eq!(params.m, Some(64)); assert_eq!( params.length_bound, - Bound::sqrt_integer(BigUint::from(256u32)) + Bound::sqrt_integer(BigUint::from(128u32)) ); assert_eq!(params.norm, SisNorm::Euclidean); } + + #[test] + fn euclidean_length_bound_is_independent_of_matrix_width() { + let narrow = + scalar_sis_from_ring_euclidean(AkitaModulusProfileId::Q64Offset59, 64, 2, 3, 1 << 40) + .unwrap(); + let wide = scalar_sis_from_ring_euclidean( + AkitaModulusProfileId::Q64Offset59, + 64, + 2, + 3_000, + 1 << 40, + ) + .unwrap(); + assert_eq!(narrow.length_bound, wide.length_bound); + assert_ne!(narrow.m, wide.m); + } } diff --git a/crates/akita-sis-estimator/src/config.rs b/crates/akita-sis-estimator/src/config.rs index 40e96f1c1..707c3c36c 100644 --- a/crates/akita-sis-estimator/src/config.rs +++ b/crates/akita-sis-estimator/src/config.rs @@ -216,12 +216,17 @@ impl EstimateConfig { } } - /// Akita Euclidean table generation profile: BDGL16 with the Euclidean - /// SIS lattice path used by the shipped 128-bit L2 table. + /// Akita Euclidean table generation profile: ADPS16 quantum at 128 bits. + /// + /// The Euclidean SIS geometry determines the required BKZ block size. The + /// reduction is priced with the same ADPS16 quantum model as the production + /// coefficient-L∞ table. #[must_use] pub fn akita_euclidean_table() -> Self { Self { - red_cost_model: ReductionCostModel::Bdgl16, + red_cost_model: ReductionCostModel::Adps16 { + mode: Adps16Mode::Quantum, + }, ..Self::default() } } @@ -378,4 +383,14 @@ mod tests { } ); } + + #[test] + fn euclidean_table_uses_the_quantum_adps16_gate() { + assert_eq!( + EstimateConfig::akita_euclidean_table().red_cost_model, + ReductionCostModel::Adps16 { + mode: Adps16Mode::Quantum, + } + ); + } } diff --git a/crates/akita-sis-estimator/src/euclidean.rs b/crates/akita-sis-estimator/src/euclidean.rs index 1982ce9fa..9807b2bbb 100644 --- a/crates/akita-sis-estimator/src/euclidean.rs +++ b/crates/akita-sis-estimator/src/euclidean.rs @@ -9,7 +9,7 @@ use crate::{ error::{EstimatorError, Result}, math::log2_biguint, params::SisParameters, - reduction::{bdgl16_log2_cost, beta as beta_from_delta, delta, validate_euclidean_reduction}, + reduction::{adps16_log2_cost, beta as beta_from_delta, delta, validate_euclidean_reduction}, }; /// Evaluate the lattice-estimator Euclidean SIS path for the configured model. @@ -57,7 +57,9 @@ pub fn cost_euclidean(params: &SisParameters, config: &EstimateConfig) -> Result let predicate = reduction_possible && lower_bound_met; let cost = if predicate { match config.red_cost_model { - ReductionCostModel::Bdgl16 => CostValue::finite_log2(bdgl16_log2_cost(beta, d)), + ReductionCostModel::Adps16 { mode } => { + CostValue::finite_log2(adps16_log2_cost(beta, mode)) + } _ => unreachable!("validated above"), } } else { @@ -111,6 +113,7 @@ fn length_bound_exceeds_euclidean_lower_bound(params: &SisParameters, d: u64, lo #[cfg(test)] mod tests { use crate::{ + config::Adps16Mode, params::{akita_q32, Bound, SisNorm}, EstimateConfig, }; @@ -130,7 +133,9 @@ mod tests { let cost = cost_euclidean( ¶ms, &EstimateConfig { - red_cost_model: ReductionCostModel::Bdgl16, + red_cost_model: ReductionCostModel::Adps16 { + mode: Adps16Mode::Quantum, + }, lattice_dimension: Some(40), ..EstimateConfig::default() }, @@ -153,11 +158,41 @@ mod tests { let cost = cost_euclidean( ¶ms, &EstimateConfig { - red_cost_model: ReductionCostModel::Bdgl16, + red_cost_model: ReductionCostModel::Adps16 { + mode: Adps16Mode::Quantum, + }, ..EstimateConfig::default() }, ) .unwrap(); assert_eq!(cost.rop, CostValue::Infinity); } + + #[test] + fn euclidean_quantum_cost_uses_adps16_exponent() { + let params = SisParameters::try_new( + 16, + BigUint::from(1u32) << 20usize, + Some(64), + Bound::from_u64(1024), + SisNorm::Euclidean, + ) + .unwrap(); + let cost = cost_euclidean( + ¶ms, + &EstimateConfig { + red_cost_model: ReductionCostModel::Adps16 { + mode: Adps16Mode::Quantum, + }, + lattice_dimension: Some(64), + ..EstimateConfig::default() + }, + ) + .unwrap(); + let beta = cost.beta.expect("Euclidean estimate has a BKZ block size"); + assert_eq!( + cost.rop, + CostValue::finite_log2(adps16_log2_cost(beta, Adps16Mode::Quantum)) + ); + } } diff --git a/crates/akita-sis-estimator/src/euclidean_width_table.rs b/crates/akita-sis-estimator/src/euclidean_width_table.rs index 659dd5d02..e12a40355 100644 --- a/crates/akita-sis-estimator/src/euclidean_width_table.rs +++ b/crates/akita-sis-estimator/src/euclidean_width_table.rs @@ -26,12 +26,6 @@ pub const EUCLIDEAN_RING_DIMS: &[u32] = &[32, 64, 128, 256, 512]; pub const MIN_LOG_BUCKET: u32 = 1; /// Largest squared-collision power-of-two bucket in the shipped L2 table. pub const MAX_LOG_BUCKET: u32 = 84; -/// Coefficient-L∞ buckets used to derive extra L2 collision keys. -pub const COEFF_LINF_BUCKETS: &[u64] = &[ - 2, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131_071, - 262_143, 524_287, 1_048_575, 2_097_151, 4_194_303, 8_388_607, 16_777_215, 33_554_431, - 67_108_863, -]; /// One Euclidean max-width generation request. #[derive(Clone, Debug, PartialEq)] pub struct EuclideanWidthTableConfig { @@ -129,10 +123,7 @@ impl EuclideanWidthRow { /// Return the full collision-key set used by the shipped L2 table. #[must_use] pub fn l2_table_collision_keys() -> Vec { - let mut keys = BTreeSet::new(); - keys.extend(power_of_two_collision_keys()); - keys.extend(derived_l2_collision_keys()); - keys.into_iter().collect() + power_of_two_collision_keys() } /// Return `2^MIN_LOG_BUCKET ..= 2^MAX_LOG_BUCKET`. @@ -143,28 +134,6 @@ pub fn power_of_two_collision_keys() -> Vec { .collect() } -/// Return the derived keys `d * B^2` used by the production table. -#[must_use] -pub fn derived_l2_collision_keys() -> Vec { - let mut keys = BTreeSet::new(); - for &d in EUCLIDEAN_RING_DIMS { - for &bound in COEFF_LINF_BUCKETS { - keys.insert(u128::from(d) * coeff_linf_bucket_sq(bound)); - } - } - keys.into_iter().collect() -} - -/// Return `B²` for a coefficient-L∞ bucket without float rounding. -#[must_use] -pub fn coeff_linf_bucket_sq(bound: u64) -> u128 { - if bound <= 3 { - return u128::from(bound) * u128::from(bound); - } - let k = (bound + 1).ilog2(); - (1u128 << (2 * k)) - (1u128 << (k + 1)) + 1 -} - /// Generate row-oriented Euclidean max-width comparison data. pub fn generate_euclidean_width_rows( config: &EuclideanWidthTableConfig, @@ -505,11 +474,10 @@ mod tests { use super::*; #[test] - fn derived_collision_keys_match_python_contract() { - assert_eq!(coeff_linf_bucket_sq(15), 225); - assert_eq!(coeff_linf_bucket_sq(31), 961); - assert!(derived_l2_collision_keys().contains(&(32 * 15 * 15))); - assert!(l2_table_collision_keys().contains(&(1u128 << 84))); + fn production_collision_keys_are_exact_power_of_two_buckets() { + assert_eq!(l2_table_collision_keys(), power_of_two_collision_keys()); + assert_eq!(l2_table_collision_keys().first(), Some(&(1u128 << 1))); + assert_eq!(l2_table_collision_keys().last(), Some(&(1u128 << 84))); } #[test] diff --git a/crates/akita-sis-estimator/src/reduction/mod.rs b/crates/akita-sis-estimator/src/reduction/mod.rs index cf490098b..cb85a39f5 100644 --- a/crates/akita-sis-estimator/src/reduction/mod.rs +++ b/crates/akita-sis-estimator/src/reduction/mod.rs @@ -35,9 +35,9 @@ pub fn validate_infinity_reduction(model: ReductionCostModel) -> Result<()> { /// Euclidean SIS path. pub fn validate_euclidean_reduction(model: ReductionCostModel) -> Result<()> { match model { - ReductionCostModel::Bdgl16 => Ok(()), - ReductionCostModel::Adps16 { .. } => Err(EstimatorError::Unsupported { - feature: "euclidean red_cost_model::ADPS16", + ReductionCostModel::Adps16 { .. } => Ok(()), + ReductionCostModel::Bdgl16 => Err(EstimatorError::Unsupported { + feature: "euclidean red_cost_model::BDGL16 (retired; use ADPS16 quantum)", }), ReductionCostModel::Matzov { .. } => Err(EstimatorError::Unsupported { feature: "euclidean red_cost_model::Matzov", diff --git a/crates/akita-sis-estimator/tests/euclidean_width_goldens.rs b/crates/akita-sis-estimator/tests/euclidean_width_goldens.rs index 9a09c88d5..d532a5b73 100644 --- a/crates/akita-sis-estimator/tests/euclidean_width_goldens.rs +++ b/crates/akita-sis-estimator/tests/euclidean_width_goldens.rs @@ -50,6 +50,43 @@ fn euclidean_width_goldens_match_current_l2_table_replay() { } } +#[test] +fn euclidean_width_goldens_match_checked_in_l2_table() { + use akita_types::sis::{ + min_secure_l2_rank, sis_l2_table_key_for_collision_sq, SisL2TableDigest, + SisModulusProfileId, DEFAULT_SIS_SECURITY_POLICY, + }; + + for row in parse_rows() { + let profile = match row.family { + AkitaModulusProfileId::Q32Offset99 => SisModulusProfileId::Q32Offset99, + AkitaModulusProfileId::Q64Offset59 => SisModulusProfileId::Q64Offset59, + AkitaModulusProfileId::Q128OffsetA7F7 => SisModulusProfileId::Q128OffsetA7F7, + }; + let key = sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest::CURRENT, + profile, + row.d, + row.collision_l2_sq, + ) + .unwrap_or_else(|| panic!("missing checked-in L2 table key for {row:?}")); + let secure_rank = min_secure_l2_rank(key, row.max_width) + .unwrap_or_else(|| panic!("golden width is unsupported for {row:?}")); + assert!( + secure_rank <= row.rank as usize, + "golden width exceeds the checked-in rank boundary for {row:?}" + ); + if row.max_width < row.search_cap { + let next_rank = min_secure_l2_rank(key, row.max_width + 1); + assert!( + next_rank.is_none_or(|rank| rank > row.rank as usize), + "checked-in rank boundary exceeds the independent golden for {row:?}" + ); + } + } +} + fn parse_rows() -> Vec { let mut lines = GOLDEN_CSV.lines(); let header = lines.next().unwrap(); diff --git a/crates/akita-transcript/src/labels.rs b/crates/akita-transcript/src/labels.rs index 295d3bce1..9ca963168 100644 --- a/crates/akita-transcript/src/labels.rs +++ b/crates/akita-transcript/src/labels.rs @@ -37,12 +37,24 @@ pub const ABSORB_SUMCHECK_ROUND: &[u8] = b"ak/a/scr"; pub const CHALLENGE_SUMCHECK_ROUND: &[u8] = b"ak/c/scr"; /// Absorb the stage-1 final `range_image_evaluation` before the batching challenge. pub const ABSORB_RANGE_IMAGE_EVALUATION: &[u8] = b"ak/a/scs"; +/// Absorb the exact public integer square sum on an L2-selected fold. +pub const ABSORB_L2_NORM_INTEGER: &[u8] = b"ak/a/l2n"; +/// Absorb one canonical blockwise limb inner-product claim. +pub const ABSORB_L2_NORM_SUBCLAIM: &[u8] = b"ak/a/l2s"; +/// Absorb one final Stage-1 physical response or limb evaluation. +pub const ABSORB_L2_VIRTUAL_EVALUATION: &[u8] = b"ak/a/l2v"; /// Absorb the stage-2 next-witness evaluation handoff before recursion continues. pub const ABSORB_STAGE2_NEXT_W_EVAL: &[u8] = b"ak/a/s2w"; /// Absorb stage-1 inter-stage claims before batching them into the next stage. pub const ABSORB_SUMCHECK_INTERSTAGE_CLAIM: &[u8] = b"ak/a/sci"; /// Challenge for batched sumcheck coefficient sampling. pub const CHALLENGE_SUMCHECK_BATCH: &[u8] = b"ak/c/scb"; +/// Challenge batching canonical blockwise L2 norm subclaims. +pub const CHALLENGE_L2_NORM_BATCH: &[u8] = b"ak/c/l2b"; +/// Challenge merging the range and norm identities in the final Stage-1 leaf. +pub const CHALLENGE_L2_NORM_MERGE: &[u8] = b"ak/c/l2m"; +/// Challenge batching Stage-2 bindings of L2 virtual evaluations. +pub const CHALLENGE_L2_VIRTUAL_BATCH: &[u8] = b"ak/c/l2v"; /// Challenge batching the support-restricted negative-binary compression check. pub const CHALLENGE_COMPRESSION_BINARY: &[u8] = b"ak/c/cb"; /// Challenge for batching stage-1 inter-stage claims into the next tree stage. @@ -98,9 +110,15 @@ pub const ALL_LABELS: &[&[u8]] = &[ ABSORB_SUMCHECK_ROUND, CHALLENGE_SUMCHECK_ROUND, ABSORB_RANGE_IMAGE_EVALUATION, + ABSORB_L2_NORM_INTEGER, + ABSORB_L2_NORM_SUBCLAIM, + ABSORB_L2_VIRTUAL_EVALUATION, ABSORB_STAGE2_NEXT_W_EVAL, ABSORB_SUMCHECK_INTERSTAGE_CLAIM, CHALLENGE_SUMCHECK_BATCH, + CHALLENGE_L2_NORM_BATCH, + CHALLENGE_L2_NORM_MERGE, + CHALLENGE_L2_VIRTUAL_BATCH, CHALLENGE_COMPRESSION_BINARY, CHALLENGE_SUMCHECK_INTERSTAGE_BATCH, ABSORB_STOP_CONDITION, diff --git a/crates/akita-types/src/field_reduction/tests.rs b/crates/akita-types/src/field_reduction/tests.rs index b0ca902dd..572d9887c 100644 --- a/crates/akita-types/src/field_reduction/tests.rs +++ b/crates/akita-types/src/field_reduction/tests.rs @@ -353,6 +353,53 @@ fn embed_subfield_matches_psi_embed_first_slot() { assert_psi_embed_slot_zero_matches_embed_subfield::<128, 16>(); } +#[test] +fn pre_psi_digit_conversion_is_charged_once_before_physical_a_sizing() { + use crate::sis::{ + role_a_collision_inf_norm_for_response_bound, role_a_collision_l2_sq_for_response_bound, + }; + use crate::SisModulusProfileId; + + // Two logical degree-four values with unit coordinates overlap under psi. + // The logical infinity norm is one, while the actual packed coefficient + // vector already carries the conversion cost with infinity norm two. + let logical = vec![1i8; 8]; + let physical = pack_tensor_base_lift_i8_digits::<8>(&logical, 4, 4).unwrap(); + assert_eq!(physical, vec![1, 2, 2, 2, 1, 0, 0, 0]); + let physical_linf = physical + .iter() + .map(|value| value.unsigned_abs() as u128) + .max() + .unwrap(); + let physical_l2_sq = physical.iter().fold(0u128, |sum, value| { + let magnitude = value.unsigned_abs() as u128; + sum + magnitude * magnitude + }); + assert_eq!((physical_linf, physical_l2_sq), (2, 14)); + + let challenge_l1 = 7u128; + let expected_linf = 8 * challenge_l1 * physical_linf; + let expected_l2_sq = 64 * challenge_l1 * challenge_l1 * physical_l2_sq; + for profile in [ + SisModulusProfileId::Q128OffsetA7F7, + SisModulusProfileId::Q64Offset59, + SisModulusProfileId::Q32Offset99, + ] { + // The physical A formulas are profile independent. In particular, + // fp32/fp64 do not multiply the already packed norms by another psi + // factor. + let _physical_profile = profile; + assert_eq!( + role_a_collision_inf_norm_for_response_bound(challenge_l1, physical_linf), + Some(expected_linf) + ); + assert_eq!( + role_a_collision_l2_sq_for_response_bound(challenge_l1, physical_l2_sq), + Some(expected_l2_sq) + ); + } +} + fn assert_embed_subfield_scales_packed_slots() { let params = SubfieldParams::::new().unwrap(); let packed_len = D / K; diff --git a/crates/akita-types/src/golomb_rice.rs b/crates/akita-types/src/golomb_rice.rs index 5f048d411..c095ab259 100644 --- a/crates/akita-types/src/golomb_rice.rs +++ b/crates/akita-types/src/golomb_rice.rs @@ -237,20 +237,6 @@ pub fn sample_optimal_rice_low_bits(values: &[i64], zigzag_w: u32, low_bits_hi: .unwrap_or(0) } -/// Payload byte length for each `rice_low_bits` in `0..=low_bits_hi` on a realized `z` sample. -pub fn golomb_rice_low_bits_sweep_payload_bytes( - values: &[i64], - zigzag_w: u32, - low_bits_hi: u32, -) -> Result, AkitaError> { - (0..=low_bits_hi) - .map(|rice_low_bits| { - let bits = golomb_rice_total_bits(values, rice_low_bits, zigzag_w)?; - Ok((rice_low_bits, bits.div_ceil(8))) - }) - .collect() -} - /// Distribution summary for terminal fold-response `z` coefficients. #[derive(Debug, Clone, PartialEq)] pub struct ZFoldEncodingStats { @@ -405,6 +391,29 @@ pub fn golomb_rice_total_wire_bits( }) } +/// Conservative planner estimate for an L2-bounded Golomb-Rice payload. +/// +/// The zigzag magnitude is at most `2 * |z_i|`. Cauchy-Schwarz gives +/// `sum_i |z_i| <= floor(sqrt(num_values * l2_sq_cap))`, which bounds the +/// complete unary-quotient contribution without a distributional assumption. +/// This estimate does not replace the scheduled payload cap enforced on wire. +#[must_use] +pub fn golomb_rice_l2_planner_payload_bytes( + num_values: usize, + l2_sq_cap: u128, + rice_low_bits: u32, +) -> Option { + let num_values_u128 = u128::try_from(num_values).ok()?; + let sum_abs_bound = num_values_u128.checked_mul(l2_sq_cap)?.isqrt(); + let quotient_sum_bound = sum_abs_bound.checked_mul(2)?.checked_shr(rice_low_bits)?; + let fixed_bits = num_values.checked_mul(rice_low_bits as usize + 1)?; + let quotient_bits = usize::try_from(quotient_sum_bound).ok()?; + fixed_bits + .checked_add(quotient_bits)? + .checked_add(7) + .map(|bits| bits / 8) +} + /// Whether every coefficient lies in `[-cap, cap]`. pub fn golomb_rice_values_within_cap(values: &[i64], cap: u128) -> Result<(), AkitaError> { for &n in values { @@ -630,6 +639,55 @@ mod tests { .unwrap_or(0) } + #[test] + fn l2_planner_payload_bound_contains_actual_encodings() { + let rice_low_bits = 4; + let cases = [ + vec![0i64; 64], + vec![7i64; 64], + { + let mut sparse = vec![0i64; 64]; + sparse[0] = 127; + sparse[17] = -31; + sparse + }, + (0..64) + .map(|index| if index % 2 == 0 { 15 } else { -16 }) + .collect(), + ]; + + for values in cases { + let l2_sq_cap = values.iter().fold(0u128, |acc, &value| { + acc + i128::from(value).unsigned_abs().pow(2) + }); + let zigzag_w = golomb_rice_zigzag_width( + values + .iter() + .map(|&value| i128::from(value).unsigned_abs()) + .max() + .unwrap_or(0), + ); + let encoded = golomb_rice_encode_vec(&values, rice_low_bits, zigzag_w).expect("encode"); + let estimate = + golomb_rice_l2_planner_payload_bytes(values.len(), l2_sq_cap, rice_low_bits) + .expect("planner estimate"); + assert!( + encoded.len() <= estimate, + "actual payload {} exceeds L2 estimate {estimate}", + encoded.len() + ); + } + } + + #[test] + fn l2_planner_payload_estimate_tracks_energy() { + let low = + golomb_rice_l2_planner_payload_bytes(1024, 1 << 20, 9).expect("low-energy estimate"); + let high = + golomb_rice_l2_planner_payload_bytes(1024, 1 << 30, 9).expect("high-energy estimate"); + assert!(low < high); + } + #[test] fn golomb_rice_round_trips_cap_range_at_wire_low_bits() { for cap in [504u128, 1008, 1568, 2016] { diff --git a/crates/akita-types/src/instance_descriptor/tests.rs b/crates/akita-types/src/instance_descriptor/tests.rs index b94c5a9f9..f27e5207d 100644 --- a/crates/akita-types/src/instance_descriptor/tests.rs +++ b/crates/akita-types/src/instance_descriptor/tests.rs @@ -8,12 +8,28 @@ use crate::{ use akita_challenges::SparseChallengeConfig; use akita_field::Prime32Offset99; +// `pm1_only(3)` prices the fixtures' response cap 127 below A bucket 4095. +const TEST_TERMINAL_A_BUCKET: u128 = 4_095; + fn sample_schedule() -> FoldSchedule { let sparse = SparseChallengeConfig::pm1_only(3); - let committed = + let mut committed = CommittedGroupParams::params_only(SisModulusProfileId::Q32Offset99, 64, 3, 4, 3, 2, sparse) .with_decomp(4, 32, 2, 2, 2) .expect("sample committed params"); + let inner = committed.inner_commit_matrix; + committed.inner_commit_matrix = InnerCommitMatrixParams::new_unchecked( + inner.security_policy(), + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, + inner.sis_modulus_profile(), + inner.output_rank(), + inner.input_width(), + TEST_TERMINAL_A_BUCKET, + inner.ring_dimension(), + ); let (terminal_witness, admission_cap) = TerminalCommittedGroupParams::try_from_expanded_group(committed.clone()) .expect("terminal response bounds"); @@ -229,11 +245,14 @@ fn role_local_ring_dimension_changes_plan_binding() { .commitment .inner_commit_matrix = InnerCommitMatrixParams::new_unchecked( matrix.security_policy(), - matrix.sis_table_key().table_digest, + matrix + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, matrix.sis_modulus_profile(), matrix.output_rank(), matrix.input_width(), - matrix.coeff_linf_bound(), + matrix.coeff_linf_bound().expect("L infinity test matrix"), matrix.ring_dimension() * 2, ); diff --git a/crates/akita-types/src/layout/mod.rs b/crates/akita-types/src/layout/mod.rs index 6a8a8dbad..074e89c1f 100644 --- a/crates/akita-types/src/layout/mod.rs +++ b/crates/akita-types/src/layout/mod.rs @@ -30,7 +30,8 @@ pub use params::{ pub use proof_size::{ extension_opening_reduction_level_bytes, extension_opening_reduction_proof_bytes, field_bytes, packed_digits_bytes, padded_boolean_opening_vars, proof_ring_vec_bytes, sumcheck_rounds, - terminal_response_bytes, try_extension_opening_reduction_level_bytes, + terminal_response_bytes, terminal_response_planner_bytes, + try_extension_opening_reduction_level_bytes, }; pub use ring_dims::{ validate_role_dims, validate_schedule_ring_dims, CommitmentRingDims, RingRole, MAX_FOLD_LEVELS, diff --git a/crates/akita-types/src/layout/params.rs b/crates/akita-types/src/layout/params.rs index b9391b66e..f5e6746b4 100644 --- a/crates/akita-types/src/layout/params.rs +++ b/crates/akita-types/src/layout/params.rs @@ -396,33 +396,27 @@ impl CommittedGroupParams { params: &(impl LevelParamsLike + ?Sized), ) -> Result { let inner_commit_matrix = params.inner_commit_matrix_params(); - if inner_commit_matrix.sis_table_key().role != crate::sis::SisMatrixRole::Inner { + let table_key = inner_commit_matrix.sis_table_key().ok_or_else(|| { + AkitaError::InvalidSetup( + "terminal response requires an L-infinity A-role matrix".to_string(), + ) + })?; + if table_key.role != crate::sis::SisMatrixRole::Inner { return Err(AkitaError::InvalidSetup( "terminal response requires an A-role inner matrix".to_string(), )); } - let collision_capacity = - inner_commit_matrix - .max_secure_collision_linf() - .ok_or_else(|| { - AkitaError::InvalidSetup( - "terminal inner matrix has no supported SIS collision capacity".to_string(), - ) - })?; + // Bind the terminal wire to the selected SIS bucket. A larger bucket + // that the same rank happens to support is unused schedule slack. + let collision_capacity = table_key.coeff_linf_bound; let challenge = crate::sis::FoldChallengeNorms::new(&self.fold_challenge_config); - crate::sis::max_response_linf_for_role_a_collision( - collision_capacity, - challenge.l1_norm, - inner_commit_matrix - .sis_modulus_profile() - .ring_subfield_embedding_norm_bound(), - ) - .filter(|&limit| limit > 0) - .ok_or_else(|| { - AkitaError::InvalidSetup( - "terminal inner matrix cannot certify a nonzero folded response".to_string(), - ) - }) + crate::sis::max_response_linf_for_role_a_collision(collision_capacity, challenge.l1_norm) + .filter(|&limit| limit > 0) + .ok_or_else(|| { + AkitaError::InvalidSetup( + "terminal inner matrix cannot certify a nonzero folded response".to_string(), + ) + }) } /// Number of Boolean coordinates in the block-index domain. @@ -1082,15 +1076,7 @@ impl CommittedGroupParams { log_basis_inner: self.log_basis_inner, log_basis_outer: self.log_basis_outer, log_basis_open: self.log_basis_open, - inner_commit_matrix: InnerCommitMatrixParams::new_unchecked( - self.inner_commit_matrix.security_policy(), - self.inner_commit_matrix.sis_table_key().table_digest, - self.inner_commit_matrix.sis_modulus_profile(), - self.inner_commit_matrix.output_rank, - inner_width, - self.inner_commit_matrix.coeff_linf_bound(), - self.inner_commit_matrix.ring_dimension(), - ), + inner_commit_matrix: self.inner_commit_matrix.try_with_input_width(inner_width)?, outer_commit_matrix: OuterCommitMatrixParams::new_unchecked( self.outer_commit_matrix.security_policy(), self.outer_commit_matrix.sis_table_key().table_digest, @@ -1146,15 +1132,9 @@ impl CommittedGroupParams { log_basis_inner: other.log_basis_inner, log_basis_outer: other.log_basis_outer, log_basis_open: other.log_basis_open, - inner_commit_matrix: InnerCommitMatrixParams::new_unchecked( - self.inner_commit_matrix.security_policy(), - self.inner_commit_matrix.sis_table_key().table_digest, - self.inner_commit_matrix.sis_modulus_profile(), - self.inner_commit_matrix.output_rank, - other.inner_commit_matrix.input_width, - self.inner_commit_matrix.coeff_linf_bound(), - self.inner_commit_matrix.ring_dimension(), - ), + inner_commit_matrix: self + .inner_commit_matrix + .try_with_input_width(other.inner_commit_matrix.input_width)?, outer_commit_matrix: OuterCommitMatrixParams::new_unchecked( self.outer_commit_matrix.security_policy(), self.outer_commit_matrix.sis_table_key().table_digest, diff --git a/crates/akita-types/src/layout/params/precommitted.rs b/crates/akita-types/src/layout/params/precommitted.rs index a4b755f7a..a512db550 100644 --- a/crates/akita-types/src/layout/params/precommitted.rs +++ b/crates/akita-types/src/layout/params/precommitted.rs @@ -42,8 +42,6 @@ pub struct PrecommittedGroupAdmissionPolicy { pub sis_table_digest: SisTableDigest, /// Modulus family required for both frozen matrices. pub sis_modulus_profile: SisModulusProfileId, - /// Subfield norm factor used in the A-role bound. - pub ring_subfield_norm_bound: u32, } impl PartialEq for PrecommittedLevelParams { @@ -126,10 +124,15 @@ impl PrecommittedLevelParams { log_basis_open, &fold_challenge_config, num_digits_fold, - policy.ring_subfield_norm_bound, ) .ok_or_else(|| AkitaError::InvalidSetup("no precommitted A-role norm".into()))?; - if required_a_bound > layout.inner_commit_matrix.coeff_linf_bound() { + let declared_a_bound = layout + .inner_commit_matrix + .coeff_linf_bound() + .ok_or_else(|| { + AkitaError::InvalidSetup("precommitted A cannot use an L2 security route".into()) + })?; + if required_a_bound > declared_a_bound { return Err(AkitaError::InvalidSetup( "precommitted A bound does not cover the certified opening basis".into(), )); diff --git a/crates/akita-types/src/layout/params/tests/mod.rs b/crates/akita-types/src/layout/params/tests/mod.rs index f7d148c1b..ef07361af 100644 --- a/crates/akita-types/src/layout/params/tests/mod.rs +++ b/crates/akita-types/src/layout/params/tests/mod.rs @@ -63,7 +63,10 @@ fn certify_test_sis_bounds(lp: &mut CommittedGroupParams) { const OUTER_BOUND: u128 = 3; lp.inner_commit_matrix = InnerCommitMatrixParams::new_unchecked( lp.inner_commit_matrix.security_policy(), - lp.inner_commit_matrix.sis_table_key().table_digest, + lp.inner_commit_matrix + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, lp.inner_commit_matrix.sis_modulus_profile(), lp.inner_commit_matrix.output_rank(), lp.inner_commit_matrix.input_width(), diff --git a/crates/akita-types/src/layout/params/tests/params_precommitted_group_tests.rs b/crates/akita-types/src/layout/params/tests/params_precommitted_group_tests.rs index d35e1309d..318ab6be2 100644 --- a/crates/akita-types/src/layout/params/tests/params_precommitted_group_tests.rs +++ b/crates/akita-types/src/layout/params/tests/params_precommitted_group_tests.rs @@ -136,7 +136,6 @@ fn precommit_admission_fixture() -> ( sis_security_policy: crate::sis::DEFAULT_SIS_SECURITY_POLICY, sis_table_digest: crate::SisTableDigest::CURRENT, sis_modulus_profile: SisModulusProfileId::Q128OffsetA7F7, - ring_subfield_norm_bound: 1, }; let num_digits_fold = 2; let a_bound = crate::sis::rounded_up_role_a_inf_norm( @@ -147,7 +146,6 @@ fn precommit_admission_fixture() -> ( 3, &challenge, num_digits_fold, - policy.ring_subfield_norm_bound, ) .expect("A admission bound"); let b_bound = crate::sis::rounded_up_collision_inf_norm( @@ -262,12 +260,12 @@ fn precommit_admission_rejects_insufficient_a_and_b_bounds() { let lower_a_bound = crate::sis::COEFF_LINF_BUCKETS .iter() .copied() - .rfind(|&bound| bound < inner.coeff_linf_bound()) + .rfind(|&bound| bound < inner.coeff_linf_bound().expect("L infinity test matrix")) .expect("lower supported A bound"); low_a.inner_commit_matrix = InnerCommitMatrixParams::try_new_with_min_rank( crate::SisTableKey { coeff_linf_bound: lower_a_bound, - ..inner.sis_table_key() + ..inner.sis_table_key().expect("L infinity test matrix") }, inner.input_width(), ) @@ -317,11 +315,14 @@ fn native_group_dimensions_are_independent_of_final_group_order() { let inner = &precommitted.layout.inner_commit_matrix; precommitted.layout.inner_commit_matrix = InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), - inner.coeff_linf_bound(), + inner.coeff_linf_bound().expect("L infinity test matrix"), 128, ); let outer = &precommitted.layout.outer_commit_matrix; @@ -361,6 +362,10 @@ fn native_group_dimensions_are_independent_of_final_group_order() { .expect("policy-bound output witness length"), witness_layout.live_coeff_len() ); + assert!( + witness_layout.live_coeff_len().is_multiple_of(128), + "the grouped witness must include padding for the widest successor A carrier" + ); assert!(witness_layout .units_for_group(0) .expect("precommitted units") diff --git a/crates/akita-types/src/layout/params/tests/params_relation_row_tests.rs b/crates/akita-types/src/layout/params/tests/params_relation_row_tests.rs index 40b2a7b4f..dde9a379e 100644 --- a/crates/akita-types/src/layout/params/tests/params_relation_row_tests.rs +++ b/crates/akita-types/src/layout/params/tests/params_relation_row_tests.rs @@ -11,11 +11,16 @@ fn compression_quotient_rows_are_included_before_evaluation_trace() { let mut lp = laid_out_sample_lp(); lp.inner_commit_matrix = InnerCommitMatrixParams::new_unchecked( lp.inner_commit_matrix.security_policy(), - lp.inner_commit_matrix.sis_table_key().table_digest, + lp.inner_commit_matrix + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, lp.inner_commit_matrix.sis_modulus_profile(), 2, lp.inner_commit_matrix.input_width(), - lp.inner_commit_matrix.coeff_linf_bound(), + lp.inner_commit_matrix + .coeff_linf_bound() + .expect("L infinity test matrix"), lp.d_a(), ); lp.outer_commit_matrix = OuterCommitMatrixParams::new_unchecked( diff --git a/crates/akita-types/src/layout/proof_size.rs b/crates/akita-types/src/layout/proof_size.rs index 5139dbd10..92c306c15 100644 --- a/crates/akita-types/src/layout/proof_size.rs +++ b/crates/akita-types/src/layout/proof_size.rs @@ -30,6 +30,38 @@ pub fn terminal_response_bytes(field_bits: u32, shape: &TerminalResponseShape) - ) } +/// Planner byte estimate for a terminal response. +/// +/// The scheduled Golomb payload cap remains unchanged. For a single-group L2 +/// route, candidate selection may price the tighter deterministic payload bound +/// implied by the certified energy. Unsupported shapes conservatively use the +/// scheduled byte budget. +pub fn terminal_response_planner_bytes( + field_bits: u32, + shape: &TerminalResponseShape, + response_l2_sq_cap: Option, +) -> usize { + let scheduled = terminal_response_bytes(field_bits, shape); + let Some(l2_sq_cap) = response_l2_sq_cap else { + return scheduled; + }; + let [group] = shape.layout.groups.as_slice() else { + return scheduled; + }; + let Some(z_payload_bytes) = crate::golomb_rice::golomb_rice_l2_planner_payload_bytes( + group.z_coords, + l2_sq_cap, + group.z_rice_low_bits, + ) else { + return scheduled; + }; + crate::proof::terminal_response_upper_bound_bytes( + field_bits, + &shape.layout, + z_payload_bytes.min(group.z_payload_bytes), + ) +} + fn compressed_unipoly_bytes(degree: usize, elem_bytes: usize) -> usize { degree * elem_bytes } @@ -282,6 +314,24 @@ pub fn sumcheck_rounds(level_d: usize, output_witness_len: usize) -> usize { #[cfg(test)] mod tests { use super::*; + use crate::{TailSegmentGroupLayout, TailSegmentLayout}; + + fn sample_terminal_shape() -> TerminalResponseShape { + TerminalResponseShape { + layout: TailSegmentLayout { + ring_dimension: 64, + groups: vec![TailSegmentGroupLayout { + z_coords: 1024, + e_field_elems: 64, + t_field_elems: 128, + z_admission_linf_cap: 2_570, + z_rice_low_bits: 9, + z_payload_bytes: 4_096, + }], + logical_num_elems: 1_216, + }, + } + } fn level_bytes(width: usize, fold_level: usize, ring_d: usize) -> Result { extension_opening_reduction_level_bytes( @@ -341,4 +391,31 @@ mod tests { ); assert!(try_extension_opening_reduction_level_bytes(128, 3, 1, key, 16, 64).is_err()); } + + #[test] + fn terminal_l2_planner_estimate_does_not_change_the_wire_cap() { + let shape = sample_terminal_shape(); + let original = shape.clone(); + let scheduled = terminal_response_bytes(64, &shape); + let estimated = terminal_response_planner_bytes(64, &shape, Some(1 << 20)); + + assert!(estimated < scheduled); + assert_eq!( + shape, original, + "planning must not mutate scheduled geometry" + ); + assert_eq!(shape.layout.groups[0].z_payload_bytes, 4_096); + assert_eq!(terminal_response_planner_bytes(64, &shape, None), scheduled); + } + + #[test] + fn terminal_l2_planner_estimate_falls_back_for_multiple_groups() { + let mut shape = sample_terminal_shape(); + shape.layout.groups.push(shape.layout.groups[0]); + shape.layout.logical_num_elems *= 2; + assert_eq!( + terminal_response_planner_bytes(64, &shape, Some(1 << 20)), + terminal_response_bytes(64, &shape) + ); + } } diff --git a/crates/akita-types/src/layout/ring_dims.rs b/crates/akita-types/src/layout/ring_dims.rs index 77d3fc53f..4887035d8 100644 --- a/crates/akita-types/src/layout/ring_dims.rs +++ b/crates/akita-types/src/layout/ring_dims.rs @@ -269,7 +269,7 @@ pub fn validate_schedule_ring_dims(schedule: &FoldSchedule) -> Result<(), AkitaE .terminal .input_witness_len .is_multiple_of(terminal_d) - || terminal.inner_commit_matrix.sis_table_key().ring_dimension as usize != terminal_d + || terminal.inner_commit_matrix.ring_dimension() != terminal_d { return Err(AkitaError::InvalidSetup( "terminal inner ring dimension is inconsistent with witness length".to_string(), @@ -280,7 +280,7 @@ pub fn validate_schedule_ring_dims(schedule: &FoldSchedule) -> Result<(), AkitaE pub fn validate_role_dims_match_keys(lp: &crate::CommittedGroupParams) -> Result<(), AkitaError> { let dims = lp.role_dims(); - let a_ring = lp.inner_commit_matrix.sis_table_key().ring_dimension as usize; + let a_ring = lp.inner_commit_matrix.ring_dimension(); let b_ring = lp.outer_commit_matrix.sis_table_key().ring_dimension as usize; let d_ring = lp.open_commit_matrix.sis_table_key().ring_dimension as usize; if a_ring != dims.inner { diff --git a/crates/akita-types/src/lib.rs b/crates/akita-types/src/lib.rs index dfe244adf..bdbd49494 100644 --- a/crates/akita-types/src/lib.rs +++ b/crates/akita-types/src/lib.rs @@ -77,12 +77,12 @@ pub use layout::{ gadget_row_scalars, lagrange_weights, monomial_weights, opening_domain_len, packed_digits_bytes, padded_boolean_opening_vars, proof_ring_vec_bytes, reduce_inner_opening_to_ring_element, ring_opening_point_from_field, shared_d_digit_log_basis, - sumcheck_rounds, terminal_response_bytes, try_extension_opening_reduction_level_bytes, - validate_role_dims, validate_schedule_ring_dims, witness_commitment_domain_len, BasisMode, - CommitmentRingDims, CommittedGroupParams, FlatMatrix, LevelParamsLike, - PrecommittedGroupAdmissionPolicy, PrecommittedLevelParams, RingMatrixView, RingOpeningPoint, - RingRole, MAX_FOLD_LEVELS, MIN_A_ROLE_FOLD_CHALLENGE_RING_D, SUPPORTED_CHALLENGE_RING_DIMS, - SUPPORTED_COMMITMENT_RING_DIMS, + sumcheck_rounds, terminal_response_bytes, terminal_response_planner_bytes, + try_extension_opening_reduction_level_bytes, validate_role_dims, validate_schedule_ring_dims, + witness_commitment_domain_len, BasisMode, CommitmentRingDims, CommittedGroupParams, FlatMatrix, + LevelParamsLike, PrecommittedGroupAdmissionPolicy, PrecommittedLevelParams, RingMatrixView, + RingOpeningPoint, RingRole, MAX_FOLD_LEVELS, MIN_A_ROLE_FOLD_CHALLENGE_RING_D, + SUPPORTED_CHALLENGE_RING_DIMS, SUPPORTED_COMMITMENT_RING_DIMS, }; pub use ntt_cache::{ centered_quotient_requires_i16_tail, centered_quotient_requires_i16_tail_for_field, @@ -120,20 +120,21 @@ pub use proof::{ DummyProof, ExtensionOpeningReductionProof, ExtensionOpeningReductionShape, FoldLevelProof, GroupBatchStatement, LevelProofShape, NegativeBinarySupport, NextWitnessBinding, NextWitnessBindingShape, OpeningClaims, OpeningClaimsLayout, OpeningPoints, - PolynomialGroupClaims, PolynomialGroupLayout, PreparedOpeningPoint, ProverCommitmentRows, - PublicMatrixDerivation, RelationAddressGeometry, RelationGroupRows, - RelationRangeImageGroupPlan, RelationRangeImagePlan, RelationRhsLayout, RelationRowFamily, - RingCommitment, RingMultiplierOpeningPoint, RingRelationInstance, RingRelationOpeningCounts, - RingRelationSegmentLengths, RingVec, RingView, SetupMatrixCapacity, SetupPrefixProverRegistry, - SetupPrefixPublicCommitment, SetupPrefixSlot, SetupPrefixSlotId, SetupPrefixVerifierRegistry, - SetupPrefixVerifierSlot, SetupProductSumcheckShape, SetupSumcheckProof, - SubfieldMultiplierOpeningPoint, TailSegmentGroupLayout, TailSegmentLayout, TerminalLevelProof, - TerminalLevelProofShape, TerminalResponse, TerminalResponseGroupParts, TerminalResponseShape, - TerminalWitnessTranscriptParts, MAX_GENERIC_SETUP_DECODE_FIELD_ELEMENTS, + PhysicalL2NormProof, PhysicalResponsePlan, PolynomialGroupClaims, PolynomialGroupLayout, + PreparedOpeningPoint, ProverCommitmentRows, PublicMatrixDerivation, RelationAddressGeometry, + RelationGroupRows, RelationRangeImageGroupPlan, RelationRangeImagePlan, RelationRhsLayout, + RelationRowFamily, RingCommitment, RingMultiplierOpeningPoint, RingRelationInstance, + RingRelationOpeningCounts, RingRelationSegmentLengths, RingVec, RingView, SetupMatrixCapacity, + SetupPrefixProverRegistry, SetupPrefixPublicCommitment, SetupPrefixSlot, SetupPrefixSlotId, + SetupPrefixVerifierRegistry, SetupPrefixVerifierSlot, SetupProductSumcheckShape, + SetupSumcheckProof, SubfieldMultiplierOpeningPoint, TailSegmentGroupLayout, TailSegmentLayout, + TerminalLevelProof, TerminalLevelProofShape, TerminalResponse, TerminalResponseGroupParts, + TerminalResponseShape, TerminalWitnessTranscriptParts, MAX_GENERIC_SETUP_DECODE_FIELD_ELEMENTS, MAX_UNTRUSTED_COMMITMENT_COEFFICIENTS, SETUP_SUMCHECK_DEGREE, }; pub use proof::{ - append_digit_range_child_claims, DigitRangeEqualityPoint, DigitRangePlan, FlatBooleanDomain, + append_digit_range_child_claims, reconstruct_l2_sq_from_gram, DigitRangeEqualityPoint, + DigitRangePlan, FlatBooleanDomain, }; pub use proof_size::{level_proof_bytes, FOLD_GRIND_NONCE_BYTES}; pub use schedule::{ @@ -157,9 +158,10 @@ pub use signed_digit::{ MIN_SIGNED_DIGIT_LOG_BASIS, }; pub use sis::{ - InnerCommitMatrixParams, OpenCommitMatrixParams, OuterCommitMatrixParams, ScalarCutoff, - SisMatrixRole, SisModulusProfileId, SisRoleCell, SisSecurityPolicyId, SisTableDigest, - SisTableKey, DEFAULT_SIS_SECURITY_POLICY, + InnerCommitMatrixParams, InnerCommitSecurityRoute, OpenCommitMatrixParams, + OuterCommitMatrixParams, PhysicalL2NormProofShape, ScalarCutoff, SisL2TableDigest, + SisL2TableKey, SisMatrixRole, SisModulusProfileId, SisRoleCell, SisSecurityPolicyId, + SisTableDigest, SisTableKey, DEFAULT_SIS_SECURITY_POLICY, }; pub use tail_golomb_rice_low_bits::{cap_rice_low_bits, wire_rice_low_bits}; pub use trace_weight::{ diff --git a/crates/akita-types/src/proof/commitment.rs b/crates/akita-types/src/proof/commitment.rs index 9635f01c5..f9ed68e0d 100644 --- a/crates/akita-types/src/proof/commitment.rs +++ b/crates/akita-types/src/proof/commitment.rs @@ -268,10 +268,12 @@ impl AkitaSerialize for .log_basis_inner .serialize_with_mode(&mut writer, Compress::No)?; write_usize(&mut writer, profile.num_digits_inner)?; - for matrix in [ - profile.inner_commit_matrix.sis_table_key(), - profile.outer_commit_matrix.sis_table_key(), - ] { + let inner_table_key = profile.inner_commit_matrix.sis_table_key().ok_or_else(|| { + SerializationError::InvalidData( + "precommitted group cannot use an L2 A security route".into(), + ) + })?; + for matrix in [inner_table_key, profile.outer_commit_matrix.sis_table_key()] { matrix .modulus_profile .tag() @@ -649,25 +651,31 @@ mod committed_group_tests { inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), - inner.coeff_linf_bound(), + inner.coeff_linf_bound().expect("L infinity test matrix"), inner.ring_dimension(), ), InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank().saturating_sub(1), inner.input_width(), - inner.coeff_linf_bound(), + inner.coeff_linf_bound().expect("L infinity test matrix"), inner.ring_dimension(), ), InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), - inner.coeff_linf_bound() - 1, + inner.coeff_linf_bound().expect("L infinity test matrix") - 1, inner.ring_dimension(), ), ]; diff --git a/crates/akita-types/src/proof/levels.rs b/crates/akita-types/src/proof/levels.rs index 5f328eaba..6dca12165 100644 --- a/crates/akita-types/src/proof/levels.rs +++ b/crates/akita-types/src/proof/levels.rs @@ -22,6 +22,24 @@ pub struct AkitaStage1Proof { pub stages: Vec>, /// Claimed evaluation of `S` at the final stage-1 output point. pub range_image_evaluation: F, + /// Optional schedule-selected proof of the complete physical response + /// square sum. Its presence and exact vector lengths are derived from the + /// A matrix security route. + pub norm_proof: Option>, +} + +/// Stage-1 payload for one schedule-selected physical L2 norm proof. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PhysicalL2NormProof { + /// Exact nonnegative integer square sum reconstructed by the verifier. + pub response_l2_sq: u128, + /// Direct mode leaves this empty. Limb-Gram mode carries the canonical + /// block-major, upper-triangular inner-product claims. + pub subclaims: Vec, + /// Final virtual response or limb evaluations consumed by Stage 2. + pub virtual_evaluations: Vec, + /// General final-leaf sumcheck batching range and norm terms. + pub sumcheck: SumcheckProof, } /// FoldSchedule-shaped outgoing witness binding for an intermediate fold. diff --git a/crates/akita-types/src/proof/mod.rs b/crates/akita-types/src/proof/mod.rs index 387ce796b..9680122c6 100644 --- a/crates/akita-types/src/proof/mod.rs +++ b/crates/akita-types/src/proof/mod.rs @@ -60,8 +60,8 @@ pub use containers::{ pub use hints::AkitaCommitmentHint; pub use levels::{ AkitaBatchedProof, AkitaStage1Proof, AkitaStage1StageProof, AkitaStage2Proof, - ExtensionOpeningReductionProof, FoldLevelProof, NextWitnessBinding, SetupSumcheckProof, - TerminalLevelProof, + ExtensionOpeningReductionProof, FoldLevelProof, NextWitnessBinding, PhysicalL2NormProof, + SetupSumcheckProof, TerminalLevelProof, }; pub use relation::{ assemble_compressed_relation_rhs, assemble_relation_rhs, @@ -72,7 +72,10 @@ pub use relation::{ relation_rhs_row_count, RelationGroupRows, RelationRhsLayout, RelationRowFamily, }; pub use relation_address::{CompressionRelationAddressGeometry, RelationAddressGeometry}; -pub use relation_range_image::{RelationRangeImageGroupPlan, RelationRangeImagePlan}; +pub use relation_range_image::{ + reconstruct_l2_sq_from_gram, PhysicalResponsePlan, RelationRangeImageGroupPlan, + RelationRangeImagePlan, +}; pub use ring_relation::{ ring_relation_segment_lengths, RingRelationInstance, RingRelationOpeningCounts, RingRelationSegmentLengths, @@ -96,8 +99,8 @@ pub use setup_prefix::{ }; pub use shapes::{ AkitaBatchedProofShape, AkitaStage1StageShape, ExtensionOpeningReductionShape, LevelProofShape, - NextWitnessBindingShape, SetupProductSumcheckShape, TerminalLevelProofShape, - SETUP_SUMCHECK_DEGREE, + NextWitnessBindingShape, PhysicalL2NormProofWireShape, SetupProductSumcheckShape, + TerminalLevelProofShape, SETUP_SUMCHECK_DEGREE, }; pub use stage1::{ append_digit_range_child_claims, DigitRangeEqualityPoint, DigitRangePlan, FlatBooleanDomain, diff --git a/crates/akita-types/src/proof/relation_range_image.rs b/crates/akita-types/src/proof/relation_range_image.rs index 0ea45a177..803c572dd 100644 --- a/crates/akita-types/src/proof/relation_range_image.rs +++ b/crates/akita-types/src/proof/relation_range_image.rs @@ -2,13 +2,349 @@ use std::ops::Range; +use akita_algebra::offset_eq::{EqPairTensorAxis, EqPairTensorFamily}; use akita_field::AkitaError; +use akita_field::{FieldCore, FromPrimitiveInt}; use crate::{ - CommitmentRingDims, DigitRangePlan, FlatBooleanDomain, OpeningClaimsLayout, + CommitmentRingDims, CommittedGroupParams, DigitRangePlan, FlatBooleanDomain, + InnerCommitSecurityRoute, OpeningClaimsLayout, PhysicalL2NormProofShape, RelationAddressGeometry, WitnessLayout, }; +#[derive(Clone, Debug, Eq, PartialEq)] +struct PhysicalResponseSegment { + physical_start: usize, + physical_len: usize, + witness_start: usize, +} + +/// Checked map from the canonical physical folded response to the Z digit +/// addresses in the Stage-1/Stage-2 witness table. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PhysicalResponsePlan { + domain: FlatBooleanDomain, + shape: PhysicalL2NormProofShape, + segments: Vec, + ring_dimension: usize, + fold_digit_count: usize, + fold_basis: usize, +} + +impl PhysicalResponsePlan { + /// Derive the complete physical response map from the same + /// [`WitnessLayout`] used by ring switching. + pub fn new( + params: &CommittedGroupParams, + plan: &RelationRangeImagePlan, + ) -> Result, AkitaError> { + let InnerCommitSecurityRoute::L2 { + norm_proof_shape: shape, + .. + } = params.inner_commit_matrix.security_route() + else { + return Ok(None); + }; + shape.validate()?; + if !params.precommitted_groups.is_empty() || plan.groups.len() != 1 { + return Err(AkitaError::InvalidSetup( + "L2 response proofs are restricted to scalar recursive folds".into(), + )); + } + let ring_dimension = params.d_a(); + let fold_digit_count = params.num_digits_fold(); + let fold_basis = 1usize + .checked_shl(params.log_basis_open) + .ok_or_else(|| AkitaError::InvalidSetup("fold basis overflow".into()))?; + if ring_dimension == 0 || fold_digit_count == 0 { + return Err(AkitaError::InvalidSetup( + "L2 response proof has empty ring or digit geometry".into(), + )); + } + let digit_stride = fold_digit_count + .checked_mul(ring_dimension) + .ok_or_else(|| AkitaError::InvalidSetup("L2 response stride overflow".into()))?; + let mut physical_cursor = 0usize; + let mut segments = Vec::with_capacity(plan.witness_layout.units().len()); + for unit in plan.witness_layout.units() { + if unit.group_index() != 0 || !unit.z_range().len().is_multiple_of(digit_stride) { + return Err(AkitaError::InvalidSetup( + "L2 response Z layout is not a scalar digit grid".into(), + )); + } + let physical_len = unit.z_range().len() / fold_digit_count; + segments.push(PhysicalResponseSegment { + physical_start: physical_cursor, + physical_len, + witness_start: unit.z_range().start, + }); + physical_cursor = physical_cursor + .checked_add(physical_len) + .ok_or_else(|| AkitaError::InvalidSetup("L2 response length overflow".into()))?; + } + if physical_cursor != shape.physical_response_len() { + return Err(AkitaError::InvalidSetup(format!( + "L2 response shape length {} disagrees with WitnessLayout length {physical_cursor}", + shape.physical_response_len() + ))); + } + if matches!( + shape, + PhysicalL2NormProofShape::LimbGram { limb_count, .. } + if limb_count != fold_digit_count + ) { + return Err(AkitaError::InvalidSetup( + "L2 limb count disagrees with folded-response digit depth".into(), + )); + } + if physical_cursor > plan.digit_witness_domain().domain_len() { + return Err(AkitaError::InvalidSetup( + "L2 response table exceeds the Stage-1 domain".into(), + )); + } + Ok(Some(Self { + domain: plan.digit_witness_domain(), + shape, + segments, + ring_dimension, + fold_digit_count, + fold_basis, + })) + } + + /// Scheduled integer norm proof shape. + #[must_use] + pub const fn shape(&self) -> PhysicalL2NormProofShape { + self.shape + } + + /// Shared padded Stage-1 witness domain. + #[must_use] + pub const fn domain(&self) -> FlatBooleanDomain { + self.domain + } + + /// Number of virtual tables bound at the final Stage-1 point. + #[must_use] + pub const fn virtual_table_count(&self) -> usize { + match self.shape { + PhysicalL2NormProofShape::Direct { .. } => 1, + PhysicalL2NormProofShape::LimbGram { limb_count, .. } => limb_count, + } + } + + /// Integer folded-response digit basis. + #[must_use] + pub const fn fold_basis(&self) -> usize { + self.fold_basis + } + + /// Number of balanced fold digits recomposed into one physical response. + #[must_use] + pub const fn fold_digit_count(&self) -> usize { + self.fold_digit_count + } + + /// Materialize the unpadded centered integer virtual tables used for exact + /// norm and limb-Gram claim construction. + pub fn materialize_virtual_integers( + &self, + compact_witness: &[i8], + ) -> Result>, AkitaError> { + if compact_witness.len() != self.domain.live_len() { + return Err(AkitaError::InvalidSize { + expected: self.domain.live_len(), + actual: compact_witness.len(), + }); + } + let mut tables = + vec![vec![0i128; self.shape.physical_response_len()]; self.virtual_table_count()]; + let digit_stride = self + .fold_digit_count + .checked_mul(self.ring_dimension) + .ok_or_else(|| AkitaError::InvalidSetup("L2 response stride overflow".into()))?; + for segment in &self.segments { + for row in 0..segment.physical_len / self.ring_dimension { + let witness_row = segment + .witness_start + .checked_add(row.checked_mul(digit_stride).ok_or_else(|| { + AkitaError::InvalidSetup("L2 witness row overflow".into()) + })?) + .ok_or_else(|| AkitaError::InvalidSetup("L2 witness row overflow".into()))?; + let physical_row = segment + .physical_start + .checked_add(row.checked_mul(self.ring_dimension).ok_or_else(|| { + AkitaError::InvalidSetup("L2 physical row overflow".into()) + })?) + .ok_or_else(|| AkitaError::InvalidSetup("L2 physical row overflow".into()))?; + for coefficient in 0..self.ring_dimension { + let physical_index = physical_row + coefficient; + match self.shape { + PhysicalL2NormProofShape::Direct { .. } => { + let mut value = 0i128; + let mut basis_power = 1i128; + for limb in 0..self.fold_digit_count { + let index = witness_row + limb * self.ring_dimension + coefficient; + let digit = compact_witness + .get(index) + .copied() + .ok_or(AkitaError::InvalidProof)?; + value = value + .checked_add( + i128::from(digit).checked_mul(basis_power).ok_or_else( + || { + AkitaError::InvalidSetup( + "L2 basis power overflow".into(), + ) + }, + )?, + ) + .ok_or_else(|| { + AkitaError::InvalidSetup( + "L2 response recomposition overflow".into(), + ) + })?; + basis_power = basis_power + .checked_mul(self.fold_basis as i128) + .ok_or_else(|| { + AkitaError::InvalidSetup("L2 basis power overflow".into()) + })?; + } + *tables + .first_mut() + .and_then(|table| table.get_mut(physical_index)) + .ok_or(AkitaError::InvalidProof)? = value; + } + PhysicalL2NormProofShape::LimbGram { limb_count, .. } => { + for (limb, table) in tables.iter_mut().enumerate().take(limb_count) { + let index = witness_row + limb * self.ring_dimension + coefficient; + *table + .get_mut(physical_index) + .ok_or(AkitaError::InvalidProof)? = i128::from( + compact_witness + .get(index) + .copied() + .ok_or(AkitaError::InvalidProof)?, + ); + } + } + } + } + } + } + Ok(tables) + } + + /// Canonical paired-equality geometry that batches all virtual response + /// evaluations into the existing Stage-2 witness relation. + pub fn virtualization_families( + &self, + batching: &[E], + ) -> Result>, AkitaError> { + if batching.len() != self.virtual_table_count() { + return Err(AkitaError::InvalidSize { + expected: self.virtual_table_count(), + actual: batching.len(), + }); + } + let limb_weights = match self.shape { + PhysicalL2NormProofShape::Direct { .. } => { + let mut weights = Vec::with_capacity(self.fold_digit_count); + let mut power = E::one(); + let basis = E::from_u64(self.fold_basis as u64); + for _ in 0..self.fold_digit_count { + weights.push(batching[0] * power); + power *= basis; + } + weights + } + PhysicalL2NormProofShape::LimbGram { limb_count, .. } => { + batching.iter().copied().take(limb_count).collect() + } + }; + let digit_stride = self + .fold_digit_count + .checked_mul(self.ring_dimension) + .ok_or_else(|| AkitaError::InvalidSetup("L2 response stride overflow".into()))?; + let mut families = Vec::with_capacity(self.segments.len()); + for segment in &self.segments { + let row_count = segment.physical_len / self.ring_dimension; + families.push(EqPairTensorFamily::new( + segment.witness_start, + segment.physical_start, + E::one(), + vec![ + EqPairTensorAxis::unit(self.ring_dimension, 1, 1), + EqPairTensorAxis::dense(self.ring_dimension, 0, limb_weights.clone()), + EqPairTensorAxis::unit(row_count, digit_stride, self.ring_dimension), + ], + )?); + } + Ok(families) + } +} + +/// Reconstruct the exact nonnegative square sum from canonical block-major, +/// upper-triangular limb Gram claims. +pub fn reconstruct_l2_sq_from_gram( + shape: PhysicalL2NormProofShape, + fold_basis: usize, + claims: &[i128], +) -> Result { + let layout = shape.limb_gram_layout()?.ok_or_else(|| { + AkitaError::InvalidInput("direct L2 shape has no limb-Gram reconstruction".into()) + })?; + let expected = layout.subclaim_count(); + if claims.len() != expected { + return Err(AkitaError::InvalidSize { + expected, + actual: claims.len(), + }); + } + let basis = i128::try_from(fold_basis) + .map_err(|_| AkitaError::InvalidSetup("L2 fold basis exceeds i128".into()))?; + let power_count = layout + .limb_count() + .checked_mul(2) + .ok_or_else(|| AkitaError::InvalidSetup("L2 power count overflow".into()))?; + let mut powers = Vec::with_capacity(power_count); + let mut power = 1i128; + for _ in 0..power_count { + powers.push(power); + power = power + .checked_mul(basis) + .ok_or_else(|| AkitaError::InvalidSetup("L2 basis power overflow".into()))?; + } + let mut total = 0i128; + for block_index in 0..layout.block_count() { + for (left, right) in layout.limb_pairs() { + let claim_index = layout + .subclaim_index(block_index, left, right) + .ok_or(AkitaError::InvalidProof)?; + let claim = claims + .get(claim_index) + .copied() + .ok_or(AkitaError::InvalidProof)?; + let exponent = left + .checked_add(right) + .ok_or_else(|| AkitaError::InvalidSetup("L2 exponent overflow".into()))?; + let scale = powers + .get(exponent) + .copied() + .ok_or(AkitaError::InvalidProof)? + .checked_mul(if left == right { 1 } else { 2 }) + .ok_or_else(|| AkitaError::InvalidSetup("L2 Gram scale overflow".into()))?; + total = + total + .checked_add(claim.checked_mul(scale).ok_or_else(|| { + AkitaError::InvalidSetup("L2 Gram product overflow".into()) + })?) + .ok_or_else(|| AkitaError::InvalidSetup("L2 Gram sum overflow".into()))?; + } + } + u128::try_from(total).map_err(|_| AkitaError::InvalidProof) +} + /// One commitment group's claims and witness units in physical processing order. #[derive(Clone, Debug, Eq, PartialEq)] pub struct RelationRangeImageGroupPlan { @@ -389,4 +725,33 @@ mod tests { ) .is_err()); } + + #[test] + fn limb_gram_reconstruction_handles_signs_and_block_boundaries() { + let shape = PhysicalL2NormProofShape::LimbGram { + physical_response_len: 5, + block_len: 2, + limb_count: 2, + }; + // Block-major upper triangles for limbs + // l0 = [-2, -1, 0, 1, 2], l1 = [1, -2, 2, 0, -1]. + let claims = [5, 0, 5, 1, 0, 4, 4, -2, 1]; + assert_eq!( + reconstruct_l2_sq_from_gram(shape, 4, &claims).expect("signed block Gram norm"), + 154 + ); + assert!(reconstruct_l2_sq_from_gram(shape, 4, &claims[..8]).is_err()); + } + + #[test] + fn limb_gram_reconstruction_rejects_integer_overflow() { + let shape = PhysicalL2NormProofShape::LimbGram { + physical_response_len: 1, + block_len: 1, + limb_count: 2, + }; + assert!( + reconstruct_l2_sq_from_gram(shape, usize::MAX, &[i128::MAX, 0, i128::MAX]).is_err() + ); + } } diff --git a/crates/akita-types/src/proof/ring_relation.rs b/crates/akita-types/src/proof/ring_relation.rs index 51378256e..ab32513d9 100644 --- a/crates/akita-types/src/proof/ring_relation.rs +++ b/crates/akita-types/src/proof/ring_relation.rs @@ -407,7 +407,10 @@ mod tests { fn certify_test_sis_bounds(lp: &mut CommittedGroupParams) { lp.inner_commit_matrix = InnerCommitMatrixParams::new_unchecked( lp.inner_commit_matrix.security_policy(), - lp.inner_commit_matrix.sis_table_key().table_digest, + lp.inner_commit_matrix + .sis_table_key() + .expect("test matrix is L infinity") + .table_digest, lp.inner_commit_matrix.sis_modulus_profile(), lp.inner_commit_matrix.output_rank(), lp.inner_commit_matrix.input_width(), diff --git a/crates/akita-types/src/proof/setup_prefix.rs b/crates/akita-types/src/proof/setup_prefix.rs index 2f1231bab..677af3458 100644 --- a/crates/akita-types/src/proof/setup_prefix.rs +++ b/crates/akita-types/src/proof/setup_prefix.rs @@ -231,141 +231,11 @@ fn deserialize_sis_table_digest( Ok(SisTableDigest(bytes)) } -trait SetupPrefixCommitMatrixParams: Sized { - const ROLE: SisMatrixRole; - - fn sis_modulus_profile(&self) -> SisModulusProfileId; - fn security_policy(&self) -> SisSecurityPolicyId; - fn sis_table_key(&self) -> crate::SisTableKey; - fn output_rank(&self) -> usize; - fn input_width(&self) -> usize; - fn coeff_linf_bound(&self) -> u128; - - #[allow(clippy::too_many_arguments)] - fn new_unchecked( - policy: SisSecurityPolicyId, - table_digest: SisTableDigest, - sis_modulus_profile: SisModulusProfileId, - output_rank: usize, - input_width: usize, - coeff_linf_bound: u128, - ring_dimension: usize, - ) -> Self; -} - -macro_rules! impl_setup_prefix_commit_matrix_params { - ($ty:ty, $role:expr) => { - impl SetupPrefixCommitMatrixParams for $ty { - const ROLE: SisMatrixRole = $role; - - fn sis_modulus_profile(&self) -> SisModulusProfileId { - self.sis_modulus_profile() - } - fn security_policy(&self) -> SisSecurityPolicyId { - self.security_policy() - } - fn sis_table_key(&self) -> crate::SisTableKey { - self.sis_table_key() - } - fn output_rank(&self) -> usize { - self.output_rank() - } - fn input_width(&self) -> usize { - self.input_width() - } - fn coeff_linf_bound(&self) -> u128 { - self.coeff_linf_bound() - } - fn new_unchecked( - policy: SisSecurityPolicyId, - table_digest: SisTableDigest, - sis_modulus_profile: SisModulusProfileId, - output_rank: usize, - input_width: usize, - coeff_linf_bound: u128, - ring_dimension: usize, - ) -> Self { - Self::new_unchecked( - policy, - table_digest, - sis_modulus_profile, - output_rank, - input_width, - coeff_linf_bound, - ring_dimension, - ) - } - } - }; -} - -impl_setup_prefix_commit_matrix_params!(InnerCommitMatrixParams, SisMatrixRole::Inner); -impl_setup_prefix_commit_matrix_params!(OuterCommitMatrixParams, SisMatrixRole::Outer); - -/// Wire layout mirrors the commit-matrix descriptor bytes: -/// profile tag, policy tag, role tag, table digest, ring dim, row, col, linf. -fn serialize_commit_matrix( - key: &K, - mut writer: W, - compress: Compress, -) -> Result<(), SerializationError> { - let table_key = key.sis_table_key(); - serialize_sis_modulus_profile(key.sis_modulus_profile(), &mut writer)?; - serialize_sis_security_policy(key.security_policy(), &mut writer)?; - serialize_sis_matrix_role(table_key.role, &mut writer)?; - serialize_sis_table_digest(table_key.table_digest, &mut writer)?; - (table_key.ring_dimension as usize).serialize_with_mode(&mut writer, compress)?; - key.output_rank() - .serialize_with_mode(&mut writer, compress)?; - key.input_width() - .serialize_with_mode(&mut writer, compress)?; - key.coeff_linf_bound() - .serialize_with_mode(&mut writer, compress)?; - Ok(()) -} - -fn deserialize_commit_matrix( - mut reader: R, - compress: Compress, - validate: Validate, -) -> Result { - let sis_modulus_profile = deserialize_sis_modulus_profile(&mut reader)?; - let policy = deserialize_sis_security_policy(&mut reader)?; - let role = deserialize_sis_matrix_role(&mut reader)?; - if role != K::ROLE { - return Err(SerializationError::InvalidData( - "setup-prefix commitment matrix has the wrong role".to_string(), - )); - } - let table_digest = deserialize_sis_table_digest(&mut reader)?; - let ring_dimension = usize::deserialize_with_mode(&mut reader, compress, validate, &())?; - let row_len = usize::deserialize_with_mode(&mut reader, compress, validate, &())?; - let col_len = usize::deserialize_with_mode(&mut reader, compress, validate, &())?; - let coeff_linf_bound = u128::deserialize_with_mode(&mut reader, compress, validate, &())?; - Ok(K::new_unchecked( - policy, - table_digest, - sis_modulus_profile, - row_len, - col_len, - coeff_linf_bound, - ring_dimension, - )) -} - -fn commit_matrix_serialized_size( - key: &K, - compress: Compress, -) -> usize { - 1 // profile tag - + 1 // policy tag - + 1 // role tag - + 32 // table digest - + (key.sis_table_key().ring_dimension as usize).serialized_size(compress) - + key.output_rank().serialized_size(compress) - + key.input_width().serialized_size(compress) - + key.coeff_linf_bound().serialized_size(compress) -} +#[path = "setup_prefix_commit_matrix.rs"] +mod commit_matrix; +use commit_matrix::{ + commit_matrix_serialized_size, deserialize_commit_matrix, serialize_commit_matrix, +}; fn serialize_precommitted_level_params( params: &PrecommittedLevelParams, @@ -1330,18 +1200,14 @@ pub fn setup_prefix_precommitted_params( if inner_width <= prefix_params.inner_commit_matrix.input_width() && outer_width <= prefix_params.outer_commit_matrix.input_width() { - let inner_commit_matrix = InnerCommitMatrixParams::new_unchecked( - prefix_params.inner_commit_matrix.security_policy(), - prefix_params - .inner_commit_matrix - .sis_table_key() - .table_digest, - prefix_params.inner_commit_matrix.sis_modulus_profile(), - prefix_params.inner_commit_matrix.output_rank(), - inner_width, - prefix_params.inner_commit_matrix.coeff_linf_bound(), - prefix_params.inner_commit_matrix.ring_dimension(), - ); + if prefix_params.inner_commit_matrix.sis_table_key().is_none() { + return Err(AkitaError::InvalidSetup( + "setup prefix cannot be derived from an L2 A security route".into(), + )); + } + let inner_commit_matrix = prefix_params + .inner_commit_matrix + .try_with_input_width(inner_width)?; let outer_commit_matrix = OuterCommitMatrixParams::new_unchecked( prefix_params.outer_commit_matrix.security_policy(), prefix_params diff --git a/crates/akita-types/src/proof/setup_prefix_commit_matrix.rs b/crates/akita-types/src/proof/setup_prefix_commit_matrix.rs new file mode 100644 index 000000000..394a04998 --- /dev/null +++ b/crates/akita-types/src/proof/setup_prefix_commit_matrix.rs @@ -0,0 +1,191 @@ +//! Setup-prefix wire encoding for SIS commitment matrices. + +use super::*; + +pub(super) trait SetupPrefixCommitMatrixParams: Sized { + const ROLE: SisMatrixRole; + + fn sis_modulus_profile(&self) -> SisModulusProfileId; + fn security_policy(&self) -> SisSecurityPolicyId; + fn sis_table_key(&self) -> Option; + fn output_rank(&self) -> usize; + fn input_width(&self) -> usize; + fn coeff_linf_bound(&self) -> Option; + fn ring_dimension(&self) -> usize; + + #[allow(clippy::too_many_arguments)] + fn new_unchecked( + policy: SisSecurityPolicyId, + table_digest: SisTableDigest, + sis_modulus_profile: SisModulusProfileId, + output_rank: usize, + input_width: usize, + coeff_linf_bound: u128, + ring_dimension: usize, + ) -> Self; +} + +macro_rules! impl_setup_prefix_commit_matrix_params { + ($ty:ty, $role:expr) => { + impl SetupPrefixCommitMatrixParams for $ty { + const ROLE: SisMatrixRole = $role; + + fn sis_modulus_profile(&self) -> SisModulusProfileId { + self.sis_modulus_profile() + } + fn security_policy(&self) -> SisSecurityPolicyId { + self.security_policy() + } + fn sis_table_key(&self) -> Option { + Some(self.sis_table_key()) + } + fn output_rank(&self) -> usize { + self.output_rank() + } + fn input_width(&self) -> usize { + self.input_width() + } + fn coeff_linf_bound(&self) -> Option { + Some(self.coeff_linf_bound()) + } + fn ring_dimension(&self) -> usize { + self.ring_dimension() + } + fn new_unchecked( + policy: SisSecurityPolicyId, + table_digest: SisTableDigest, + sis_modulus_profile: SisModulusProfileId, + output_rank: usize, + input_width: usize, + coeff_linf_bound: u128, + ring_dimension: usize, + ) -> Self { + Self::new_unchecked( + policy, + table_digest, + sis_modulus_profile, + output_rank, + input_width, + coeff_linf_bound, + ring_dimension, + ) + } + } + }; +} + +impl_setup_prefix_commit_matrix_params!(OuterCommitMatrixParams, SisMatrixRole::Outer); + +impl SetupPrefixCommitMatrixParams for InnerCommitMatrixParams { + const ROLE: SisMatrixRole = SisMatrixRole::Inner; + + fn sis_modulus_profile(&self) -> SisModulusProfileId { + self.sis_modulus_profile() + } + fn security_policy(&self) -> SisSecurityPolicyId { + self.security_policy() + } + fn sis_table_key(&self) -> Option { + self.sis_table_key() + } + fn output_rank(&self) -> usize { + self.output_rank() + } + fn input_width(&self) -> usize { + self.input_width() + } + fn coeff_linf_bound(&self) -> Option { + self.coeff_linf_bound() + } + fn ring_dimension(&self) -> usize { + self.ring_dimension() + } + fn new_unchecked( + policy: SisSecurityPolicyId, + table_digest: SisTableDigest, + sis_modulus_profile: SisModulusProfileId, + output_rank: usize, + input_width: usize, + coeff_linf_bound: u128, + ring_dimension: usize, + ) -> Self { + Self::new_unchecked( + policy, + table_digest, + sis_modulus_profile, + output_rank, + input_width, + coeff_linf_bound, + ring_dimension, + ) + } +} + +/// Wire layout mirrors the commit-matrix descriptor bytes: +/// profile tag, policy tag, role tag, table digest, ring dim, row, col, linf. +pub(super) fn serialize_commit_matrix( + key: &K, + mut writer: W, + compress: Compress, +) -> Result<(), SerializationError> { + let table_key = key.sis_table_key().ok_or_else(|| { + SerializationError::InvalidData("setup prefix cannot use an L2 A security route".into()) + })?; + serialize_sis_modulus_profile(key.sis_modulus_profile(), &mut writer)?; + serialize_sis_security_policy(key.security_policy(), &mut writer)?; + serialize_sis_matrix_role(table_key.role, &mut writer)?; + serialize_sis_table_digest(table_key.table_digest, &mut writer)?; + (table_key.ring_dimension as usize).serialize_with_mode(&mut writer, compress)?; + key.output_rank() + .serialize_with_mode(&mut writer, compress)?; + key.input_width() + .serialize_with_mode(&mut writer, compress)?; + key.coeff_linf_bound() + .ok_or_else(|| { + SerializationError::InvalidData("setup prefix cannot use an L2 A security route".into()) + })? + .serialize_with_mode(&mut writer, compress)?; + Ok(()) +} + +pub(super) fn deserialize_commit_matrix( + mut reader: R, + compress: Compress, + validate: Validate, +) -> Result { + let sis_modulus_profile = deserialize_sis_modulus_profile(&mut reader)?; + let policy = deserialize_sis_security_policy(&mut reader)?; + let role = deserialize_sis_matrix_role(&mut reader)?; + if role != K::ROLE { + return Err(SerializationError::InvalidData( + "setup-prefix commitment matrix has the wrong role".to_string(), + )); + } + let table_digest = deserialize_sis_table_digest(&mut reader)?; + let ring_dimension = usize::deserialize_with_mode(&mut reader, compress, validate, &())?; + let row_len = usize::deserialize_with_mode(&mut reader, compress, validate, &())?; + let col_len = usize::deserialize_with_mode(&mut reader, compress, validate, &())?; + let coeff_linf_bound = u128::deserialize_with_mode(&mut reader, compress, validate, &())?; + Ok(K::new_unchecked( + policy, + table_digest, + sis_modulus_profile, + row_len, + col_len, + coeff_linf_bound, + ring_dimension, + )) +} + +pub(super) fn commit_matrix_serialized_size( + key: &K, + compress: Compress, +) -> usize { + 1 + 1 + + 1 + + 32 + + key.ring_dimension().serialized_size(compress) + + key.output_rank().serialized_size(compress) + + key.input_width().serialized_size(compress) + + 0u128.serialized_size(compress) +} diff --git a/crates/akita-types/src/proof/setup_prefix_tests.rs b/crates/akita-types/src/proof/setup_prefix_tests.rs index a053ea215..d74d13720 100644 --- a/crates/akita-types/src/proof/setup_prefix_tests.rs +++ b/crates/akita-types/src/proof/setup_prefix_tests.rs @@ -81,11 +81,17 @@ fn active_setup_field_len_includes_mixed_role_subcolumns() { let inner = &lp.inner_commit_matrix; lp.inner_commit_matrix = crate::InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), - inner.coeff_linf_bound().max(1), + inner + .coeff_linf_bound() + .expect("L infinity test matrix") + .max(1), 128, ); let opening_batch = OpeningClaimsLayout::new(5, 3).expect("opening batch"); @@ -122,7 +128,10 @@ fn retarget_group_role_dims( params.inner_commit_matrix = crate::InnerCommitMatrixParams::try_new_with_min_rank( crate::SisTableKey { policy: inner.security_policy(), - table_digest: inner.sis_table_key().table_digest, + table_digest: inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, modulus_profile: inner.sis_modulus_profile(), role: crate::sis::SisMatrixRole::Inner, ring_dimension: u32::try_from(inner_ring_dimension).expect("test ring dimension"), diff --git a/crates/akita-types/src/proof/shapes.rs b/crates/akita-types/src/proof/shapes.rs index a8b306289..311e95df4 100644 --- a/crates/akita-types/src/proof/shapes.rs +++ b/crates/akita-types/src/proof/shapes.rs @@ -102,6 +102,8 @@ pub struct LevelProofShape { pub opening_payload_coeffs: usize, /// Stage-1 tree stage shapes in root-to-leaf order. pub stage1_stages: Vec, + /// Shape of the optional schedule-selected physical norm payload. + pub stage1_norm: Option, /// Stage-2 sumcheck shape: `(num_rounds, degree)`. pub stage2_sumcheck_proof: SumcheckProofShape, /// Shape of the optional stage-3 setup product-sumcheck payload. @@ -110,6 +112,17 @@ pub struct LevelProofShape { pub next_witness_binding: NextWitnessBindingShape, } +/// Headerless wire shape of [`PhysicalL2NormProof`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PhysicalL2NormProofWireShape { + /// Number of blockwise limb claims; zero for direct mode. + pub subclaims: usize, + /// Number of final response/limb virtual evaluations. + pub virtual_evaluations: usize, + /// General final-leaf sumcheck shape. + pub sumcheck: SumcheckProofShape, +} + /// Shape descriptor for deserializing an [`AkitaBatchedProof`] without /// headers. #[derive(Debug, Clone, PartialEq, Eq)] @@ -158,6 +171,14 @@ pub(super) fn level_proof_shape( child_claims: stage.child_claims.len(), }) .collect(), + stage1_norm: stage1 + .norm_proof + .as_ref() + .map(|proof| PhysicalL2NormProofWireShape { + subclaims: proof.subclaims.len(), + virtual_evaluations: proof.virtual_evaluations.len(), + sumcheck: sumcheck_shape(&proof.sumcheck), + }), stage2_sumcheck_proof: sumcheck_shape(&stage2.sumcheck_proof), stage3_sumcheck: stage3_sumcheck_proof.map(SetupSumcheckProof::shape), next_witness_binding: match &stage2.next_witness_binding { @@ -260,6 +281,68 @@ impl AkitaDeserialize for AkitaStage1StageShape { } } +impl Valid for PhysicalL2NormProofWireShape { + fn check(&self) -> Result<(), SerializationError> { + checked_shape_len(self.subclaims)?; + checked_shape_len(self.virtual_evaluations)?; + if self.virtual_evaluations == 0 { + return Err(SerializationError::InvalidData( + "L2 norm proof shape requires a virtual evaluation".into(), + )); + } + checked_shape_sequence_len(self.sumcheck.len())?; + for °ree in &self.sumcheck { + checked_shape_len(degree)?; + } + Ok(()) + } +} + +impl AkitaSerialize for PhysicalL2NormProofWireShape { + fn serialize_with_mode( + &self, + mut writer: W, + compress: Compress, + ) -> Result<(), SerializationError> { + self.subclaims.serialize_with_mode(&mut writer, compress)?; + self.virtual_evaluations + .serialize_with_mode(&mut writer, compress)?; + self.sumcheck.serialize_with_mode(&mut writer, compress) + } + + fn serialized_size(&self, compress: Compress) -> usize { + self.subclaims.serialized_size(compress) + + self.virtual_evaluations.serialized_size(compress) + + self.sumcheck.serialized_size(compress) + } +} + +impl AkitaDeserialize for PhysicalL2NormProofWireShape { + type Context = (); + + fn deserialize_with_mode( + mut reader: R, + compress: Compress, + validate: Validate, + _ctx: &(), + ) -> Result { + let out = Self { + subclaims: usize::deserialize_with_mode(&mut reader, compress, validate, &())?, + virtual_evaluations: usize::deserialize_with_mode( + &mut reader, + compress, + validate, + &(), + )?, + sumcheck: deserialize_shape_vec(&mut reader, compress, validate)?, + }; + if matches!(validate, Validate::Yes) { + out.check()?; + } + Ok(out) + } +} + impl Valid for LevelProofShape { fn check(&self) -> Result<(), SerializationError> { if let Some(reduction) = &self.extension_opening_reduction { @@ -268,6 +351,9 @@ impl Valid for LevelProofShape { checked_shape_len(self.opening_payload_coeffs)?; checked_shape_sequence_len(self.stage1_stages.len())?; self.stage1_stages.check()?; + if let Some(shape) = &self.stage1_norm { + shape.check()?; + } checked_shape_sequence_len(self.stage2_sumcheck_proof.len())?; for °ree in &self.stage2_sumcheck_proof { checked_shape_len(degree)?; @@ -303,6 +389,12 @@ impl AkitaSerialize for LevelProofShape { .serialize_with_mode(&mut writer, compress)?; self.stage1_stages .serialize_with_mode(&mut writer, compress)?; + self.stage1_norm + .is_some() + .serialize_with_mode(&mut writer, compress)?; + if let Some(stage1_norm) = &self.stage1_norm { + stage1_norm.serialize_with_mode(&mut writer, compress)?; + } self.stage2_sumcheck_proof .serialize_with_mode(&mut writer, compress)?; self.stage3_sumcheck @@ -337,6 +429,11 @@ impl AkitaSerialize for LevelProofShape { reduction_size + self.opening_payload_coeffs.serialized_size(compress) + self.stage1_stages.serialized_size(compress) + + true.serialized_size(compress) + + self + .stage1_norm + .as_ref() + .map_or(0, |shape| shape.serialized_size(compress)) + self.stage2_sumcheck_proof.serialized_size(compress) + true.serialized_size(compress) + self @@ -373,6 +470,17 @@ impl AkitaDeserialize for LevelProofShape { let opening_payload_coeffs = usize::deserialize_with_mode(&mut reader, compress, validate, &())?; let stage1_stages = deserialize_shape_vec(&mut reader, compress, validate)?; + let has_stage1_norm = bool::deserialize_with_mode(&mut reader, compress, validate, &())?; + let stage1_norm = if has_stage1_norm { + Some(PhysicalL2NormProofWireShape::deserialize_with_mode( + &mut reader, + compress, + validate, + &(), + )?) + } else { + None + }; let stage2_sumcheck = deserialize_shape_vec(&mut reader, compress, validate)?; let has_stage3_sumcheck = bool::deserialize_with_mode(&mut reader, compress, validate, &())?; @@ -399,6 +507,7 @@ impl AkitaDeserialize for LevelProofShape { extension_opening_reduction, opening_payload_coeffs, stage1_stages, + stage1_norm, stage2_sumcheck_proof: stage2_sumcheck, stage3_sumcheck, next_witness_binding, diff --git a/crates/akita-types/src/proof/stage1.rs b/crates/akita-types/src/proof/stage1.rs index 7352887ae..a38d3f049 100644 --- a/crates/akita-types/src/proof/stage1.rs +++ b/crates/akita-types/src/proof/stage1.rs @@ -1,6 +1,7 @@ //! Shared stage-1 tree shape and polynomial helpers. -use crate::{AkitaStage1Proof, AkitaStage1StageShape}; +use crate::proof::PhysicalL2NormProofWireShape; +use crate::{AkitaStage1Proof, AkitaStage1StageShape, InnerCommitSecurityRoute}; use akita_field::{AkitaError, CanonicalField, ExtField, FieldCore, FromPrimitiveInt}; use akita_transcript::{append_ext_field, labels, Transcript}; @@ -284,6 +285,41 @@ impl DigitRangePlan { .collect() } + /// Derive the headerless Stage 1 wire shape from the scheduled A route. + pub fn proof_shapes_for_route( + self, + rounds: usize, + route: InnerCommitSecurityRoute, + ) -> Result< + ( + Vec, + Option, + ), + AkitaError, + > { + match route { + InnerCommitSecurityRoute::Linf(_) => Ok((self.stage_shapes(rounds), None)), + InnerCommitSecurityRoute::L2 { + norm_proof_shape, .. + } => { + norm_proof_shape.validate()?; + Ok(( + self.stage_shapes(rounds) + .into_iter() + .take(self.product_stage_arities().len()) + .collect(), + Some(PhysicalL2NormProofWireShape { + subclaims: norm_proof_shape.subclaim_count().ok_or_else(|| { + AkitaError::InvalidSetup("L2 norm subclaim count overflow".into()) + })?, + virtual_evaluations: norm_proof_shape.virtual_evaluation_count(), + sumcheck: vec![self.leaf_degree() + 1; rounds], + }), + )) + } + } + } + /// Validate the complete in-memory range-proof shape without allocation. /// /// # Errors @@ -429,6 +465,10 @@ fn poly_coeffs_from_roots(roots: &[E]) -> Vec { #[cfg(test)] mod tests { use super::*; + use crate::{ + InnerCommitSecurityRoute, PhysicalL2NormProofShape, SisL2TableDigest, SisL2TableKey, + SisModulusProfileId, SisSecurityPolicyId, SisTableDigest, SisTableKey, + }; use akita_field::Prime128Offset275; type F = Prime128Offset275; @@ -523,4 +563,40 @@ mod tests { .unwrap(); assert!(short_point.validate_domain(domain).is_err()); } + + #[test] + fn route_authority_derives_exact_headerless_stage1_shapes() { + let plan = DigitRangePlan::new(64).unwrap(); + let linf = InnerCommitSecurityRoute::Linf(SisTableKey { + policy: SisSecurityPolicyId::Quantum128BitADPS16, + table_digest: SisTableDigest::CURRENT, + modulus_profile: SisModulusProfileId::Q128OffsetA7F7, + role: crate::SisMatrixRole::Inner, + ring_dimension: 64, + coeff_linf_bound: 1, + }); + let (linf_stages, linf_norm) = plan.proof_shapes_for_route(7, linf).unwrap(); + assert_eq!(linf_stages, plan.stage_shapes(7)); + assert!(linf_norm.is_none()); + + let l2 = InnerCommitSecurityRoute::L2 { + table_key: SisL2TableKey { + policy: SisSecurityPolicyId::Quantum128BitADPS16, + table_digest: SisL2TableDigest::CURRENT, + modulus_profile: SisModulusProfileId::Q128OffsetA7F7, + ring_dimension: 64, + collision_l2_sq: 1, + }, + response_l2_sq_cap: 1, + norm_proof_shape: PhysicalL2NormProofShape::Direct { + physical_response_len: 64, + }, + }; + let (l2_stages, l2_norm) = plan.proof_shapes_for_route(7, l2).unwrap(); + assert_eq!(l2_stages.len(), plan.product_stage_arities().len()); + let l2_norm = l2_norm.expect("L2 wire shape"); + assert_eq!(l2_norm.subclaims, 0); + assert_eq!(l2_norm.virtual_evaluations, 1); + assert_eq!(l2_norm.sumcheck, vec![plan.leaf_degree() + 1; 7]); + } } diff --git a/crates/akita-types/src/proof/tail_segments/tests.rs b/crates/akita-types/src/proof/tail_segments/tests.rs index 300b2cd80..5934485e0 100644 --- a/crates/akita-types/src/proof/tail_segments/tests.rs +++ b/crates/akita-types/src/proof/tail_segments/tests.rs @@ -21,7 +21,11 @@ fn test_lp() -> CommittedGroupParams { .expect("tail segment test params"); let key = crate::sis::SisTableKey { policy: params.inner_commit_matrix.security_policy(), - table_digest: params.inner_commit_matrix.sis_table_key().table_digest, + table_digest: params + .inner_commit_matrix + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, modulus_profile: params.inner_commit_matrix.sis_modulus_profile(), role: crate::sis::SisMatrixRole::Inner, ring_dimension: 64, diff --git a/crates/akita-types/src/proof/tests.rs b/crates/akita-types/src/proof/tests.rs index 77b4296c4..510318c75 100644 --- a/crates/akita-types/src/proof/tests.rs +++ b/crates/akita-types/src/proof/tests.rs @@ -85,6 +85,7 @@ fn level_shape_validation_checks_extension_opening_reduction() { )), opening_payload_coeffs: 1, stage1_stages: Vec::new(), + stage1_norm: None, stage2_sumcheck_proof: Vec::new(), stage3_sumcheck: None, next_witness_binding: NextWitnessBindingShape::OuterPayload { coeffs: 1 }, @@ -125,10 +126,28 @@ fn level_shape_deserialization_rejects_vector_length_before_allocation() { )); } +#[test] +fn l2_shape_deserialization_rejects_rounds_before_allocation() { + let mut bytes = Vec::new(); + 0usize.serialize_compressed(&mut bytes).unwrap(); // subclaims + 1usize.serialize_compressed(&mut bytes).unwrap(); // virtual evaluations + (MAX_PROOF_SHAPE_SEQUENCE_LEN as u64 + 1) + .serialize_compressed(&mut bytes) + .unwrap(); // sumcheck round count + + let err = PhysicalL2NormProofWireShape::deserialize_compressed(&bytes[..], &()) + .expect_err("oversized L2 round vector must be rejected before allocation"); + assert!(matches!( + err, + SerializationError::LengthLimitExceeded { .. } + )); +} + fn tiny_stage1() -> AkitaStage1Proof { AkitaStage1Proof { stages: Vec::new(), range_image_evaluation: F::zero(), + norm_proof: None, } } diff --git a/crates/akita-types/src/proof/wire.rs b/crates/akita-types/src/proof/wire.rs index 6b92a61ec..dc6c652d2 100644 --- a/crates/akita-types/src/proof/wire.rs +++ b/crates/akita-types/src/proof/wire.rs @@ -1,5 +1,97 @@ use super::*; +impl AkitaSerialize for PhysicalL2NormProof { + fn serialize_with_mode( + &self, + mut writer: W, + compress: Compress, + ) -> Result<(), SerializationError> { + self.response_l2_sq + .serialize_with_mode(&mut writer, compress)?; + for subclaim in &self.subclaims { + subclaim.serialize_with_mode(&mut writer, compress)?; + } + for evaluation in &self.virtual_evaluations { + evaluation.serialize_with_mode(&mut writer, compress)?; + } + self.sumcheck.serialize_with_mode(writer, compress) + } + + fn serialized_size(&self, compress: Compress) -> usize { + self.response_l2_sq.serialized_size(compress) + + self + .subclaims + .iter() + .map(|claim| claim.serialized_size(compress)) + .sum::() + + self + .virtual_evaluations + .iter() + .map(|evaluation| evaluation.serialized_size(compress)) + .sum::() + + self.sumcheck.serialized_size(compress) + } +} + +impl AkitaDeserialize for PhysicalL2NormProof +where + E: FieldCore + Valid + AkitaDeserialize, +{ + type Context = PhysicalL2NormProofWireShape; + + fn deserialize_with_mode( + mut reader: R, + compress: Compress, + validate: Validate, + shape: &Self::Context, + ) -> Result { + let response_l2_sq = u128::deserialize_with_mode(&mut reader, compress, validate, &())?; + let mut subclaims = Vec::new(); + reserve_shape_len(&mut subclaims, shape.subclaims)?; + for _ in 0..shape.subclaims { + subclaims.push(E::deserialize_with_mode( + &mut reader, + compress, + validate, + &(), + )?); + } + let mut virtual_evaluations = Vec::new(); + reserve_shape_len(&mut virtual_evaluations, shape.virtual_evaluations)?; + for _ in 0..shape.virtual_evaluations { + virtual_evaluations.push(E::deserialize_with_mode( + &mut reader, + compress, + validate, + &(), + )?); + } + let out = Self { + response_l2_sq, + subclaims, + virtual_evaluations, + sumcheck: SumcheckProof::deserialize_with_mode( + reader, + compress, + validate, + &shape.sumcheck, + )?, + }; + if matches!(validate, Validate::Yes) { + out.check()?; + } + Ok(out) + } +} + +impl Valid for PhysicalL2NormProof { + fn check(&self) -> Result<(), SerializationError> { + self.subclaims.check()?; + self.virtual_evaluations.check()?; + self.sumcheck.check() + } +} + fn serialize_extension_opening_reduction( reduction: Option<&ExtensionOpeningReductionProof>, mut writer: W, @@ -414,6 +506,9 @@ impl() + self.stage1.range_image_evaluation.serialized_size(compress) + + self + .stage1 + .norm_proof + .as_ref() + .map_or(0, |norm| norm.serialized_size(compress)) + ({ stage2.sumcheck_proof.serialized_size(compress) }) + stage3_sumcheck_serialized_size(self.stage3_sumcheck_proof.as_ref(), compress) + next_witness_binding_serialized_size(&stage2.next_witness_binding, compress) @@ -463,6 +563,9 @@ impl Valid for FoldLevelProof stage.child_claims.check()?; } self.stage1.range_image_evaluation.check()?; + if let Some(norm) = &self.stage1.norm_proof { + norm.check()?; + } let stage2 = &self.stage2; stage2.sumcheck_proof.check()?; if let Some(stage3_sumcheck) = &self.stage3_sumcheck_proof { @@ -521,9 +624,22 @@ impl< child_claims, }); } + let range_image_evaluation = + E::deserialize_with_mode(&mut reader, compress, validate, &())?; + let norm_proof = if let Some(shape) = &ctx.stage1_norm { + Some(PhysicalL2NormProof::deserialize_with_mode( + &mut reader, + compress, + validate, + shape, + )?) + } else { + None + }; let stage1 = AkitaStage1Proof { stages: stage1_stages, - range_image_evaluation: E::deserialize_with_mode(&mut reader, compress, validate, &())?, + range_image_evaluation, + norm_proof, }; let stage2_sumcheck_proof = SumcheckProof::deserialize_with_mode( &mut reader, diff --git a/crates/akita-types/src/proof_size.rs b/crates/akita-types/src/proof_size.rs index 75e843dbc..88465acae 100644 --- a/crates/akita-types/src/proof_size.rs +++ b/crates/akita-types/src/proof_size.rs @@ -8,7 +8,9 @@ //! schedule-table representation it consumes. use crate::layout::{field_bytes, proof_ring_vec_bytes, sumcheck_rounds}; -use crate::{CommitmentPayloadGeometry, CommittedGroupParams, DigitRangePlan}; +use crate::{ + CommitmentPayloadGeometry, CommittedGroupParams, DigitRangePlan, InnerCommitSecurityRoute, +}; use akita_field::AkitaError; /// Fixed wire size of `fold_grind_nonce` on every fold level proof. @@ -22,17 +24,29 @@ fn sumcheck_bytes(rounds: usize, degree: usize, elem_bytes: usize) -> usize { rounds * compressed_unipoly_bytes(degree, elem_bytes) } -fn stage1_proof_bytes(rounds: usize, b: usize, elem_bytes: usize) -> usize { - DigitRangePlan::new(b) - .expect("scheduled range basis must be certified") - .stage_shapes(rounds) +fn stage1_proof_bytes( + rounds: usize, + b: usize, + elem_bytes: usize, + route: InnerCommitSecurityRoute, +) -> Result { + let plan = DigitRangePlan::new(b)?; + let (stages, norm) = plan.proof_shapes_for_route(rounds, route)?; + let stages_bytes = stages .into_iter() .map(|stage| { - ({ sumcheck_bytes(rounds, stage.sumcheck_proof.1, elem_bytes) }) + sumcheck_bytes(rounds, stage.sumcheck_proof.1, elem_bytes) + stage.child_claims * elem_bytes }) - .sum::() - + elem_bytes + .sum::(); + let norm_bytes = norm.map_or(0, |shape| { + 16 + (shape.subclaims + shape.virtual_evaluations) * elem_bytes + + shape.sumcheck.into_iter().sum::() * elem_bytes + }); + // The ordinary final range evaluation remains outside the optional norm + // payload. The fused standard leaf shape accounts for the one additional + // stored coefficient in every selected L2 leaf round. + Ok(stages_bytes + elem_bytes + norm_bytes) } /// Header-stripped byte size of one non-terminal folded proof level. @@ -100,7 +114,12 @@ pub fn level_proof_bytes( }; let next_eval_bytes = challenge_elem_bytes; let b = 1usize << lp.log_basis_open; - let stage1_bytes = stage1_proof_bytes(rounds, b, challenge_elem_bytes); + let stage1_bytes = stage1_proof_bytes( + rounds, + b, + challenge_elem_bytes, + lp.inner_commit_matrix.security_route(), + )?; Ok(v_bytes + FOLD_GRIND_NONCE_BYTES + stage1_bytes @@ -165,19 +184,26 @@ mod tests { use akita_challenges::SparseChallengeConfig; use akita_field::AkitaError; - use akita_field::{CanonicalField, FieldCore, Prime128OffsetA7F7}; + use akita_field::{ + CanonicalField, Ext2, FieldCore, FpExt4, Prime128OffsetA7F7, Prime32Offset99, + Prime64Offset59, + }; use akita_serialization::{AkitaSerialize, Compress}; use akita_sumcheck::EqFactoredUniPoly; use akita_sumcheck::{CompressedUniPoly, EqFactoredSumcheckProof, SumcheckProof}; use crate::golomb_rice::golomb_rice_encode_vec; + use crate::sis::sis_l2_table_key_for_collision_sq; use crate::{ terminal_response_bytes, AkitaStage1Proof, AkitaStage1StageProof, AkitaStage2Proof, - FoldLevelProof, RingVec, SetupSumcheckProof, SisModulusProfileId, TerminalLevelProof, - TerminalResponse, TerminalResponseShape, SETUP_SUMCHECK_DEGREE, + FoldLevelProof, PhysicalL2NormProof, PhysicalL2NormProofShape, RingVec, SetupSumcheckProof, + SisL2TableDigest, SisModulusProfileId, TerminalLevelProof, TerminalResponse, + TerminalResponseShape, DEFAULT_SIS_SECURITY_POLICY, SETUP_SUMCHECK_DEGREE, }; type F = Prime128OffsetA7F7; + // `pm1_only(3)` prices the fixtures' response cap 127 below A bucket 4095. + const TEST_TERMINAL_A_BUCKET: u128 = 4_095; fn terminal_response_fixture( lp: &CommittedGroupParams, @@ -238,18 +264,47 @@ mod tests { } } - fn dummy_stage1_proof(rounds: usize, b: usize) -> AkitaStage1Proof { + fn dummy_stage1_proof( + rounds: usize, + b: usize, + route: InnerCommitSecurityRoute, + ) -> AkitaStage1Proof { + let plan = DigitRangePlan::new(b).expect("test range basis"); + let (stage_count, norm_proof) = match route { + InnerCommitSecurityRoute::Linf(_) => (plan.stage_count(), None), + InnerCommitSecurityRoute::L2 { + norm_proof_shape, .. + } => { + let (subclaims, virtual_evaluations) = match norm_proof_shape { + PhysicalL2NormProofShape::Direct { .. } => (0, 1), + PhysicalL2NormProofShape::LimbGram { limb_count, .. } => ( + norm_proof_shape.subclaim_count().expect("test subclaims"), + limb_count, + ), + }; + ( + plan.product_stage_arities().len(), + Some(PhysicalL2NormProof { + response_l2_sq: 0, + subclaims: vec![F::zero(); subclaims], + virtual_evaluations: vec![F::zero(); virtual_evaluations], + sumcheck: dummy_sumcheck(rounds, plan.leaf_degree() + 1), + }), + ) + } + }; AkitaStage1Proof { - stages: DigitRangePlan::new(b) - .expect("test range basis") + stages: plan .stage_shapes(rounds) .into_iter() + .take(stage_count) .map(|shape| AkitaStage1StageProof { sumcheck_proof: dummy_eq_factored_sumcheck(rounds, shape.sumcheck_proof.1), child_claims: vec![F::zero(); shape.child_claims], }) .collect(), range_image_evaluation: F::zero(), + norm_proof, } } @@ -272,7 +327,10 @@ mod tests { } } - fn exact_level_proof_bytes( + fn exact_level_proof_bytes< + B: FieldCore + CanonicalField + AkitaSerialize, + E: FieldCore + AkitaSerialize, + >( lp: &CommittedGroupParams, next_lp: &CommittedGroupParams, output_witness_len: usize, @@ -286,15 +344,15 @@ mod tests { let proof = FoldLevelProof { extension_opening_reduction: None, - opening_payload: RingVec::from_coeffs(vec![F::zero(); current_coeffs]), + opening_payload: RingVec::from_coeffs(vec![B::zero(); current_coeffs]), fold_grind_nonce: 0, - stage1: dummy_stage1_proof(rounds, b), + stage1: dummy_stage1_proof::(rounds, b, lp.inner_commit_matrix.security_route()), stage2: AkitaStage2Proof { - sumcheck_proof: dummy_sumcheck(rounds, 3), + sumcheck_proof: dummy_sumcheck::(rounds, 3), next_witness_binding: match next_witness_binding { crate::NextWitnessBindingPolicy::OuterPayload => { crate::NextWitnessBinding::OuterPayload(RingVec::from_coeffs(vec![ - F::zero(); + B::zero(); next_commit_coeffs ])) } @@ -302,14 +360,77 @@ mod tests { crate::NextWitnessBinding::TerminalInnerState } }, - next_w_eval: F::zero(), + next_w_eval: E::zero(), }, stage3_sumcheck_proof: stage3_setup_ring_len - .map(|setup_ring_len| dummy_stage3_proof::(lp.d_a(), setup_ring_len)), + .map(|setup_ring_len| dummy_stage3_proof::(lp.d_a(), setup_ring_len)), }; Ok(proof.serialized_size(Compress::No)) } + fn assert_l2_bytes_match_for_profile( + profile: SisModulusProfileId, + field_bits: u32, + log_basis: u32, + fold_digit_count: usize, + ) where + B: FieldCore + CanonicalField + AkitaSerialize, + E: FieldCore + AkitaSerialize, + { + const D: usize = 128; + let challenge = SparseChallengeConfig::pm1_only(3); + let mut lp = CommittedGroupParams::params_only(profile, D, log_basis, 4, 2, 2, challenge) + .with_decomp(256, 8, 1, 1, 1) + .unwrap(); + lp.num_digits_fold = fold_digit_count; + let shape = PhysicalL2NormProofShape::derive( + profile, + lp.inner_commit_matrix.input_width() * D, + 1usize << log_basis, + fold_digit_count, + ) + .expect("profile norm shape"); + let table_key = sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest::CURRENT, + profile, + D as u32, + 1u128 << 50, + ) + .expect("profile L2 key"); + lp.inner_commit_matrix = crate::InnerCommitMatrixParams::try_new_l2_with_min_rank( + table_key, + lp.inner_commit_matrix.input_width(), + 1u128 << 32, + shape, + ) + .expect("profile L2 matrix"); + let next_lp = CommittedGroupParams::params_only(profile, D, 3, 2, 2, 2, challenge) + .with_decomp(8, 8, 1, 1, 1) + .unwrap(); + let output_witness_len = D * 8; + assert_eq!( + level_proof_bytes( + field_bits, + 128, + &lp, + Some(&next_lp), + output_witness_len, + Some(crate::NextWitnessBindingPolicy::OuterPayload), + ) + .unwrap(), + exact_level_proof_bytes::( + &lp, + &next_lp, + output_witness_len, + None, + crate::NextWitnessBindingPolicy::OuterPayload, + ) + .unwrap(), + "planned L2 bytes must match {profile:?} serialization for {shape:?}" + ); + } + #[test] fn planned_level_bytes_match_non_offloaded_payload_at_all_bases() { const D: usize = 64; @@ -347,7 +468,7 @@ mod tests { Some(crate::NextWitnessBindingPolicy::OuterPayload), ) .unwrap(), - exact_level_proof_bytes::( + exact_level_proof_bytes::( &lp, &next_lp, output_witness_len, @@ -360,6 +481,97 @@ mod tests { } } + #[test] + fn planned_level_bytes_match_serialized_l2_payloads() { + const D: usize = 64; + let fold_challenge_config = SparseChallengeConfig::pm1_only(3); + let next_lp = CommittedGroupParams::params_only( + SisModulusProfileId::Q128OffsetA7F7, + D, + 2, + 2, + 3, + 2, + fold_challenge_config, + ); + let table_key = sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest::CURRENT, + SisModulusProfileId::Q128OffsetA7F7, + D as u32, + 1u128 << 50, + ) + .expect("generated L2 key"); + let shapes = [ + PhysicalL2NormProofShape::Direct { + physical_response_len: 512, + }, + PhysicalL2NormProofShape::LimbGram { + physical_response_len: 512, + block_len: 32, + limb_count: 3, + }, + ]; + + for shape in shapes { + let mut lp = CommittedGroupParams::params_only( + SisModulusProfileId::Q128OffsetA7F7, + D, + 4, + 2, + 2, + 2, + fold_challenge_config, + ) + .with_decomp(1, 1, 1, 1, 1) + .unwrap(); + lp.inner_commit_matrix = crate::InnerCommitMatrixParams::try_new_l2_with_min_rank( + table_key, + shape.physical_response_len() / D, + 1u128 << 30, + shape, + ) + .expect("audited L2 matrix"); + let output_witness_len = D * 8; + assert_eq!( + level_proof_bytes( + 128, + 128, + &lp, + Some(&next_lp), + output_witness_len, + Some(crate::NextWitnessBindingPolicy::OuterPayload), + ) + .unwrap(), + exact_level_proof_bytes::( + &lp, + &next_lp, + output_witness_len, + None, + crate::NextWitnessBindingPolicy::OuterPayload, + ) + .unwrap(), + "planned L2 bytes should match serialized body for {shape:?}" + ); + } + } + + #[test] + fn planned_l2_bytes_match_small_field_extension_serialization() { + assert_l2_bytes_match_for_profile::>( + SisModulusProfileId::Q32Offset99, + 32, + 4, + 3, + ); + assert_l2_bytes_match_for_profile::>( + SisModulusProfileId::Q64Offset59, + 64, + 6, + 2, + ); + } + #[test] fn planned_level_bytes_use_fixed_compressed_d_and_successor_b_payloads() { const D_A: usize = 128; @@ -432,7 +644,7 @@ mod tests { Some(crate::NextWitnessBindingPolicy::OuterPayload), ) .unwrap(); - let serialized = exact_level_proof_bytes::( + let serialized = exact_level_proof_bytes::( &lp, &next_lp, output_witness_len, @@ -490,7 +702,7 @@ mod tests { assert_eq!(outer - terminal_inner, crate::COMPRESSION_TARGET_BYTES); assert_eq!( terminal_inner, - exact_level_proof_bytes::( + exact_level_proof_bytes::( &lp, &next_lp, output_witness_len, @@ -590,7 +802,7 @@ mod tests { .with_decomp(1, 1, 1, 1, 1) .unwrap(); - let terminal_bytes = exact_level_proof_bytes::( + let terminal_bytes = exact_level_proof_bytes::( &lp, &next_lp, output_witness_len, @@ -598,7 +810,7 @@ mod tests { crate::NextWitnessBindingPolicy::OuterPayload, ) .unwrap(); - let recursive_bytes = exact_level_proof_bytes::( + let recursive_bytes = exact_level_proof_bytes::( &lp, &next_lp, output_witness_len, @@ -635,7 +847,7 @@ mod tests { let num_claims = 3; for log_basis in 2..=6 { - let lp = CommittedGroupParams::params_only( + let mut lp = CommittedGroupParams::params_only( SisModulusProfileId::Q128OffsetA7F7, D, log_basis, @@ -646,6 +858,19 @@ mod tests { ) .with_decomp(1, 1, 1, 1, 1) .unwrap(); + let inner = lp.inner_commit_matrix; + lp.inner_commit_matrix = crate::InnerCommitMatrixParams::new_unchecked( + inner.security_policy(), + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, + inner.sis_modulus_profile(), + inner.output_rank(), + inner.input_width(), + TEST_TERMINAL_A_BUCKET, + inner.ring_dimension(), + ); let (terminal_response, witness_shape) = terminal_response_fixture(&lp, num_claims); let terminal_response_bytes_runtime = terminal_response.serialized_size(Compress::No); diff --git a/crates/akita-types/src/schedule.rs b/crates/akita-types/src/schedule.rs index f1efcc5d3..ce90779e7 100644 --- a/crates/akita-types/src/schedule.rs +++ b/crates/akita-types/src/schedule.rs @@ -547,12 +547,17 @@ impl RecursiveFoldParams { /// Exact terminal committed-witness parameters. /// -/// The terminal relation binds only the source decomposition through the -/// inner commitment matrix. It has no outer/open commitment matrix and no -/// outer/open response decomposition. +/// The terminal relation binds the source decomposition through the inner +/// commitment matrix. It also retains the terminal fold basis and digit count +/// needed to audit a calibrated L2 route. It has no outer/open commitment +/// matrix and no outer/open response decomposition. #[derive(Clone, Debug, PartialEq, Eq)] pub struct TerminalCommittedGroupParams { pub log_basis_inner: u32, + /// Response basis used by the planner for this terminal fold. + pub fold_log_basis: u32, + /// Number of response digits used by the planner for this terminal fold. + pub fold_digit_count: usize, pub inner_commit_matrix: InnerCommitMatrixParams, pub num_live_ring_elements_per_claim: usize, pub num_positions_per_block: usize, @@ -579,6 +584,8 @@ impl TerminalCommittedGroupParams { pub fn from_expanded_group(params: CommittedGroupParams) -> Self { Self { log_basis_inner: params.log_basis_inner, + fold_log_basis: params.log_basis_open, + fold_digit_count: params.num_digits_fold, inner_commit_matrix: params.inner_commit_matrix, num_live_ring_elements_per_claim: params.num_live_ring_elements_per_claim, num_positions_per_block: params.num_positions_per_block, @@ -642,25 +649,32 @@ impl TerminalCommittedGroupParams { ) } - /// Largest raw response admitted by this fixed inner matrix and the signed - /// terminal coefficient representation. + /// Largest raw response admitted by this terminal's selected inner-matrix + /// SIS bucket and the signed coefficient representation. + /// + /// The matrix rank can incidentally support a larger collision bucket. The + /// terminal wire does not consume that slack because doing so would change + /// its admission and encoding bounds when an unrelated rank frontier moves. pub fn certified_response_linf_cap( &self, sparse: &akita_challenges::SparseChallengeConfig, ) -> Result { + if matches!( + self.inner_commit_matrix.security_route(), + crate::sis::InnerCommitSecurityRoute::L2 { .. } + ) { + // A clear-terminal L2 route still needs a finite coefficient cap + // for signed-i16 kernels and Golomb decoding, but SIS security is + // provided by the directly checked complete Euclidean norm. + return Ok(i16::MAX as u128); + } let challenge = crate::sis::FoldChallengeNorms::new(sparse); - let collision_capacity = self - .inner_commit_matrix - .max_secure_collision_linf() - .ok_or_else(|| { - AkitaError::InvalidSetup("terminal A has no collision capacity".into()) - })?; + let collision_capacity = self.inner_commit_matrix.coeff_linf_bound().ok_or_else(|| { + AkitaError::InvalidSetup("terminal A cannot use an L2 security route".into()) + })?; let certified_capacity = crate::sis::max_response_linf_for_role_a_collision( collision_capacity, challenge.l1_norm, - self.inner_commit_matrix - .sis_modulus_profile() - .ring_subfield_embedding_norm_bound(), ) .filter(|value| *value > 0) .ok_or_else(|| AkitaError::InvalidSetup("terminal A cannot certify a response".into()))?; @@ -669,8 +683,21 @@ impl TerminalCommittedGroupParams { Ok(certified_capacity.min(i16::MAX as u128)) } + /// Verifier-enforced complete physical L2 cap for a clear terminal route. + #[must_use] + pub fn response_l2_sq_cap(&self) -> Option { + match self.inner_commit_matrix.security_route() { + crate::sis::InnerCommitSecurityRoute::Linf(_) => None, + crate::sis::InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, .. + } => Some(response_l2_sq_cap), + } + } + pub(crate) fn append_descriptor_bytes(&self, bytes: &mut Vec) { push_u32(bytes, self.log_basis_inner); + push_u32(bytes, self.fold_log_basis); + push_usize(bytes, self.fold_digit_count); self.inner_commit_matrix.append_descriptor_bytes(bytes); push_usize(bytes, self.num_live_ring_elements_per_claim); push_usize(bytes, self.num_positions_per_block); diff --git a/crates/akita-types/src/schedule_tests.rs b/crates/akita-types/src/schedule_tests.rs index 4090ca456..036a77e77 100644 --- a/crates/akita-types/src/schedule_tests.rs +++ b/crates/akita-types/src/schedule_tests.rs @@ -37,6 +37,8 @@ use akita_sumcheck::EqFactoredUniPoly; use akita_sumcheck::{CompressedUniPoly, EqFactoredSumcheckProof, SumcheckProof}; type F = Prime128OffsetA7F7; +// `pm1_only(3)` prices the fixtures' response cap 127 below A bucket 4095. +const TEST_TERMINAL_A_BUCKET: u128 = 4_095; fn committed_params(ring_dimension: usize) -> CommittedGroupParams { committed_params_with_geometry(ring_dimension, 4, 4) @@ -397,7 +399,10 @@ fn schedule_accepts_exact_multi_group_prefix_from_mixed_producer() { let inner = &group_params.inner_commit_matrix; group_params.inner_commit_matrix = crate::sis::InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), @@ -449,11 +454,14 @@ fn schedule_accepts_exact_multi_group_prefix_from_mixed_producer() { let inner = &consumer.inner_commit_matrix; consumer.inner_commit_matrix = crate::sis::InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), prefix_ring_slots * consumer.num_digits_inner, - inner.coeff_linf_bound(), + inner.coeff_linf_bound().expect("L infinity test matrix"), inner.ring_dimension(), ); let commitment_params = crate::setup_prefix_precommitted_params(&consumer, n_prefix) @@ -472,7 +480,7 @@ fn schedule_accepts_exact_multi_group_prefix_from_mixed_producer() { #[test] fn terminal_projection_preserves_the_fixed_inner_matrix() { let sparse = SparseChallengeConfig::pm1_only(3); - let committed = CommittedGroupParams::params_only( + let mut committed = CommittedGroupParams::params_only( SisModulusProfileId::Q128OffsetA7F7, 64, 3, @@ -483,6 +491,19 @@ fn terminal_projection_preserves_the_fixed_inner_matrix() { ) .with_decomp(4, 32, 2, 2, 2) .expect("committed params"); + let inner = committed.inner_commit_matrix; + committed.inner_commit_matrix = crate::sis::InnerCommitMatrixParams::new_unchecked( + inner.security_policy(), + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, + inner.sis_modulus_profile(), + inner.output_rank(), + inner.input_width(), + TEST_TERMINAL_A_BUCKET, + inner.ring_dimension(), + ); let expected_inner = committed.inner_commit_matrix; let (terminal, response_cap) = TerminalCommittedGroupParams::try_from_expanded_group(committed) @@ -641,6 +662,7 @@ fn dummy_stage1_proof(rounds: usize, b: usize) -> AkitaStage1Proof }) .collect(), range_image_evaluation: F::zero(), + norm_proof: None, } } @@ -752,6 +774,19 @@ fn planned_terminal_level_bytes_match_terminal_payload_at_all_bases() { .with_decomp(1, 1, 1, 1, 1) .unwrap(); lp.num_digits_fold = 2; + let inner = lp.inner_commit_matrix; + lp.inner_commit_matrix = crate::sis::InnerCommitMatrixParams::new_unchecked( + inner.security_policy(), + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, + inner.sis_modulus_profile(), + inner.output_rank(), + inner.input_width(), + TEST_TERMINAL_A_BUCKET, + inner.ring_dimension(), + ); let (terminal_response, witness_shape) = terminal_response_fixture(&lp, num_claims); let terminal_response_bytes_runtime = terminal_response.serialized_size(Compress::No); diff --git a/crates/akita-types/src/setup_contribution/tests.rs b/crates/akita-types/src/setup_contribution/tests.rs index c976cba1c..9d0a30e53 100644 --- a/crates/akita-types/src/setup_contribution/tests.rs +++ b/crates/akita-types/src/setup_contribution/tests.rs @@ -58,11 +58,14 @@ fn retarget_test_role_dims(params: &mut CommittedGroupParams, role_dims: Commitm let inner = ¶ms.inner_commit_matrix; params.inner_commit_matrix = crate::InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), - inner.coeff_linf_bound(), + inner.coeff_linf_bound().expect("L infinity test matrix"), role_dims.d_a(), ); let outer = ¶ms.outer_commit_matrix; @@ -102,11 +105,14 @@ fn retarget_precommitted_test_role_dims( let inner_output_rank = inner.output_rank(); layout.inner_commit_matrix = crate::InnerCommitMatrixParams::new_unchecked( inner.security_policy(), - inner.sis_table_key().table_digest, + inner + .sis_table_key() + .expect("L infinity test matrix") + .table_digest, inner.sis_modulus_profile(), inner.output_rank(), inner.input_width(), - inner.coeff_linf_bound(), + inner.coeff_linf_bound().expect("L infinity test matrix"), inner_ring_dimension, ); let outer = &layout.outer_commit_matrix; @@ -205,7 +211,7 @@ fn test_inputs_for_group_sizes( TEST_D, ); } - if lp.inner_commit_matrix.coeff_linf_bound() == 0 { + if lp.inner_commit_matrix.coeff_linf_bound() == Some(0) { lp.inner_commit_matrix = crate::InnerCommitMatrixParams::new_unchecked( crate::sis::DEFAULT_SIS_SECURITY_POLICY, crate::sis::SisTableDigest::CURRENT, diff --git a/crates/akita-types/src/sis/ajtai_key.rs b/crates/akita-types/src/sis/ajtai_key.rs index 84bc36b93..ec81addb9 100644 --- a/crates/akita-types/src/sis/ajtai_key.rs +++ b/crates/akita-types/src/sis/ajtai_key.rs @@ -10,6 +10,8 @@ use akita_field::AkitaError; use super::coverage::{sis_role_cell, GADGET_COEFF_LINF_ANCHORS}; use super::generated_sis_table::{sis_max_widths as generated_sis_max_widths, SIS_TABLE_DIGEST}; +use super::l2_table::{min_secure_l2_rank, SisL2TableKey}; +use super::physical_l2::{InnerCommitSecurityRoute, PhysicalL2NormProofShape}; use crate::descriptor_bytes::{push_u128, push_usize, sis_modulus_profile_tag}; /// Digest of the generated scalar table and its coverage certificate. @@ -161,18 +163,6 @@ impl SisModulusProfileId { } } - /// Infinity-norm expansion of the current trace-subfield embedding. - /// - /// The 128-bit profile is the base-field path. The 32- and 64-bit profiles - /// use the paired-lane trace embedding and therefore carry the certified - /// factor-of-two expansion. - pub const fn ring_subfield_embedding_norm_bound(self) -> u32 { - match self { - Self::Q128OffsetA7F7 => 1, - Self::Q32Offset99 | Self::Q64Offset59 => 2, - } - } - /// Validate an exact field modulus against this profile. pub const fn matches_modulus(self, modulus: u128) -> bool { self.modulus() == modulus @@ -435,6 +425,328 @@ fn min_rank_commit_matrix_fields( }) } +/// Parameters for the inner commitment matrix (A). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct InnerCommitMatrixParams { + pub(crate) output_rank: usize, + pub(crate) input_width: usize, + pub(crate) security_route: InnerCommitSecurityRoute, +} + +fn validate_l2_response_shape( + table_key: SisL2TableKey, + input_width: usize, + norm_proof_shape: PhysicalL2NormProofShape, +) -> Result<(), AkitaError> { + norm_proof_shape.validate()?; + let physical_response_len = input_width + .checked_mul(table_key.ring_dimension as usize) + .ok_or_else(|| AkitaError::InvalidSetup("L2 physical response length overflow".into()))?; + if norm_proof_shape.physical_response_len() != physical_response_len { + return Err(AkitaError::InvalidSetup(format!( + "L2 norm shape response length {} does not match A matrix physical length {physical_response_len}", + norm_proof_shape.physical_response_len() + ))); + } + Ok(()) +} + +impl InnerCommitMatrixParams { + #[allow(clippy::too_many_arguments)] + pub fn try_new( + policy: SisSecurityPolicyId, + table_digest: SisTableDigest, + sis_modulus_profile: SisModulusProfileId, + output_rank: usize, + input_width: usize, + coeff_linf_bound: u128, + ring_dimension: usize, + ) -> Result { + let fields = audit_commit_matrix_fields( + SisMatrixRole::Inner, + policy, + table_digest, + sis_modulus_profile, + output_rank, + input_width, + coeff_linf_bound, + ring_dimension, + )?; + Ok(Self { + output_rank: fields.output_rank, + input_width: fields.input_width, + security_route: InnerCommitSecurityRoute::Linf(fields.sis_table_key), + }) + } + + pub fn try_new_with_min_rank(key: SisTableKey, input_width: usize) -> Result { + let fields = min_rank_commit_matrix_fields(SisMatrixRole::Inner, key, input_width)?; + Ok(Self { + output_rank: fields.output_rank, + input_width: fields.input_width, + security_route: InnerCommitSecurityRoute::Linf(fields.sis_table_key), + }) + } + + /// Construct the minimum-rank A matrix for one checked Euclidean route. + pub fn try_new_l2_with_min_rank( + table_key: SisL2TableKey, + input_width: usize, + response_l2_sq_cap: u128, + norm_proof_shape: PhysicalL2NormProofShape, + ) -> Result { + if input_width == 0 || response_l2_sq_cap == 0 { + return Err(AkitaError::InvalidSetup( + "L2 A matrix requires nonzero width and response cap".into(), + )); + } + validate_l2_response_shape(table_key, input_width, norm_proof_shape)?; + let width = u64::try_from(input_width) + .map_err(|_| AkitaError::InvalidSetup("A matrix input width exceeds u64".into()))?; + let output_rank = min_secure_l2_rank(table_key, width).ok_or_else(|| { + AkitaError::InvalidSetup("A matrix has no audited L2 SIS rank".into()) + })?; + Ok(Self { + output_rank, + input_width, + security_route: InnerCommitSecurityRoute::L2 { + table_key, + response_l2_sq_cap, + norm_proof_shape, + }, + }) + } + + /// Rebuild this matrix for a layout-derived width while preserving its route. + pub fn try_with_input_width(self, input_width: usize) -> Result { + match self.security_route { + InnerCommitSecurityRoute::Linf(key) => { + if key.coeff_linf_bound == 0 { + return Ok(Self::new_unchecked( + key.policy, + key.table_digest, + key.modulus_profile, + self.output_rank, + input_width, + key.coeff_linf_bound, + key.ring_dimension as usize, + )); + } + Self::try_new( + key.policy, + key.table_digest, + key.modulus_profile, + self.output_rank, + input_width, + key.coeff_linf_bound, + key.ring_dimension as usize, + ) + } + InnerCommitSecurityRoute::L2 { + table_key, + response_l2_sq_cap, + norm_proof_shape, + } => { + let width = u64::try_from(input_width).map_err(|_| { + AkitaError::InvalidSetup("A matrix input width exceeds u64".into()) + })?; + let floor = min_secure_l2_rank(table_key, width).ok_or_else(|| { + AkitaError::InvalidSetup("A matrix has no audited L2 SIS rank".into()) + })?; + if self.output_rank < floor { + return Err(AkitaError::InvalidSetup(format!( + "A matrix output_rank {} is below L2 SIS floor {floor}", + self.output_rank + ))); + } + let out = Self { + output_rank: self.output_rank, + input_width, + security_route: InnerCommitSecurityRoute::L2 { + table_key, + response_l2_sq_cap, + norm_proof_shape, + }, + }; + out.validate()?; + Ok(out) + } + } + } + + /// Re-audit the selected route against its generated table and rank floor. + pub fn validate(&self) -> Result<(), AkitaError> { + match self.security_route { + InnerCommitSecurityRoute::Linf(key) => { + let fields = audit_commit_matrix_fields( + SisMatrixRole::Inner, + key.policy, + key.table_digest, + key.modulus_profile, + self.output_rank, + self.input_width, + key.coeff_linf_bound, + key.ring_dimension as usize, + )?; + if fields.sis_table_key != key { + return Err(AkitaError::InvalidSetup( + "A matrix L-infinity table key is not canonical".into(), + )); + } + } + InnerCommitSecurityRoute::L2 { + table_key, + response_l2_sq_cap, + norm_proof_shape, + } => { + validate_l2_response_shape(table_key, self.input_width, norm_proof_shape)?; + let width = u64::try_from(self.input_width).map_err(|_| { + AkitaError::InvalidSetup("A matrix input width exceeds u64".into()) + })?; + if response_l2_sq_cap == 0 + || min_secure_l2_rank(table_key, width) + .is_none_or(|rank| rank > self.output_rank) + { + return Err(AkitaError::InvalidSetup( + "A matrix L2 route is below its audited SIS floor".into(), + )); + } + } + } + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + pub const fn new_unchecked( + policy: SisSecurityPolicyId, + table_digest: SisTableDigest, + sis_modulus_profile: SisModulusProfileId, + output_rank: usize, + input_width: usize, + coeff_linf_bound: u128, + ring_dimension: usize, + ) -> Self { + Self { + output_rank, + input_width, + security_route: InnerCommitSecurityRoute::Linf(SisTableKey { + policy, + table_digest, + modulus_profile: sis_modulus_profile, + role: SisMatrixRole::Inner, + ring_dimension: ring_dimension as u32, + coeff_linf_bound, + }), + } + } + + #[must_use] + pub const fn output_rank(&self) -> usize { + self.output_rank + } + + #[must_use] + pub const fn input_width(&self) -> usize { + self.input_width + } + + #[must_use] + pub const fn security_route(&self) -> InnerCommitSecurityRoute { + self.security_route + } + + #[must_use] + pub const fn security_policy(&self) -> SisSecurityPolicyId { + self.security_route.policy() + } + + #[must_use] + pub const fn sis_modulus_profile(&self) -> SisModulusProfileId { + self.security_route.modulus_profile() + } + + #[must_use] + pub const fn ring_dimension(&self) -> usize { + self.security_route.ring_dimension() as usize + } + + /// Input dimension after expanding module coordinates into ring coefficients. + #[must_use] + pub fn raw_input_dimension(&self) -> Option { + self.input_width.checked_mul(self.ring_dimension()) + } + + /// Output dimension after expanding module coordinates into ring coefficients. + #[must_use] + pub fn raw_output_dimension(&self) -> Option { + self.output_rank.checked_mul(self.ring_dimension()) + } + + #[must_use] + pub const fn sis_table_key(&self) -> Option { + match self.security_route { + InnerCommitSecurityRoute::Linf(key) => Some(key), + InnerCommitSecurityRoute::L2 { .. } => None, + } + } + + #[must_use] + pub const fn coeff_linf_bound(&self) -> Option { + match self.security_route { + InnerCommitSecurityRoute::Linf(key) => Some(key.coeff_linf_bound), + InnerCommitSecurityRoute::L2 { .. } => None, + } + } + + #[must_use] + pub fn max_secure_collision_linf(&self) -> Option { + let key = self.sis_table_key()?; + COEFF_LINF_BUCKETS + .iter() + .copied() + .take_while(|&bound| { + min_secure_rank( + SisTableKey { + coeff_linf_bound: bound, + ..key + }, + self.input_width as u64, + ) + .is_some_and(|rank| rank <= self.output_rank) + }) + .last() + } + + pub(crate) fn append_descriptor_bytes(&self, bytes: &mut Vec) { + bytes.push(sis_modulus_profile_tag(self.sis_modulus_profile())); + bytes.push(self.security_policy().tag()); + bytes.push(SisMatrixRole::Inner.tag()); + match self.security_route { + InnerCommitSecurityRoute::Linf(key) => { + bytes.extend_from_slice(&key.table_digest.0); + bytes.extend_from_slice(&key.ring_dimension.to_le_bytes()); + push_usize(bytes, self.output_rank); + push_usize(bytes, self.input_width); + push_u128(bytes, key.coeff_linf_bound); + } + InnerCommitSecurityRoute::L2 { + table_key, + response_l2_sq_cap, + norm_proof_shape, + } => { + bytes.extend_from_slice(b"akita-l2-route-v1"); + bytes.extend_from_slice(&table_key.table_digest.0); + bytes.extend_from_slice(&table_key.ring_dimension.to_le_bytes()); + push_usize(bytes, self.output_rank); + push_usize(bytes, self.input_width); + push_u128(bytes, table_key.collision_l2_sq); + push_u128(bytes, response_l2_sq_cap); + norm_proof_shape.append_descriptor_bytes(bytes); + } + } + } +} + macro_rules! define_commit_matrix_params { ($name:ident, $role:expr, $description:literal) => { #[doc = $description] @@ -608,11 +920,6 @@ macro_rules! define_commit_matrix_params { }; } -define_commit_matrix_params!( - InnerCommitMatrixParams, - SisMatrixRole::Inner, - "Parameters for the inner commitment matrix (A)." -); define_commit_matrix_params!( OuterCommitMatrixParams, SisMatrixRole::Outer, @@ -628,6 +935,10 @@ define_commit_matrix_params!( #[path = "ajtai_key/artifact_tests.rs"] mod artifact_tests; +#[cfg(test)] +#[path = "ajtai_key_tests.rs"] +mod l2_tests; + #[cfg(test)] mod tests { use super::*; diff --git a/crates/akita-types/src/sis/ajtai_key_tests.rs b/crates/akita-types/src/sis/ajtai_key_tests.rs new file mode 100644 index 000000000..9376aa023 --- /dev/null +++ b/crates/akita-types/src/sis/ajtai_key_tests.rs @@ -0,0 +1,142 @@ +use super::*; +use crate::sis::{ + ceil_supported_l2_collision_sq, sis_l2_table_key_for_collision_sq, SisL2TableDigest, +}; + +#[test] +fn l2_key_rounds_the_complete_collision_to_a_power_of_two() { + assert_eq!(ceil_supported_l2_collision_sq(1), Some(2)); + assert_eq!(ceil_supported_l2_collision_sq(2), Some(2)); + assert_eq!(ceil_supported_l2_collision_sq(3), Some(4)); + assert_eq!( + ceil_supported_l2_collision_sq(1u128 << 84), + Some(1u128 << 84) + ); + assert_eq!(ceil_supported_l2_collision_sq((1u128 << 84) + 1), None); +} + +#[test] +fn l2_table_has_the_expected_q128_d64_rank_boundary() { + let key = sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest::CURRENT, + SisModulusProfileId::Q128OffsetA7F7, + 64, + 1u128 << 50, + ) + .expect("generated L2 key"); + assert_eq!(min_secure_l2_rank(key, 21), Some(3)); + assert_eq!(min_secure_l2_rank(key, 22), Some(4)); + assert_eq!(min_secure_l2_rank(key, 512), Some(4)); +} + +#[test] +fn l2_lookup_rejects_an_unknown_table_digest() { + assert!(sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest([0u8; 32]), + SisModulusProfileId::Q128OffsetA7F7, + 64, + 1u128 << 50, + ) + .is_none()); +} + +#[test] +fn inner_l2_route_owns_its_cap_shape_and_table_identity() { + let table_key = sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest::CURRENT, + SisModulusProfileId::Q128OffsetA7F7, + 64, + 1u128 << 50, + ) + .expect("generated L2 key"); + let shape = PhysicalL2NormProofShape::Direct { + physical_response_len: 21 * 64, + }; + let matrix = + InnerCommitMatrixParams::try_new_l2_with_min_rank(table_key, 21, 1u128 << 30, shape) + .expect("audited L2 matrix"); + + assert_eq!(matrix.output_rank(), 3); + assert_eq!(matrix.sis_table_key(), None); + assert_eq!(matrix.coeff_linf_bound(), None); + assert_eq!( + matrix.security_route(), + InnerCommitSecurityRoute::L2 { + table_key, + response_l2_sq_cap: 1u128 << 30, + norm_proof_shape: shape, + } + ); + matrix.validate().expect("L2 route re-audits"); + + let mut descriptor = Vec::new(); + matrix.append_descriptor_bytes(&mut descriptor); + let different_cap = + InnerCommitMatrixParams::try_new_l2_with_min_rank(table_key, 21, (1u128 << 30) - 1, shape) + .expect("second audited L2 matrix"); + let mut different_descriptor = Vec::new(); + different_cap.append_descriptor_bytes(&mut different_descriptor); + assert_ne!(descriptor, different_descriptor); +} + +#[test] +fn inner_l2_route_rejects_a_shape_inconsistent_with_matrix_width() { + let table_key = sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest::CURRENT, + SisModulusProfileId::Q128OffsetA7F7, + 64, + 1u128 << 50, + ) + .expect("generated L2 key"); + let mismatched = PhysicalL2NormProofShape::Direct { + physical_response_len: 512, + }; + assert!(InnerCommitMatrixParams::try_new_l2_with_min_rank( + table_key, + 21, + 1u128 << 30, + mismatched, + ) + .is_err()); + + let matrix = InnerCommitMatrixParams::try_new_l2_with_min_rank( + table_key, + 21, + 1u128 << 30, + PhysicalL2NormProofShape::Direct { + physical_response_len: 21 * 64, + }, + ) + .expect("consistent L2 matrix"); + assert!(matrix.try_with_input_width(22).is_err()); +} + +#[test] +fn physical_norm_shape_derivation_selects_direct_or_limb_gram() { + let direct = PhysicalL2NormProofShape::derive(SisModulusProfileId::Q128OffsetA7F7, 64, 4, 2) + .expect("large-field direct shape"); + assert_eq!( + direct, + PhysicalL2NormProofShape::Direct { + physical_response_len: 64 + } + ); + + let gram = PhysicalL2NormProofShape::derive(SisModulusProfileId::Q32Offset99, 1 << 22, 64, 5) + .expect("small-field limb-Gram shape"); + let PhysicalL2NormProofShape::LimbGram { + physical_response_len, + block_len, + limb_count, + } = gram + else { + panic!("expected limb-Gram shape"); + }; + assert_eq!(physical_response_len, 1 << 22); + assert_eq!(limb_count, 5); + assert!((1..physical_response_len).contains(&block_len)); +} diff --git a/crates/akita-types/src/sis/generated_l2_sis_table/mod.rs b/crates/akita-types/src/sis/generated_l2_sis_table/mod.rs new file mode 100644 index 000000000..cee6e5387 --- /dev/null +++ b/crates/akita-types/src/sis/generated_l2_sis_table/mod.rs @@ -0,0 +1,32 @@ +// AUTO-GENERATED by crates/akita-sis-estimator/examples/euclidean_width_table.rs -- do not edit by hand. +// +// SIS width thresholds for 128-bit quantum security (ADPS16, Euclidean norm=2). +// Rust estimator path: akita-sis-estimator::euclidean_width_table. +// Keys bound the squared norm of the complete scalar collision vector. + +mod q128; +mod q32; +mod q64; + +use super::SisModulusProfileId; + +/// SHA-256 digest of the generated audit CSV, including every accepted boundary and rejected successor. +pub(crate) const TABLE_DIGEST: [u8; 32] = [ + 0xa1, 0xcc, 0x0a, 0x06, 0x08, 0x97, 0x44, 0x14, 0x5b, 0x61, 0x91, 0x9c, 0xf0, 0x01, 0xea, 0x26, + 0x0c, 0x95, 0xa4, 0xbb, 0xa1, 0x61, 0xff, 0xda, 0xff, 0x55, 0x39, 0x1d, 0x0d, 0xfa, 0x10, 0x2a, +]; + +/// Generated SIS max-width table: for each `(family, d, collision_l2_sq)` the +/// maximum secure ring-element width per module rank (`widths[rank - 1]`). +#[rustfmt::skip] +pub(crate) fn sis_max_widths( + family: SisModulusProfileId, + d: u32, + collision_l2_sq: u128, +) -> Option<&'static [u64]> { + match family { + SisModulusProfileId::Q32Offset99 => q32::sis_max_widths(d, collision_l2_sq), + SisModulusProfileId::Q64Offset59 => q64::sis_max_widths(d, collision_l2_sq), + SisModulusProfileId::Q128OffsetA7F7 => q128::sis_max_widths(d, collision_l2_sq), + } +} diff --git a/crates/akita-types/src/sis/generated_l2_sis_table/q128.rs b/crates/akita-types/src/sis/generated_l2_sis_table/q128.rs new file mode 100644 index 000000000..d6db36f8f --- /dev/null +++ b/crates/akita-types/src/sis/generated_l2_sis_table/q128.rs @@ -0,0 +1,434 @@ +// AUTO-GENERATED by crates/akita-sis-estimator/examples/euclidean_width_table.rs -- do not edit by hand. +// +// SIS width thresholds for 128-bit quantum security (ADPS16, Euclidean norm=2). +// Rust estimator path: akita-sis-estimator::euclidean_width_table. +// Keys bound the squared norm of the complete scalar collision vector. + +// Family: Q128 + +#[rustfmt::skip] +pub(super) fn sis_max_widths(d: u32, collision_l2_sq: u128) -> Option<&'static [u64]> { + match (d, collision_l2_sq) { + (32, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 524288) => Some(&[20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1048576) => Some(&[18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2097152) => Some(&[16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4194304) => Some(&[14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8388608) => Some(&[14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16777216) => Some(&[13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 33554432) => Some(&[12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 67108864) => Some(&[11, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 134217728) => Some(&[11, 28, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 268435456) => Some(&[10, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 536870912) => Some(&[10, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1073741824) => Some(&[9, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2147483648) => Some(&[9, 21, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4294967296) => Some(&[9, 20, 40, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8589934592) => Some(&[8, 19, 35, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 17179869184) => Some(&[8, 18, 32, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 34359738368) => Some(&[8, 17, 30, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 68719476736) => Some(&[7, 16, 28, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 137438953472) => Some(&[7, 16, 27, 46, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 274877906944) => Some(&[7, 15, 25, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 549755813888) => Some(&[7, 14, 24, 38, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1099511627776) => Some(&[7, 14, 23, 36, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2199023255552) => Some(&[6, 14, 22, 34, 54, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4398046511104) => Some(&[6, 13, 21, 32, 48, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8796093022208) => Some(&[6, 13, 21, 30, 44, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 17592186044416) => Some(&[6, 13, 20, 29, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 35184372088832) => Some(&[6, 12, 19, 28, 39, 58, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 70368744177664) => Some(&[6, 12, 19, 27, 37, 53, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 140737488355328) => Some(&[5, 12, 18, 26, 36, 49, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 281474976710656) => Some(&[5, 11, 18, 25, 34, 46, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 562949953421312) => Some(&[5, 11, 17, 24, 33, 44, 60, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1125899906842624) => Some(&[5, 11, 17, 24, 32, 42, 55, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2251799813685248) => Some(&[5, 10, 16, 23, 31, 40, 52, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4503599627370496) => Some(&[5, 10, 16, 22, 30, 38, 49, 67, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 9007199254740992) => Some(&[5, 10, 16, 22, 29, 37, 47, 61, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 18014398509481984) => Some(&[5, 10, 15, 21, 28, 36, 45, 57, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 36028797018963968) => Some(&[4, 10, 15, 21, 27, 35, 43, 54, 73, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 72057594037927936) => Some(&[4, 9, 15, 20, 27, 34, 42, 52, 66, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 144115188075855872) => Some(&[4, 9, 14, 20, 26, 33, 40, 50, 62, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 288230376151711744) => Some(&[4, 9, 14, 19, 25, 32, 39, 48, 59, 76, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 576460752303423488) => Some(&[4, 9, 14, 19, 25, 31, 38, 46, 56, 70, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1152921504606846976) => Some(&[4, 9, 13, 18, 24, 30, 37, 44, 54, 66, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2305843009213693952) => Some(&[4, 8, 13, 18, 24, 29, 36, 43, 52, 62, 79, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4611686018427387904) => Some(&[4, 8, 13, 18, 23, 29, 35, 42, 50, 59, 73, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 9223372036854775808) => Some(&[4, 8, 13, 17, 23, 28, 34, 41, 48, 57, 68, 91, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 18446744073709551616) => Some(&[4, 8, 12, 17, 22, 27, 33, 40, 47, 55, 65, 80, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 36893488147419103232) => Some(&[4, 8, 12, 17, 22, 27, 32, 39, 45, 53, 62, 75, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 73786976294838206464) => Some(&[4, 8, 12, 16, 21, 26, 32, 38, 44, 51, 60, 71, 89, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 147573952589676412928) => Some(&[3, 8, 12, 16, 21, 26, 31, 37, 43, 50, 58, 68, 81, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 295147905179352825856) => Some(&[3, 7, 12, 16, 20, 25, 30, 36, 42, 48, 56, 65, 76, 99, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 590295810358705651712) => Some(&[3, 7, 11, 16, 20, 25, 30, 35, 41, 47, 54, 63, 73, 88, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1180591620717411303424) => Some(&[3, 7, 11, 15, 20, 24, 29, 34, 40, 46, 53, 60, 70, 82, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2361183241434822606848) => Some(&[3, 7, 11, 15, 19, 24, 29, 34, 39, 45, 51, 59, 67, 78, 94, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4722366482869645213696) => Some(&[3, 7, 11, 15, 19, 23, 28, 33, 38, 44, 50, 57, 65, 74, 87, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 9444732965739290427392) => Some(&[3, 7, 11, 15, 19, 23, 27, 32, 37, 43, 49, 55, 63, 71, 82, 101, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 18889465931478580854784) => Some(&[3, 7, 11, 14, 18, 23, 27, 32, 37, 42, 48, 54, 61, 69, 79, 92, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 37778931862957161709568) => Some(&[3, 7, 10, 14, 18, 22, 27, 31, 36, 41, 47, 52, 59, 67, 75, 87, 108, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 75557863725914323419136) => Some(&[3, 7, 10, 14, 18, 22, 26, 31, 35, 40, 45, 51, 58, 65, 73, 83, 97, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 151115727451828646838272) => Some(&[3, 6, 10, 14, 17, 21, 26, 30, 35, 39, 45, 50, 56, 63, 70, 79, 91, 116, 6_400_000_000_000, 6_400_000_000_000]), + (32, 302231454903657293676544) => Some(&[3, 6, 10, 13, 17, 21, 25, 29, 34, 39, 44, 49, 55, 61, 68, 76, 86, 101, 6_400_000_000_000, 6_400_000_000_000]), + (32, 604462909807314587353088) => Some(&[3, 6, 10, 13, 17, 21, 25, 29, 33, 38, 43, 48, 53, 60, 66, 74, 83, 95, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1208925819614629174706176) => Some(&[3, 6, 10, 13, 17, 20, 24, 28, 33, 37, 42, 47, 52, 58, 64, 72, 80, 90, 105, 6_400_000_000_000]), + (32, 2417851639229258349412352) => Some(&[3, 6, 10, 13, 16, 20, 24, 28, 32, 37, 41, 46, 51, 57, 63, 70, 77, 86, 98, 6_400_000_000_000]), + (32, 4835703278458516698824704) => Some(&[3, 6, 9, 13, 16, 20, 24, 28, 32, 36, 40, 45, 50, 55, 61, 68, 75, 83, 93, 109]), + (32, 9671406556917033397649408) => Some(&[3, 6, 9, 13, 16, 20, 23, 27, 31, 35, 40, 44, 49, 54, 60, 66, 73, 80, 89, 101]), + (32, 19342813113834066795298816) => Some(&[3, 6, 9, 12, 16, 19, 23, 27, 31, 35, 39, 43, 48, 53, 59, 64, 71, 78, 86, 96]), + (64, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 67108864) => Some(&[16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 134217728) => Some(&[14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 268435456) => Some(&[13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 536870912) => Some(&[12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1073741824) => Some(&[11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2147483648) => Some(&[10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4294967296) => Some(&[10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8589934592) => Some(&[9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 17179869184) => Some(&[9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 34359738368) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 68719476736) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 137438953472) => Some(&[8, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 274877906944) => Some(&[7, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 549755813888) => Some(&[7, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1099511627776) => Some(&[7, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2199023255552) => Some(&[7, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4398046511104) => Some(&[6, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8796093022208) => Some(&[6, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 17592186044416) => Some(&[6, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 35184372088832) => Some(&[6, 14, 29, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 70368744177664) => Some(&[6, 13, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 140737488355328) => Some(&[6, 13, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 281474976710656) => Some(&[5, 12, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 562949953421312) => Some(&[5, 12, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1125899906842624) => Some(&[5, 12, 21, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2251799813685248) => Some(&[5, 11, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4503599627370496) => Some(&[5, 11, 19, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9007199254740992) => Some(&[5, 11, 18, 30, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 18014398509481984) => Some(&[5, 10, 18, 28, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 36028797018963968) => Some(&[5, 10, 17, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 72057594037927936) => Some(&[4, 10, 17, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 144115188075855872) => Some(&[4, 10, 16, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 288230376151711744) => Some(&[4, 9, 16, 24, 38, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 576460752303423488) => Some(&[4, 9, 15, 23, 35, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1152921504606846976) => Some(&[4, 9, 15, 22, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2305843009213693952) => Some(&[4, 9, 14, 21, 31, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4611686018427387904) => Some(&[4, 9, 14, 21, 29, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9223372036854775808) => Some(&[4, 8, 14, 20, 28, 45, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 18446744073709551616) => Some(&[4, 8, 13, 20, 27, 40, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 36893488147419103232) => Some(&[4, 8, 13, 19, 26, 37, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 73786976294838206464) => Some(&[4, 8, 13, 19, 25, 35, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 147573952589676412928) => Some(&[4, 8, 13, 18, 25, 34, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 295147905179352825856) => Some(&[3, 8, 12, 18, 24, 32, 49, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 590295810358705651712) => Some(&[3, 8, 12, 17, 23, 31, 44, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1180591620717411303424) => Some(&[3, 7, 12, 17, 23, 30, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2361183241434822606848) => Some(&[3, 7, 12, 17, 22, 29, 39, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4722366482869645213696) => Some(&[3, 7, 11, 16, 22, 28, 37, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9444732965739290427392) => Some(&[3, 7, 11, 16, 21, 27, 35, 50, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 18889465931478580854784) => Some(&[3, 7, 11, 16, 21, 27, 34, 46, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 37778931862957161709568) => Some(&[3, 7, 11, 15, 20, 26, 33, 43, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 75557863725914323419136) => Some(&[3, 7, 11, 15, 20, 25, 32, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 151115727451828646838272) => Some(&[3, 7, 10, 15, 19, 25, 31, 39, 58, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 302231454903657293676544) => Some(&[3, 6, 10, 14, 19, 24, 30, 38, 50, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 604462909807314587353088) => Some(&[3, 6, 10, 14, 19, 24, 30, 37, 47, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1208925819614629174706176) => Some(&[3, 6, 10, 14, 18, 23, 29, 36, 45, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2417851639229258349412352) => Some(&[3, 6, 10, 14, 18, 23, 28, 35, 43, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4835703278458516698824704) => Some(&[3, 6, 10, 14, 18, 22, 27, 34, 41, 54, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9671406556917033397649408) => Some(&[3, 6, 10, 13, 17, 22, 27, 33, 40, 50, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 19342813113834066795298816) => Some(&[3, 6, 9, 13, 17, 21, 26, 32, 39, 48, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 67108864) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 134217728) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 268435456) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 536870912) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1073741824) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2147483648) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4294967296) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8589934592) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 17179869184) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 34359738368) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 68719476736) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 137438953472) => Some(&[11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 274877906944) => Some(&[10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 549755813888) => Some(&[9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1099511627776) => Some(&[9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2199023255552) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4398046511104) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8796093022208) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 17592186044416) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 35184372088832) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 70368744177664) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 140737488355328) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 281474976710656) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 562949953421312) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1125899906842624) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2251799813685248) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4503599627370496) => Some(&[5, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9007199254740992) => Some(&[5, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 18014398509481984) => Some(&[5, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 36028797018963968) => Some(&[5, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 72057594037927936) => Some(&[5, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 144115188075855872) => Some(&[5, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 288230376151711744) => Some(&[4, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 576460752303423488) => Some(&[4, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1152921504606846976) => Some(&[4, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2305843009213693952) => Some(&[4, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4611686018427387904) => Some(&[4, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9223372036854775808) => Some(&[4, 10, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 18446744073709551616) => Some(&[4, 10, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 36893488147419103232) => Some(&[4, 9, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 73786976294838206464) => Some(&[4, 9, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 147573952589676412928) => Some(&[4, 9, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 295147905179352825856) => Some(&[4, 9, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 590295810358705651712) => Some(&[4, 8, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1180591620717411303424) => Some(&[3, 8, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2361183241434822606848) => Some(&[3, 8, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4722366482869645213696) => Some(&[3, 8, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9444732965739290427392) => Some(&[3, 8, 13, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 18889465931478580854784) => Some(&[3, 8, 13, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 37778931862957161709568) => Some(&[3, 7, 13, 21, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 75557863725914323419136) => Some(&[3, 7, 12, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 151115727451828646838272) => Some(&[3, 7, 12, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 302231454903657293676544) => Some(&[3, 7, 12, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 604462909807314587353088) => Some(&[3, 7, 12, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1208925819614629174706176) => Some(&[3, 7, 11, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2417851639229258349412352) => Some(&[3, 7, 11, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4835703278458516698824704) => Some(&[3, 7, 11, 17, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9671406556917033397649408) => Some(&[3, 6, 11, 16, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 19342813113834066795298816) => Some(&[3, 6, 10, 16, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 67108864) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 134217728) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 268435456) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 536870912) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1073741824) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2147483648) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4294967296) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8589934592) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 17179869184) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 34359738368) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 68719476736) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 137438953472) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 274877906944) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 549755813888) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1099511627776) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2199023255552) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4398046511104) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8796093022208) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 17592186044416) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 35184372088832) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 70368744177664) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 140737488355328) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 281474976710656) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 562949953421312) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1125899906842624) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2251799813685248) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4503599627370496) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9007199254740992) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 18014398509481984) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 36028797018963968) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 72057594037927936) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 144115188075855872) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 288230376151711744) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 576460752303423488) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1152921504606846976) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2305843009213693952) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4611686018427387904) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9223372036854775808) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 18446744073709551616) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 36893488147419103232) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 73786976294838206464) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 147573952589676412928) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 295147905179352825856) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 590295810358705651712) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1180591620717411303424) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2361183241434822606848) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4722366482869645213696) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9444732965739290427392) => Some(&[4, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 18889465931478580854784) => Some(&[4, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 37778931862957161709568) => Some(&[3, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 75557863725914323419136) => Some(&[3, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 151115727451828646838272) => Some(&[3, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 302231454903657293676544) => Some(&[3, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 604462909807314587353088) => Some(&[3, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1208925819614629174706176) => Some(&[3, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2417851639229258349412352) => Some(&[3, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4835703278458516698824704) => Some(&[3, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9671406556917033397649408) => Some(&[3, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 19342813113834066795298816) => Some(&[3, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 67108864) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 134217728) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 268435456) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 536870912) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1073741824) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2147483648) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4294967296) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8589934592) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 17179869184) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 34359738368) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 68719476736) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 137438953472) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 274877906944) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 549755813888) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1099511627776) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2199023255552) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4398046511104) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8796093022208) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 17592186044416) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 35184372088832) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 70368744177664) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 140737488355328) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 281474976710656) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 562949953421312) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1125899906842624) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2251799813685248) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4503599627370496) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9007199254740992) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 18014398509481984) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 36028797018963968) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 72057594037927936) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 144115188075855872) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 288230376151711744) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 576460752303423488) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1152921504606846976) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2305843009213693952) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4611686018427387904) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9223372036854775808) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 18446744073709551616) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 36893488147419103232) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 73786976294838206464) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 147573952589676412928) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 295147905179352825856) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 590295810358705651712) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1180591620717411303424) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2361183241434822606848) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4722366482869645213696) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9444732965739290427392) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 18889465931478580854784) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 37778931862957161709568) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 75557863725914323419136) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 151115727451828646838272) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 302231454903657293676544) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 604462909807314587353088) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1208925819614629174706176) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2417851639229258349412352) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4835703278458516698824704) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9671406556917033397649408) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 19342813113834066795298816) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + _ => None, + } +} diff --git a/crates/akita-types/src/sis/generated_l2_sis_table/q32.rs b/crates/akita-types/src/sis/generated_l2_sis_table/q32.rs new file mode 100644 index 000000000..b64507937 --- /dev/null +++ b/crates/akita-types/src/sis/generated_l2_sis_table/q32.rs @@ -0,0 +1,319 @@ +// AUTO-GENERATED by crates/akita-sis-estimator/examples/euclidean_width_table.rs -- do not edit by hand. +// +// SIS width thresholds for 128-bit quantum security (ADPS16, Euclidean norm=2). +// Rust estimator path: akita-sis-estimator::euclidean_width_table. +// Keys bound the squared norm of the complete scalar collision vector. + +// Family: Q32 + +#[rustfmt::skip] +pub(super) fn sis_max_widths(d: u32, collision_l2_sq: u128) -> Option<&'static [u64]> { + match (d, collision_l2_sq) { + (32, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1024) => Some(&[11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2048) => Some(&[9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4096) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8192) => Some(&[6, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16384) => Some(&[6, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 32768) => Some(&[5, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 65536) => Some(&[5, 11, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 131072) => Some(&[4, 10, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 262144) => Some(&[4, 9, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 524288) => Some(&[3, 8, 13, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1048576) => Some(&[3, 7, 12, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2097152) => Some(&[3, 7, 11, 16, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4194304) => Some(&[3, 7, 10, 14, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8388608) => Some(&[3, 6, 10, 14, 18, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16777216) => Some(&[2, 6, 9, 13, 17, 23, 36, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 33554432) => Some(&[2, 5, 9, 12, 16, 21, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 67108864) => Some(&[2, 5, 8, 11, 15, 19, 24, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 134217728) => Some(&[2, 5, 8, 11, 14, 18, 22, 28, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 268435456) => Some(&[2, 5, 7, 10, 13, 17, 21, 26, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 536870912) => Some(&[2, 4, 7, 10, 13, 16, 19, 24, 29, 38, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1073741824) => Some(&[2, 4, 7, 9, 12, 15, 18, 22, 27, 32, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2147483648) => Some(&[2, 4, 7, 9, 12, 14, 17, 21, 25, 29, 36, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4294967296) => Some(&[2, 4, 6, 9, 11, 14, 16, 20, 23, 27, 32, 40, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8589934592) => Some(&[2, 4, 6, 8, 11, 13, 16, 19, 22, 25, 30, 35, 44, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 17179869184) => Some(&[2, 4, 6, 8, 10, 13, 15, 18, 21, 24, 28, 32, 38, 49, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 34359738368) => Some(&[1, 3, 6, 8, 10, 12, 14, 17, 20, 23, 26, 30, 35, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 68719476736) => Some(&[1, 3, 5, 7, 10, 12, 14, 16, 19, 22, 25, 28, 32, 37, 43, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 137438953472) => Some(&[1, 3, 5, 7, 9, 11, 13, 16, 18, 21, 24, 27, 30, 34, 39, 46, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 274877906944) => Some(&[1, 3, 5, 7, 9, 11, 13, 15, 17, 20, 22, 25, 29, 32, 36, 41, 48, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 549755813888) => Some(&[1, 3, 5, 7, 9, 11, 13, 14, 17, 19, 22, 24, 27, 30, 34, 38, 43, 50, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1099511627776) => Some(&[1, 3, 5, 7, 8, 10, 12, 14, 16, 18, 21, 23, 26, 29, 32, 36, 40, 45, 52, 6_400_000_000_000]), + (32, 2199023255552) => Some(&[1, 3, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 27, 30, 34, 37, 41, 46, 54]), + (32, 4398046511104) => Some(&[1, 3, 4, 6, 8, 10, 11, 13, 15, 17, 19, 21, 24, 26, 29, 32, 35, 39, 43, 48]), + (32, 8796093022208) => Some(&[1, 3, 4, 6, 8, 9, 11, 13, 15, 17, 19, 21, 23, 25, 28, 30, 33, 37, 40, 44]), + (32, 17592186044416) => Some(&[1, 3, 4, 6, 7, 9, 11, 13, 14, 16, 18, 20, 22, 24, 27, 29, 32, 35, 38, 41]), + (32, 35184372088832) => Some(&[1, 3, 4, 6, 7, 9, 11, 12, 14, 16, 17, 19, 21, 24, 26, 28, 31, 33, 36, 39]), + (32, 70368744177664) => Some(&[1, 2, 4, 6, 7, 9, 10, 12, 13, 15, 17, 19, 21, 23, 25, 27, 29, 32, 34, 37]), + (32, 140737488355328) => Some(&[1, 2, 4, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 22, 24, 26, 28, 31, 33, 36]), + (32, 281474976710656) => Some(&[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 18, 20, 21, 23, 25, 27, 30, 32, 34]), + (32, 562949953421312) => Some(&[1, 2, 4, 5, 7, 8, 10, 11, 12, 14, 16, 17, 19, 21, 23, 24, 26, 29, 31, 33]), + (32, 1125899906842624) => Some(&[1, 2, 4, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 22, 24, 26, 28, 30, 32]), + (32, 2251799813685248) => Some(&[1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31]), + (32, 4503599627370496) => Some(&[1, 2, 3, 5, 6, 7, 9, 10, 12, 13, 14, 16, 18, 19, 21, 22, 24, 26, 28, 30]), + (32, 9007199254740992) => Some(&[1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 16, 17, 19, 20, 22, 24, 25, 27, 29]), + (32, 18014398509481984) => Some(&[1, 2, 3, 5, 6, 7, 8, 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 26, 28]), + (32, 36028797018963968) => Some(&[1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 21, 22, 24, 26, 27]), + (32, 72057594037927936) => Some(&[1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20, 22, 23, 25, 27]), + (32, 144115188075855872) => Some(&[1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 23, 24, 26]), + (32, 288230376151711744) => Some(&[1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 17, 18, 19, 21, 22, 24, 25]), + (32, 576460752303423488) => Some(&[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 16, 18, 19, 20, 22, 23, 25]), + (32, 1152921504606846976) => Some(&[1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 15, 16, 17, 18, 20, 21, 23, 24]), + (32, 2305843009213693952) => Some(&[1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 21, 22, 24]), + (64, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8192) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16384) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 32768) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 65536) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 131072) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 262144) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 524288) => Some(&[4, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1048576) => Some(&[3, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2097152) => Some(&[3, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4194304) => Some(&[3, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8388608) => Some(&[3, 7, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16777216) => Some(&[3, 6, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 33554432) => Some(&[2, 6, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 67108864) => Some(&[2, 5, 9, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 134217728) => Some(&[2, 5, 9, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 268435456) => Some(&[2, 5, 8, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 536870912) => Some(&[2, 5, 8, 12, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1073741824) => Some(&[2, 4, 7, 11, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2147483648) => Some(&[2, 4, 7, 10, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4294967296) => Some(&[2, 4, 7, 10, 13, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8589934592) => Some(&[2, 4, 6, 9, 12, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 17179869184) => Some(&[2, 4, 6, 9, 12, 16, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 34359738368) => Some(&[1, 4, 6, 8, 11, 15, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 68719476736) => Some(&[1, 3, 6, 8, 11, 14, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 137438953472) => Some(&[1, 3, 5, 8, 10, 13, 17, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 274877906944) => Some(&[1, 3, 5, 7, 10, 12, 16, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 549755813888) => Some(&[1, 3, 5, 7, 9, 12, 15, 19, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1099511627776) => Some(&[1, 3, 5, 7, 9, 11, 14, 18, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2199023255552) => Some(&[1, 3, 5, 7, 9, 11, 13, 17, 20, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4398046511104) => Some(&[1, 3, 5, 6, 8, 10, 13, 16, 19, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8796093022208) => Some(&[1, 3, 4, 6, 8, 10, 12, 15, 18, 22, 28, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 17592186044416) => Some(&[1, 3, 4, 6, 8, 10, 12, 14, 17, 20, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 35184372088832) => Some(&[1, 3, 4, 6, 8, 9, 12, 14, 16, 19, 23, 29, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 70368744177664) => Some(&[1, 3, 4, 6, 7, 9, 11, 13, 16, 18, 22, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 140737488355328) => Some(&[1, 2, 4, 6, 7, 9, 11, 13, 15, 18, 21, 24, 30, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 281474976710656) => Some(&[1, 2, 4, 5, 7, 9, 10, 12, 15, 17, 20, 23, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 562949953421312) => Some(&[1, 2, 4, 5, 7, 8, 10, 12, 14, 16, 19, 22, 25, 30, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1125899906842624) => Some(&[1, 2, 4, 5, 7, 8, 10, 12, 14, 16, 18, 21, 24, 27, 34, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2251799813685248) => Some(&[1, 2, 4, 5, 6, 8, 10, 11, 13, 15, 17, 20, 22, 26, 30, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4503599627370496) => Some(&[1, 2, 3, 5, 6, 8, 9, 11, 13, 15, 17, 19, 21, 24, 28, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9007199254740992) => Some(&[1, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 18, 21, 23, 26, 30, 38, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 18014398509481984) => Some(&[1, 2, 3, 5, 6, 7, 9, 10, 12, 14, 16, 18, 20, 22, 25, 28, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 36028797018963968) => Some(&[1, 2, 3, 5, 6, 7, 9, 10, 12, 13, 15, 17, 19, 21, 24, 27, 31, 36, 6_400_000_000_000, 6_400_000_000_000]), + (64, 72057594037927936) => Some(&[1, 2, 3, 4, 6, 7, 8, 10, 11, 13, 15, 17, 18, 21, 23, 26, 29, 33, 41, 6_400_000_000_000]), + (64, 144115188075855872) => Some(&[1, 2, 3, 4, 6, 7, 8, 10, 11, 13, 14, 16, 18, 20, 22, 25, 27, 31, 35, 6_400_000_000_000]), + (64, 288230376151711744) => Some(&[1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 14, 16, 17, 19, 21, 24, 26, 29, 33, 38]), + (64, 576460752303423488) => Some(&[1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 19, 21, 23, 25, 28, 31, 35]), + (64, 1152921504606846976) => Some(&[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 15, 16, 18, 20, 22, 24, 27, 29, 33]), + (64, 2305843009213693952) => Some(&[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 18, 19, 21, 23, 26, 28, 31]), + (128, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 524288) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1048576) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2097152) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4194304) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8388608) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16777216) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 33554432) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 67108864) => Some(&[2, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 134217728) => Some(&[2, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 268435456) => Some(&[2, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 536870912) => Some(&[2, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1073741824) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2147483648) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4294967296) => Some(&[2, 5, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8589934592) => Some(&[2, 4, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 17179869184) => Some(&[2, 4, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 34359738368) => Some(&[2, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 68719476736) => Some(&[1, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 137438953472) => Some(&[1, 4, 6, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 274877906944) => Some(&[1, 3, 6, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 549755813888) => Some(&[1, 3, 6, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1099511627776) => Some(&[1, 3, 5, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2199023255552) => Some(&[1, 3, 5, 8, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4398046511104) => Some(&[1, 3, 5, 8, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8796093022208) => Some(&[1, 3, 5, 7, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 17592186044416) => Some(&[1, 3, 5, 7, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 35184372088832) => Some(&[1, 3, 4, 7, 9, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 70368744177664) => Some(&[1, 3, 4, 6, 9, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 140737488355328) => Some(&[1, 3, 4, 6, 9, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 281474976710656) => Some(&[1, 2, 4, 6, 8, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 562949953421312) => Some(&[1, 2, 4, 6, 8, 11, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1125899906842624) => Some(&[1, 2, 4, 6, 8, 10, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2251799813685248) => Some(&[1, 2, 4, 5, 7, 10, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4503599627370496) => Some(&[1, 2, 4, 5, 7, 9, 12, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9007199254740992) => Some(&[1, 2, 4, 5, 7, 9, 11, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 18014398509481984) => Some(&[1, 2, 3, 5, 7, 9, 11, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 36028797018963968) => Some(&[1, 2, 3, 5, 6, 8, 10, 13, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 72057594037927936) => Some(&[1, 2, 3, 5, 6, 8, 10, 13, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 144115188075855872) => Some(&[1, 2, 3, 5, 6, 8, 10, 12, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 288230376151711744) => Some(&[1, 2, 3, 4, 6, 8, 9, 12, 14, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 576460752303423488) => Some(&[1, 2, 3, 4, 6, 7, 9, 11, 14, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1152921504606846976) => Some(&[1, 2, 3, 4, 6, 7, 9, 11, 13, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2305843009213693952) => Some(&[1, 2, 3, 4, 6, 7, 9, 10, 13, 15, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 67108864) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 134217728) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 268435456) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 536870912) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1073741824) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2147483648) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4294967296) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8589934592) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 17179869184) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 34359738368) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 68719476736) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 137438953472) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 274877906944) => Some(&[1, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 549755813888) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1099511627776) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2199023255552) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4398046511104) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8796093022208) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 17592186044416) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 35184372088832) => Some(&[1, 3, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 70368744177664) => Some(&[1, 3, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 140737488355328) => Some(&[1, 3, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 281474976710656) => Some(&[1, 3, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 562949953421312) => Some(&[1, 3, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1125899906842624) => Some(&[1, 3, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2251799813685248) => Some(&[1, 2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4503599627370496) => Some(&[1, 2, 4, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9007199254740992) => Some(&[1, 2, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 18014398509481984) => Some(&[1, 2, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 36028797018963968) => Some(&[1, 2, 4, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 72057594037927936) => Some(&[1, 2, 4, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 144115188075855872) => Some(&[1, 2, 4, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 288230376151711744) => Some(&[1, 2, 4, 6, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 576460752303423488) => Some(&[1, 2, 3, 5, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1152921504606846976) => Some(&[1, 2, 3, 5, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2305843009213693952) => Some(&[1, 2, 3, 5, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 67108864) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 134217728) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 268435456) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 536870912) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1073741824) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2147483648) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4294967296) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8589934592) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 17179869184) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 34359738368) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 68719476736) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 137438953472) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 274877906944) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 549755813888) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1099511627776) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2199023255552) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4398046511104) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8796093022208) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 17592186044416) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 35184372088832) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 70368744177664) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 140737488355328) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 281474976710656) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 562949953421312) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1125899906842624) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2251799813685248) => Some(&[1, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4503599627370496) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9007199254740992) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 18014398509481984) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 36028797018963968) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 72057594037927936) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 144115188075855872) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 288230376151711744) => Some(&[1, 3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 576460752303423488) => Some(&[1, 2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1152921504606846976) => Some(&[1, 2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2305843009213693952) => Some(&[1, 2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + _ => None, + } +} diff --git a/crates/akita-types/src/sis/generated_l2_sis_table/q64.rs b/crates/akita-types/src/sis/generated_l2_sis_table/q64.rs new file mode 100644 index 000000000..de36663e4 --- /dev/null +++ b/crates/akita-types/src/sis/generated_l2_sis_table/q64.rs @@ -0,0 +1,434 @@ +// AUTO-GENERATED by crates/akita-sis-estimator/examples/euclidean_width_table.rs -- do not edit by hand. +// +// SIS width thresholds for 128-bit quantum security (ADPS16, Euclidean norm=2). +// Rust estimator path: akita-sis-estimator::euclidean_width_table. +// Keys bound the squared norm of the complete scalar collision vector. + +// Family: Q64 + +#[rustfmt::skip] +pub(super) fn sis_max_widths(d: u32, collision_l2_sq: u128) -> Option<&'static [u64]> { + match (d, collision_l2_sq) { + (32, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8192) => Some(&[16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16384) => Some(&[13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 32768) => Some(&[12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 65536) => Some(&[11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 131072) => Some(&[10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 262144) => Some(&[9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 524288) => Some(&[8, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1048576) => Some(&[7, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2097152) => Some(&[7, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4194304) => Some(&[7, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8388608) => Some(&[6, 14, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 16777216) => Some(&[6, 13, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 33554432) => Some(&[5, 12, 21, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 67108864) => Some(&[5, 11, 19, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 134217728) => Some(&[5, 11, 18, 28, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 268435456) => Some(&[5, 10, 17, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 536870912) => Some(&[4, 10, 16, 24, 38, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1073741824) => Some(&[4, 9, 15, 22, 32, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2147483648) => Some(&[4, 9, 14, 21, 29, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4294967296) => Some(&[4, 9, 14, 20, 27, 40, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8589934592) => Some(&[4, 8, 13, 19, 25, 35, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 17179869184) => Some(&[4, 8, 13, 18, 24, 32, 49, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 34359738368) => Some(&[3, 8, 12, 17, 23, 30, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 68719476736) => Some(&[3, 7, 12, 16, 22, 28, 37, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 137438953472) => Some(&[3, 7, 11, 16, 21, 27, 34, 46, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 274877906944) => Some(&[3, 7, 11, 15, 20, 25, 32, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 549755813888) => Some(&[3, 7, 11, 14, 19, 24, 30, 38, 50, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1099511627776) => Some(&[3, 7, 10, 14, 18, 23, 29, 36, 45, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2199023255552) => Some(&[3, 6, 10, 14, 18, 22, 27, 34, 41, 54, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4398046511104) => Some(&[3, 6, 10, 13, 17, 21, 26, 32, 39, 48, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 8796093022208) => Some(&[3, 6, 9, 13, 17, 21, 25, 30, 37, 44, 57, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 17592186044416) => Some(&[3, 6, 9, 13, 16, 20, 24, 29, 35, 41, 50, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 35184372088832) => Some(&[3, 6, 9, 12, 16, 19, 24, 28, 33, 39, 47, 58, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 70368744177664) => Some(&[2, 6, 9, 12, 15, 19, 23, 27, 32, 37, 44, 53, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 140737488355328) => Some(&[2, 5, 8, 12, 15, 18, 22, 26, 31, 36, 42, 49, 60, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 281474976710656) => Some(&[2, 5, 8, 11, 14, 18, 21, 25, 30, 34, 40, 46, 54, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 562949953421312) => Some(&[2, 5, 8, 11, 14, 17, 21, 24, 29, 33, 38, 44, 51, 60, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 1125899906842624) => Some(&[2, 5, 8, 11, 14, 17, 20, 24, 28, 32, 36, 42, 48, 55, 69, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 2251799813685248) => Some(&[2, 5, 8, 10, 13, 16, 20, 23, 27, 31, 35, 40, 45, 52, 61, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 4503599627370496) => Some(&[2, 5, 7, 10, 13, 16, 19, 22, 26, 30, 34, 38, 43, 49, 57, 67, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 9007199254740992) => Some(&[2, 5, 7, 10, 13, 16, 19, 22, 25, 29, 33, 37, 42, 47, 53, 61, 77, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 18014398509481984) => Some(&[2, 5, 7, 10, 12, 15, 18, 21, 25, 28, 32, 36, 40, 45, 51, 57, 67, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (32, 36028797018963968) => Some(&[2, 4, 7, 10, 12, 15, 18, 21, 24, 27, 31, 35, 39, 43, 48, 54, 62, 73, 6_400_000_000_000, 6_400_000_000_000]), + (32, 72057594037927936) => Some(&[2, 4, 7, 9, 12, 15, 17, 20, 23, 27, 30, 34, 37, 42, 46, 52, 58, 66, 82, 6_400_000_000_000]), + (32, 144115188075855872) => Some(&[2, 4, 7, 9, 12, 14, 17, 20, 23, 26, 29, 33, 36, 40, 45, 50, 55, 62, 71, 6_400_000_000_000]), + (32, 288230376151711744) => Some(&[2, 4, 7, 9, 11, 14, 17, 19, 22, 25, 28, 32, 35, 39, 43, 48, 53, 59, 66, 76]), + (32, 576460752303423488) => Some(&[2, 4, 6, 9, 11, 14, 16, 19, 22, 25, 28, 31, 34, 38, 42, 46, 51, 56, 62, 70]), + (32, 1152921504606846976) => Some(&[2, 4, 6, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 41, 44, 49, 54, 59, 66]), + (32, 2305843009213693952) => Some(&[2, 4, 6, 8, 11, 13, 16, 18, 21, 24, 26, 29, 33, 36, 39, 43, 47, 52, 56, 62]), + (32, 4611686018427387904) => Some(&[2, 4, 6, 8, 11, 13, 15, 18, 20, 23, 26, 29, 32, 35, 38, 42, 46, 50, 54, 59]), + (32, 9223372036854775808) => Some(&[2, 4, 6, 8, 10, 13, 15, 17, 20, 23, 25, 28, 31, 34, 37, 41, 44, 48, 52, 57]), + (32, 18446744073709551616) => Some(&[2, 4, 6, 8, 10, 12, 15, 17, 20, 22, 25, 27, 30, 33, 36, 40, 43, 47, 51, 55]), + (32, 36893488147419103232) => Some(&[2, 4, 6, 8, 10, 12, 14, 17, 19, 22, 24, 27, 30, 32, 35, 39, 42, 45, 49, 53]), + (32, 73786976294838206464) => Some(&[2, 4, 6, 8, 10, 12, 14, 16, 19, 21, 24, 26, 29, 32, 35, 38, 41, 44, 48, 51]), + (32, 147573952589676412928) => Some(&[1, 3, 6, 8, 10, 12, 14, 16, 18, 21, 23, 26, 28, 31, 34, 37, 40, 43, 46, 50]), + (32, 295147905179352825856) => Some(&[1, 3, 5, 7, 10, 12, 14, 16, 18, 20, 23, 25, 28, 30, 33, 36, 39, 42, 45, 48]), + (32, 590295810358705651712) => Some(&[1, 3, 5, 7, 9, 11, 13, 16, 18, 20, 22, 25, 27, 30, 32, 35, 38, 41, 44, 47]), + (32, 1180591620717411303424) => Some(&[1, 3, 5, 7, 9, 11, 13, 15, 17, 20, 22, 24, 27, 29, 32, 34, 37, 40, 43, 46]), + (32, 2361183241434822606848) => Some(&[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 22, 24, 26, 29, 31, 34, 36, 39, 42, 45]), + (32, 4722366482869645213696) => Some(&[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 26, 28, 30, 33, 36, 38, 41, 44]), + (32, 9444732965739290427392) => Some(&[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 30, 32, 35, 37, 40, 43]), + (32, 18889465931478580854784) => Some(&[1, 3, 5, 7, 9, 11, 12, 14, 16, 18, 20, 23, 25, 27, 29, 32, 34, 37, 39, 42]), + (32, 37778931862957161709568) => Some(&[1, 3, 5, 7, 9, 10, 12, 14, 16, 18, 20, 22, 24, 27, 29, 31, 33, 36, 38, 41]), + (32, 75557863725914323419136) => Some(&[1, 3, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 31, 33, 35, 38, 40]), + (32, 151115727451828646838272) => Some(&[1, 3, 5, 6, 8, 10, 12, 14, 16, 17, 19, 21, 24, 26, 28, 30, 32, 35, 37, 39]), + (32, 302231454903657293676544) => Some(&[1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 19, 21, 23, 25, 27, 29, 32, 34, 36, 39]), + (32, 604462909807314587353088) => Some(&[1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 36, 38]), + (32, 1208925819614629174706176) => Some(&[1, 3, 5, 6, 8, 10, 11, 13, 15, 17, 19, 20, 22, 24, 26, 28, 31, 33, 35, 37]), + (32, 2417851639229258349412352) => Some(&[1, 3, 4, 6, 8, 10, 11, 13, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 37]), + (32, 4835703278458516698824704) => Some(&[1, 3, 4, 6, 8, 9, 11, 13, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36]), + (32, 9671406556917033397649408) => Some(&[1, 3, 4, 6, 8, 9, 11, 13, 14, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35]), + (32, 19342813113834066795298816) => Some(&[1, 3, 4, 6, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, 27, 29, 31, 33, 35]), + (64, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 524288) => Some(&[10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1048576) => Some(&[9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2097152) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4194304) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8388608) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 16777216) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 33554432) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 67108864) => Some(&[5, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 134217728) => Some(&[5, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 268435456) => Some(&[5, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 536870912) => Some(&[5, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1073741824) => Some(&[4, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2147483648) => Some(&[4, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4294967296) => Some(&[4, 10, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8589934592) => Some(&[4, 9, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 17179869184) => Some(&[4, 9, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 34359738368) => Some(&[4, 8, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 68719476736) => Some(&[3, 8, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 137438953472) => Some(&[3, 8, 13, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 274877906944) => Some(&[3, 7, 12, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 549755813888) => Some(&[3, 7, 12, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1099511627776) => Some(&[3, 7, 11, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2199023255552) => Some(&[3, 7, 11, 17, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4398046511104) => Some(&[3, 6, 10, 16, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 8796093022208) => Some(&[3, 6, 10, 15, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 17592186044416) => Some(&[3, 6, 10, 14, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 35184372088832) => Some(&[3, 6, 9, 14, 19, 29, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 70368744177664) => Some(&[3, 6, 9, 13, 18, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 140737488355328) => Some(&[2, 6, 9, 13, 18, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 281474976710656) => Some(&[2, 5, 9, 12, 17, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 562949953421312) => Some(&[2, 5, 8, 12, 16, 22, 30, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1125899906842624) => Some(&[2, 5, 8, 12, 16, 21, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2251799813685248) => Some(&[2, 5, 8, 11, 15, 20, 26, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4503599627370496) => Some(&[2, 5, 8, 11, 15, 19, 24, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9007199254740992) => Some(&[2, 5, 8, 11, 14, 18, 23, 30, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 18014398509481984) => Some(&[2, 5, 7, 10, 14, 18, 22, 28, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 36028797018963968) => Some(&[2, 5, 7, 10, 13, 17, 21, 27, 36, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 72057594037927936) => Some(&[2, 4, 7, 10, 13, 17, 21, 26, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 144115188075855872) => Some(&[2, 4, 7, 10, 13, 16, 20, 25, 31, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 288230376151711744) => Some(&[2, 4, 7, 9, 12, 16, 19, 24, 29, 38, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 576460752303423488) => Some(&[2, 4, 7, 9, 12, 15, 19, 23, 28, 35, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1152921504606846976) => Some(&[2, 4, 6, 9, 12, 15, 18, 22, 27, 33, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2305843009213693952) => Some(&[2, 4, 6, 9, 12, 14, 18, 21, 26, 31, 39, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4611686018427387904) => Some(&[2, 4, 6, 9, 11, 14, 17, 21, 25, 29, 36, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9223372036854775808) => Some(&[2, 4, 6, 8, 11, 14, 17, 20, 24, 28, 34, 45, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 18446744073709551616) => Some(&[2, 4, 6, 8, 11, 13, 16, 20, 23, 27, 32, 40, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 36893488147419103232) => Some(&[2, 4, 6, 8, 11, 13, 16, 19, 22, 26, 31, 37, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 73786976294838206464) => Some(&[2, 4, 6, 8, 10, 13, 16, 19, 22, 25, 30, 35, 44, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 147573952589676412928) => Some(&[1, 4, 6, 8, 10, 13, 15, 18, 21, 25, 29, 34, 40, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 295147905179352825856) => Some(&[1, 3, 6, 8, 10, 12, 15, 18, 21, 24, 28, 32, 38, 49, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 590295810358705651712) => Some(&[1, 3, 5, 8, 10, 12, 15, 17, 20, 23, 27, 31, 36, 44, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1180591620717411303424) => Some(&[1, 3, 5, 7, 10, 12, 14, 17, 20, 23, 26, 30, 35, 41, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 2361183241434822606848) => Some(&[1, 3, 5, 7, 9, 12, 14, 17, 19, 22, 25, 29, 33, 39, 47, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 4722366482869645213696) => Some(&[1, 3, 5, 7, 9, 11, 14, 16, 19, 22, 25, 28, 32, 37, 43, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 9444732965739290427392) => Some(&[1, 3, 5, 7, 9, 11, 13, 16, 18, 21, 24, 27, 31, 35, 41, 50, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 18889465931478580854784) => Some(&[1, 3, 5, 7, 9, 11, 13, 16, 18, 21, 24, 27, 30, 34, 39, 46, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 37778931862957161709568) => Some(&[1, 3, 5, 7, 9, 11, 13, 15, 18, 20, 23, 26, 29, 33, 37, 43, 54, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 75557863725914323419136) => Some(&[1, 3, 5, 7, 9, 11, 13, 15, 17, 20, 22, 25, 29, 32, 36, 41, 48, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (64, 151115727451828646838272) => Some(&[1, 3, 5, 7, 8, 10, 13, 15, 17, 19, 22, 25, 28, 31, 35, 39, 45, 58, 6_400_000_000_000, 6_400_000_000_000]), + (64, 302231454903657293676544) => Some(&[1, 3, 5, 6, 8, 10, 12, 14, 17, 19, 22, 24, 27, 30, 34, 38, 43, 50, 6_400_000_000_000, 6_400_000_000_000]), + (64, 604462909807314587353088) => Some(&[1, 3, 5, 6, 8, 10, 12, 14, 16, 19, 21, 24, 26, 30, 33, 37, 41, 47, 6_400_000_000_000, 6_400_000_000_000]), + (64, 1208925819614629174706176) => Some(&[1, 3, 5, 6, 8, 10, 12, 14, 16, 18, 21, 23, 26, 29, 32, 36, 40, 45, 52, 6_400_000_000_000]), + (64, 2417851639229258349412352) => Some(&[1, 3, 5, 6, 8, 10, 12, 14, 16, 18, 20, 23, 25, 28, 31, 35, 38, 43, 49, 6_400_000_000_000]), + (64, 4835703278458516698824704) => Some(&[1, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 27, 30, 34, 37, 41, 46, 54]), + (64, 9671406556917033397649408) => Some(&[1, 3, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 27, 30, 33, 36, 40, 44, 50]), + (64, 19342813113834066795298816) => Some(&[1, 3, 4, 6, 8, 9, 11, 13, 15, 17, 19, 21, 24, 26, 29, 32, 35, 39, 43, 48]), + (128, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 67108864) => Some(&[8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 134217728) => Some(&[7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 268435456) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 536870912) => Some(&[6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1073741824) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2147483648) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4294967296) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8589934592) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 17179869184) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 34359738368) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 68719476736) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 137438953472) => Some(&[4, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 274877906944) => Some(&[3, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 549755813888) => Some(&[3, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1099511627776) => Some(&[3, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2199023255552) => Some(&[3, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4398046511104) => Some(&[3, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 8796093022208) => Some(&[3, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 17592186044416) => Some(&[3, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 35184372088832) => Some(&[3, 7, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 70368744177664) => Some(&[3, 6, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 140737488355328) => Some(&[3, 6, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 281474976710656) => Some(&[2, 6, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 562949953421312) => Some(&[2, 6, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1125899906842624) => Some(&[2, 6, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2251799813685248) => Some(&[2, 5, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4503599627370496) => Some(&[2, 5, 9, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9007199254740992) => Some(&[2, 5, 9, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 18014398509481984) => Some(&[2, 5, 9, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 36028797018963968) => Some(&[2, 5, 8, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 72057594037927936) => Some(&[2, 5, 8, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 144115188075855872) => Some(&[2, 5, 8, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 288230376151711744) => Some(&[2, 4, 8, 12, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 576460752303423488) => Some(&[2, 4, 7, 11, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1152921504606846976) => Some(&[2, 4, 7, 11, 16, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2305843009213693952) => Some(&[2, 4, 7, 10, 15, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4611686018427387904) => Some(&[2, 4, 7, 10, 14, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9223372036854775808) => Some(&[2, 4, 7, 10, 14, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 18446744073709551616) => Some(&[2, 4, 6, 10, 13, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 36893488147419103232) => Some(&[2, 4, 6, 9, 13, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 73786976294838206464) => Some(&[2, 4, 6, 9, 12, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 147573952589676412928) => Some(&[2, 4, 6, 9, 12, 17, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 295147905179352825856) => Some(&[1, 4, 6, 9, 12, 16, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 590295810358705651712) => Some(&[1, 4, 6, 8, 11, 15, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1180591620717411303424) => Some(&[1, 3, 6, 8, 11, 15, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2361183241434822606848) => Some(&[1, 3, 6, 8, 11, 14, 19, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4722366482869645213696) => Some(&[1, 3, 5, 8, 11, 14, 18, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9444732965739290427392) => Some(&[1, 3, 5, 8, 10, 13, 17, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 18889465931478580854784) => Some(&[1, 3, 5, 8, 10, 13, 17, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 37778931862957161709568) => Some(&[1, 3, 5, 7, 10, 13, 16, 21, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 75557863725914323419136) => Some(&[1, 3, 5, 7, 10, 12, 16, 20, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 151115727451828646838272) => Some(&[1, 3, 5, 7, 9, 12, 15, 19, 29, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 302231454903657293676544) => Some(&[1, 3, 5, 7, 9, 12, 15, 19, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 604462909807314587353088) => Some(&[1, 3, 5, 7, 9, 12, 15, 18, 23, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 1208925819614629174706176) => Some(&[1, 3, 5, 7, 9, 11, 14, 18, 22, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 2417851639229258349412352) => Some(&[1, 3, 5, 7, 9, 11, 14, 17, 21, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 4835703278458516698824704) => Some(&[1, 3, 5, 7, 9, 11, 13, 17, 20, 27, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 9671406556917033397649408) => Some(&[1, 3, 5, 6, 8, 11, 13, 16, 20, 25, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (128, 19342813113834066795298816) => Some(&[1, 3, 4, 6, 8, 10, 13, 16, 19, 24, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 67108864) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 134217728) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 268435456) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 536870912) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1073741824) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2147483648) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4294967296) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8589934592) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 17179869184) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 34359738368) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 68719476736) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 137438953472) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 274877906944) => Some(&[5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 549755813888) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1099511627776) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2199023255552) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4398046511104) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 8796093022208) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 17592186044416) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 35184372088832) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 70368744177664) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 140737488355328) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 281474976710656) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 562949953421312) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1125899906842624) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2251799813685248) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4503599627370496) => Some(&[2, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9007199254740992) => Some(&[2, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 18014398509481984) => Some(&[2, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 36028797018963968) => Some(&[2, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 72057594037927936) => Some(&[2, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 144115188075855872) => Some(&[2, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 288230376151711744) => Some(&[2, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 576460752303423488) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1152921504606846976) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2305843009213693952) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4611686018427387904) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9223372036854775808) => Some(&[2, 5, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 18446744073709551616) => Some(&[2, 5, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 36893488147419103232) => Some(&[2, 4, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 73786976294838206464) => Some(&[2, 4, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 147573952589676412928) => Some(&[2, 4, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 295147905179352825856) => Some(&[2, 4, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 590295810358705651712) => Some(&[2, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1180591620717411303424) => Some(&[1, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2361183241434822606848) => Some(&[1, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4722366482869645213696) => Some(&[1, 4, 7, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9444732965739290427392) => Some(&[1, 4, 6, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 18889465931478580854784) => Some(&[1, 4, 6, 11, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 37778931862957161709568) => Some(&[1, 3, 6, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 75557863725914323419136) => Some(&[1, 3, 6, 10, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 151115727451828646838272) => Some(&[1, 3, 6, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 302231454903657293676544) => Some(&[1, 3, 6, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 604462909807314587353088) => Some(&[1, 3, 6, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 1208925819614629174706176) => Some(&[1, 3, 5, 9, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 2417851639229258349412352) => Some(&[1, 3, 5, 8, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 4835703278458516698824704) => Some(&[1, 3, 5, 8, 13, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 9671406556917033397649408) => Some(&[1, 3, 5, 8, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (256, 19342813113834066795298816) => Some(&[1, 3, 5, 8, 12, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 32) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 64) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 128) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 256) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 512) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1024) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2048) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4096) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8192) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16384) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 32768) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 65536) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 131072) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 262144) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 524288) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1048576) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2097152) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4194304) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8388608) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 16777216) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 33554432) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 67108864) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 134217728) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 268435456) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 536870912) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1073741824) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2147483648) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4294967296) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8589934592) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 17179869184) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 34359738368) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 68719476736) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 137438953472) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 274877906944) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 549755813888) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1099511627776) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2199023255552) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4398046511104) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 8796093022208) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 17592186044416) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 35184372088832) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 70368744177664) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 140737488355328) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 281474976710656) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 562949953421312) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1125899906842624) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2251799813685248) => Some(&[6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4503599627370496) => Some(&[4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9007199254740992) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 18014398509481984) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 36028797018963968) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 72057594037927936) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 144115188075855872) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 288230376151711744) => Some(&[3, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 576460752303423488) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1152921504606846976) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2305843009213693952) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4611686018427387904) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9223372036854775808) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 18446744073709551616) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 36893488147419103232) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 73786976294838206464) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 147573952589676412928) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 295147905179352825856) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 590295810358705651712) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1180591620717411303424) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2361183241434822606848) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4722366482869645213696) => Some(&[2, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9444732965739290427392) => Some(&[2, 6, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 18889465931478580854784) => Some(&[2, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 37778931862957161709568) => Some(&[1, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 75557863725914323419136) => Some(&[1, 5, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 151115727451828646838272) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 302231454903657293676544) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 604462909807314587353088) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 1208925819614629174706176) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 2417851639229258349412352) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 4835703278458516698824704) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 9671406556917033397649408) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + (512, 19342813113834066795298816) => Some(&[1, 4, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000, 6_400_000_000_000]), + _ => None, + } +} diff --git a/crates/akita-types/src/sis/honest_fold_policy.rs b/crates/akita-types/src/sis/honest_fold_policy.rs index f00ab2c2a..e08662179 100644 --- a/crates/akita-types/src/sis/honest_fold_policy.rs +++ b/crates/akita-types/src/sis/honest_fold_policy.rs @@ -143,10 +143,14 @@ impl HonestFoldPolicy for BalancedSignedDigitFoldPolicy { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct UnitOneHotFoldPolicy { field_bits: u32, + source_chunk_size: usize, snap: DigitSnapCalibration, legacy_fallback: BalancedSignedDigitFoldPolicy, } +/// Canonical logical chunk size of the shipping unit one-hot representation. +pub const DEFAULT_UNIT_ONEHOT_SOURCE_CHUNK_SIZE: usize = 256; + impl UnitOneHotFoldPolicy { /// Construct the shipping no-snap policy with its historical dominance /// guard. Configurations call this only after establishing the unit @@ -158,6 +162,7 @@ impl UnitOneHotFoldPolicy { ) -> Self { Self { field_bits, + source_chunk_size: DEFAULT_UNIT_ONEHOT_SOURCE_CHUNK_SIZE, snap: DigitSnapCalibration::NONE, legacy_fallback: BalancedSignedDigitFoldPolicy::preserving_existing_behavior( field_bits, @@ -177,6 +182,7 @@ impl UnitOneHotFoldPolicy { legacy_witness.validate()?; Ok(Self { field_bits, + source_chunk_size: DEFAULT_UNIT_ONEHOT_SOURCE_CHUNK_SIZE, snap, legacy_fallback: BalancedSignedDigitFoldPolicy::preserving_existing_behavior( field_bits, @@ -185,6 +191,23 @@ impl UnitOneHotFoldPolicy { }) } + /// Number of logical coefficients represented by one unit entry. + #[must_use] + pub const fn source_chunk_size(self) -> usize { + self.source_chunk_size + } + + /// Replace the source chunk size while retaining the same fold sizing rule. + pub fn with_source_chunk_size(mut self, source_chunk_size: usize) -> Result { + if source_chunk_size == 0 { + return Err(AkitaError::InvalidSetup( + "unit one-hot source chunk size must be nonzero".into(), + )); + } + self.source_chunk_size = source_chunk_size; + Ok(self) + } + fn exact_threshold(&self, query: HonestFoldSizingQuery<'_>) -> Option { let cfg = query.challenge_config; if cfg.weight() > query.ring_dimension || query.ring_dimension == 0 { diff --git a/crates/akita-types/src/sis/l2_table.rs b/crates/akita-types/src/sis/l2_table.rs new file mode 100644 index 000000000..74447fc89 --- /dev/null +++ b/crates/akita-types/src/sis/l2_table.rs @@ -0,0 +1,101 @@ +//! Generated Euclidean SIS table lookup for complete physical L2 collisions. + +use super::ajtai_key::{SisModulusProfileId, SisSecurityPolicyId, DEFAULT_SIS_SECURITY_POLICY}; +use super::generated_l2_sis_table::{sis_max_widths as generated_l2_sis_max_widths, TABLE_DIGEST}; + +/// Digest of the separate generated Euclidean SIS table and its boundary +/// evidence. +/// +/// This identity is distinct from [`super::ajtai_key::SisTableDigest`]. An L2-selected schedule +/// binds both its squared collision bucket and this digest without changing the +/// coefficient-L∞ fallback table identity. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct SisL2TableDigest(pub [u8; 32]); + +impl Default for SisL2TableDigest { + fn default() -> Self { + Self::CURRENT + } +} + +impl SisL2TableDigest { + /// Stable wire tag for the L2 digest field. + pub const TAG: u8 = 1; + + /// SHA-256 digest of the audit CSV emitted while generating the current L2 table. + pub const CURRENT: Self = Self(TABLE_DIGEST); +} + +/// Canonical key for one generated Euclidean SIS floor row. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct SisL2TableKey { + pub policy: SisSecurityPolicyId, + pub table_digest: SisL2TableDigest, + pub modulus_profile: SisModulusProfileId, + pub ring_dimension: u32, + /// Rounded squared L2 norm of the complete scalar collision vector. + pub collision_l2_sq: u128, +} + +const MIN_COLLISION_SQ_BUCKET: u128 = 1u128 << 1; +const MAX_COLLISION_SQ_BUCKET: u128 = 1u128 << 84; + +/// Round a complete scalar collision-vector squared L2 norm to the generated +/// ADPS16 quantum table ladder. +#[must_use] +pub fn ceil_supported_l2_collision_sq(collision_l2_sq: u128) -> Option { + if collision_l2_sq == 0 { + return None; + } + let bucket = collision_l2_sq + .checked_next_power_of_two()? + .max(MIN_COLLISION_SQ_BUCKET); + (bucket <= MAX_COLLISION_SQ_BUCKET).then_some(bucket) +} + +/// Canonical generated-table key for a raw complete squared L2 collision norm. +/// +/// Returns `None` for an unsupported policy, digest, family, dimension, or +/// collision bucket. +#[must_use] +pub fn sis_l2_table_key_for_collision_sq( + policy: SisSecurityPolicyId, + table_digest: SisL2TableDigest, + modulus_profile: SisModulusProfileId, + ring_dimension: u32, + collision_l2_sq: u128, +) -> Option { + if policy != DEFAULT_SIS_SECURITY_POLICY || table_digest != SisL2TableDigest::CURRENT { + return None; + } + let collision_l2_sq = ceil_supported_l2_collision_sq(collision_l2_sq)?; + generated_l2_sis_max_widths(modulus_profile, ring_dimension, collision_l2_sq)?; + Some(SisL2TableKey { + policy, + table_digest, + modulus_profile, + ring_dimension, + collision_l2_sq, + }) +} + +/// Minimum module rank under the generated 128-bit quantum ADPS16 Euclidean +/// SIS model. +/// +/// `key.collision_l2_sq` is the squared norm of the complete scalar collision +/// vector, not a per-ring-row bound. +#[must_use] +pub fn min_secure_l2_rank(key: SisL2TableKey, width: u64) -> Option { + if width == 0 + || key.policy != DEFAULT_SIS_SECURITY_POLICY + || key.table_digest != SisL2TableDigest::CURRENT + { + return None; + } + let widths = + generated_l2_sis_max_widths(key.modulus_profile, key.ring_dimension, key.collision_l2_sq)?; + widths + .iter() + .position(|&max_width| width <= max_width) + .map(|index| index + 1) +} diff --git a/crates/akita-types/src/sis/mod.rs b/crates/akita-types/src/sis/mod.rs index 48e4c5304..1b1130173 100644 --- a/crates/akita-types/src/sis/mod.rs +++ b/crates/akita-types/src/sis/mod.rs @@ -12,7 +12,7 @@ //! num_positions_per_block, decomposition_digits::num_digits_inner(decomp, is_root))?; //! let norm_s = norm_bound::rounded_up_role_a_inf_norm( //! policy, table_digest, family, d, log_basis_response, &stage1, shape, -//! exact_fold_digit_depth, ring_subfield_norm_bound)?; +//! exact_fold_digit_depth)?; //! let n_a = ajtai_key::min_secure_rank( //! SisTableKey { policy, family, ring_dimension: d as u32, coeff_linf_bound: norm_s }, //! width_s as u64)?; @@ -27,9 +27,12 @@ pub mod compression; mod coverage; pub mod decomposition_digits; pub mod fold_linf_cap; +mod generated_l2_sis_table; mod generated_sis_table; pub mod honest_fold_policy; +mod l2_table; pub mod norm_bound; +mod physical_l2; pub use ajtai_key::{ ceil_coeff_linf_bucket, ceil_supported_linf_bound, min_secure_rank, @@ -50,13 +53,16 @@ pub use decomposition_digits::{ }; pub use honest_fold_policy::{ BalancedSignedDigitFoldPolicy, DigitSnapCalibration, HonestFoldPolicy, HonestFoldPolicySpec, - HonestFoldSizingQuery, UnitOneHotFoldPolicy, + HonestFoldSizingQuery, UnitOneHotFoldPolicy, DEFAULT_UNIT_ONEHOT_SOURCE_CHUNK_SIZE, +}; +pub use l2_table::{ + ceil_supported_l2_collision_sq, min_secure_l2_rank, sis_l2_table_key_for_collision_sq, + SisL2TableDigest, SisL2TableKey, }; -#[cfg(test)] -pub(crate) use norm_bound::{fold_witness_beta_inf, fold_witness_digit_plan}; pub use norm_bound::{ - fold_witness_unsnapped_linf_cap, max_response_linf_for_role_a_collision, - rademacher_proxy_variance, role_a_collision_inf_norm_for_response_bound, + checked_centered_l2_sq, fold_witness_unsnapped_linf_cap, + max_response_linf_for_role_a_collision, rademacher_proxy_variance, + role_a_collision_inf_norm_for_response_bound, role_a_collision_l2_sq_for_response_bound, rounded_up_collision_inf_norm, rounded_up_role_a_inf_norm, weak_binding_inf_norm, FoldChallengeNorms, FoldWitnessLinfCapConfig, FoldWitnessNorms, FOLD_LINF_FP32_SNAP_MIN_TSTAR_RETAIN_DEN, FOLD_LINF_FP32_SNAP_MIN_TSTAR_RETAIN_NUM, @@ -64,3 +70,6 @@ pub use norm_bound::{ FOLD_LINF_SNAP_MIN_TSTAR_RETAIN_DEN, FOLD_LINF_SNAP_MIN_TSTAR_RETAIN_NUM, MAX_FOLD_GRIND_ATTEMPTS, }; +#[cfg(test)] +pub(crate) use norm_bound::{fold_witness_beta_inf, fold_witness_digit_plan}; +pub use physical_l2::{InnerCommitSecurityRoute, LimbGramLayout, PhysicalL2NormProofShape}; diff --git a/crates/akita-types/src/sis/norm_bound.rs b/crates/akita-types/src/sis/norm_bound.rs index 8601305fb..189b021b7 100644 --- a/crates/akita-types/src/sis/norm_bound.rs +++ b/crates/akita-types/src/sis/norm_bound.rs @@ -45,16 +45,15 @@ pub fn rounded_up_collision_inf_norm( ) } -/// Weak-binding lemma `L∞` norm bound: -/// `2 * challenge_l1_norm * ring_subfield_norm_bound * z_inf_norm`. -pub fn weak_binding_inf_norm( - challenge_l1_norm: u128, - ring_subfield_norm_bound: u32, - z_inf_norm: u128, -) -> Option { +/// Weak-binding lemma physical coefficient-`L∞` norm bound: +/// `2 * challenge_l1_norm * z_inf_norm`. +/// +/// Both inputs are physical ring coefficient vectors at this boundary. A +/// logical extension-field to physical-ring embedding factor therefore does +/// not belong in this formula. +pub fn weak_binding_inf_norm(challenge_l1_norm: u128, z_inf_norm: u128) -> Option { 2u128 .checked_mul(challenge_l1_norm)? - .checked_mul(u128::from(ring_subfield_norm_bound))? .checked_mul(z_inf_norm) } @@ -66,16 +65,47 @@ pub fn weak_binding_inf_norm( /// of two. pub fn role_a_collision_inf_norm_for_response_bound( challenge_l1_norm: u128, - ring_subfield_norm_bound: u32, response_linf_bound: u128, ) -> Option { weak_binding_inf_norm( challenge_l1_norm.checked_mul(2)?, - ring_subfield_norm_bound, response_linf_bound.checked_mul(2)?, ) } +/// Complete physical squared-`L2` A-role collision bound for two accepted +/// folded responses. +/// +/// If each response has squared norm at most `response_l2_sq_bound`, the same +/// extraction factors as [`role_a_collision_inf_norm_for_response_bound`] +/// bound the collision length by `8 * challenge_operator_bound * ||z||_2`. +/// The challenge bound is either its deterministic L1 norm or a +/// verifier-enforced multiplication-operator threshold. Squaring that scale +/// gives `64 * challenge_operator_bound^2 * response_l2_sq_bound`. +/// +/// The response bound covers the complete physical coefficient vector across +/// every A-matrix input row. No embedding or matrix-width factor is applied. +#[must_use] +pub fn role_a_collision_l2_sq_for_response_bound( + challenge_operator_bound: u128, + response_l2_sq_bound: u128, +) -> Option { + 64u128 + .checked_mul(challenge_operator_bound.checked_mul(challenge_operator_bound)?)? + .checked_mul(response_l2_sq_bound) +} + +/// Checked squared Euclidean norm of centered physical coefficients. +#[must_use] +pub fn checked_centered_l2_sq>(values: &[T]) -> Option { + values.iter().try_fold(0u128, |sum, &value| { + let magnitude = u128::from(value.into().unsigned_abs()); + magnitude + .checked_mul(magnitude) + .and_then(|square| sum.checked_add(square)) + }) +} + /// Largest raw folded-response `L∞` bound fitting an A-role collision bucket. /// /// This is the exact integer inverse of @@ -83,13 +113,8 @@ pub fn role_a_collision_inf_norm_for_response_bound( pub fn max_response_linf_for_role_a_collision( collision_linf_capacity: u128, challenge_l1_norm: u128, - ring_subfield_norm_bound: u32, ) -> Option { - let price_per_unit = role_a_collision_inf_norm_for_response_bound( - challenge_l1_norm, - ring_subfield_norm_bound, - 1, - )?; + let price_per_unit = role_a_collision_inf_norm_for_response_bound(challenge_l1_norm, 1)?; collision_linf_capacity.checked_div(price_per_unit) } @@ -118,7 +143,6 @@ pub fn rounded_up_role_a_inf_norm( log_basis_response: u32, fold_challenge_config: &SparseChallengeConfig, fold_decomposed_digits: usize, - ring_subfield_norm_bound: u32, ) -> Option { let challenge = FoldChallengeNorms::new(fold_challenge_config); if log_basis_response == 0 || fold_decomposed_digits == 0 { @@ -126,11 +150,8 @@ pub fn rounded_up_role_a_inf_norm( } let recomposed_inf_norm_bound = balanced_digit_abs_max(log_basis_response, fold_decomposed_digits); - let collision_linf = weak_binding_inf_norm( - 2u128.checked_mul(challenge.l1_norm)?, - ring_subfield_norm_bound, - 2u128.checked_mul(recomposed_inf_norm_bound)?, - )?; + let collision_linf = + role_a_collision_inf_norm_for_response_bound(challenge.l1_norm, recomposed_inf_norm_bound)?; ceil_supported_linf_bound( policy, table_digest, @@ -355,31 +376,29 @@ mod tests { use super::*; #[test] - fn raw_terminal_response_bound_uses_the_complete_difference_interval() { + fn physical_response_bound_uses_the_complete_difference_interval() { let challenge_l1 = 41; - let subfield_norm = 2; let response_bound = 7; - let price = role_a_collision_inf_norm_for_response_bound( - challenge_l1, - subfield_norm, - response_bound, - ) - .expect("collision price"); - assert_eq!( - price, - 8 * challenge_l1 * u128::from(subfield_norm) * response_bound - ); + let price = role_a_collision_inf_norm_for_response_bound(challenge_l1, response_bound) + .expect("collision price"); + assert_eq!(price, 8 * challenge_l1 * response_bound); let unit_price = price / response_bound; assert_eq!( - max_response_linf_for_role_a_collision( - price + unit_price - 1, - challenge_l1, - subfield_norm, - ), + max_response_linf_for_role_a_collision(price + unit_price - 1, challenge_l1,), Some(response_bound) ); } + #[test] + fn l2_collision_scales_the_complete_physical_norm_once() { + let challenge_l1 = 51u128; + let response_l2_sq = 1u128 << 32; + assert_eq!( + role_a_collision_l2_sq_for_response_bound(challenge_l1, response_l2_sq), + Some(64 * challenge_l1 * challenge_l1 * response_l2_sq), + ); + } + #[test] fn fold_witness_digit_plan_beta_picks_min_ring_product_side() { let beta = |c_inf, c_l1, s_inf, s_l1| { @@ -464,8 +483,7 @@ mod tests { log_commit_bound: 1, log_open_bound: Some(128), }; - let (d, num_live_blocks, num_claims, subfield, inner_width) = - (64usize, 2usize, 1usize, 1u32, 2u64); + let (d, num_live_blocks, num_claims, inner_width) = (64usize, 2usize, 1usize, 2u64); // Recompute the Lemma-7 envelope from the same primitives the function wires. let challenge = FoldChallengeNorms::new(&fold_challenge_config); @@ -486,7 +504,7 @@ mod tests { ) .unwrap(); let z_bound = balanced_digit_abs_max(decomposition.log_basis, delta_fold); - // Weak-binding collision `8 · ω · z` for `subfield = 1`. + // Physical weak-binding collision `8 · ω · z`. let collision_linf = 8u128 * challenge.l1_norm * z_bound; let envelope = ceil_supported_linf_bound( DEFAULT_SIS_SECURITY_POLICY, @@ -506,7 +524,6 @@ mod tests { decomposition.log_basis, &fold_challenge_config, delta_fold, - subfield, ) .unwrap(), envelope, @@ -532,8 +549,7 @@ mod tests { log_commit_bound: 1, log_open_bound: Some(128), }; - let (d, num_live_blocks, num_claims, subfield, inner_width) = - (64usize, 4usize, 1usize, 1u32, 2u64); + let (d, num_live_blocks, num_claims, inner_width) = (64usize, 4usize, 1usize, 2u64); let challenge = FoldChallengeNorms::new(&fold_challenge_config); let witness = FoldWitnessNorms::sparse_binary(d, 64).unwrap(); @@ -565,7 +581,6 @@ mod tests { decomposition.log_basis, &fold_challenge_config, delta_fold, - subfield, ) .unwrap(); let cap_priced = ceil_supported_linf_bound( @@ -654,8 +669,7 @@ mod tests { log_commit_bound: 128, log_open_bound: None, }; - let (d, num_live_blocks, num_claims, subfield, inner_width) = - (64usize, 2usize, 1usize, 1u32, 2u64); + let (d, num_live_blocks, num_claims, inner_width) = (64usize, 2usize, 1usize, 2u64); let challenge = FoldChallengeNorms::new(&fold_challenge_config); let witness = FoldWitnessNorms::bounded(decomposition.log_basis, d); @@ -683,7 +697,6 @@ mod tests { decomposition.log_basis, &fold_challenge_config, delta_fold, - subfield, ) .unwrap(); assert_eq!( diff --git a/crates/akita-types/src/sis/physical_l2.rs b/crates/akita-types/src/sis/physical_l2.rs new file mode 100644 index 000000000..06d87e5df --- /dev/null +++ b/crates/akita-types/src/sis/physical_l2.rs @@ -0,0 +1,430 @@ +//! Schedule-owned physical L2 proof geometry. + +use std::ops::Range; + +/// Canonical work cap for one small-field limb inner-product subclaim. +/// +/// The integer no-wrap limit can be much larger than a practical sumcheck +/// block. Keeping blocks at 4 Ki coefficients makes the proof geometry and +/// verifier work bounded while remaining comfortably below every derived +/// field-specific no-wrap ceiling. +const MAX_LIMB_GRAM_BLOCK_LEN: usize = 1 << 12; + +use akita_field::AkitaError; + +use super::ajtai_key::{SisModulusProfileId, SisSecurityPolicyId, SisTableKey}; +use super::l2_table::SisL2TableKey; +use crate::descriptor_bytes::push_usize; + +/// Checked block and upper-triangular limb-pair layout for a LimbGram proof. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct LimbGramLayout { + physical_response_len: usize, + block_len: usize, + limb_count: usize, + block_count: usize, + pair_count: usize, +} + +impl LimbGramLayout { + /// Build a checked layout from explicit public shape values. + pub fn new( + physical_response_len: usize, + block_len: usize, + limb_count: usize, + ) -> Result { + if physical_response_len == 0 + || block_len == 0 + || limb_count == 0 + || block_len > physical_response_len + { + return Err(AkitaError::InvalidSetup( + "L2 limb-Gram shape has invalid response, block, or limb count".into(), + )); + } + let block_count = physical_response_len.div_ceil(block_len); + let pair_count = + limb_count + .checked_mul(limb_count.checked_add(1).ok_or_else(|| { + AkitaError::InvalidSetup("L2 limb-pair count overflow".into()) + })?) + .and_then(|count| count.checked_div(2)) + .ok_or_else(|| AkitaError::InvalidSetup("L2 limb-pair count overflow".into()))?; + block_count.checked_mul(pair_count).ok_or_else(|| { + AkitaError::InvalidSetup("L2 limb-Gram subclaim count overflow".into()) + })?; + Ok(Self { + physical_response_len, + block_len, + limb_count, + block_count, + pair_count, + }) + } + + #[must_use] + pub const fn physical_response_len(self) -> usize { + self.physical_response_len + } + + #[must_use] + pub const fn block_len(self) -> usize { + self.block_len + } + + #[must_use] + pub const fn limb_count(self) -> usize { + self.limb_count + } + + #[must_use] + pub const fn block_count(self) -> usize { + self.block_count + } + + #[must_use] + pub const fn pair_count(self) -> usize { + self.pair_count + } + + #[must_use] + pub fn subclaim_count(self) -> usize { + self.block_count * self.pair_count + } + + /// Consecutive response ranges, including the final short block. + pub fn block_ranges(self) -> impl ExactSizeIterator> { + (0..self.block_count).map(move |block_index| { + let start = block_index * self.block_len; + let end = start + .saturating_add(self.block_len) + .min(self.physical_response_len); + start..end + }) + } + + /// Canonical upper-triangular limb-pair order. + pub fn limb_pairs(self) -> impl Iterator + Clone { + (0..self.limb_count) + .flat_map(move |left| (left..self.limb_count).map(move |right| (left, right))) + } + + /// Canonical flat subclaim index for one block and limb pair. + pub fn subclaim_index( + self, + block_index: usize, + left_limb: usize, + right_limb: usize, + ) -> Option { + if block_index >= self.block_count + || left_limb > right_limb + || right_limb >= self.limb_count + { + return None; + } + let preceding_rows = left_limb + .checked_mul(self.limb_count)? + .checked_sub(left_limb.checked_mul(left_limb.saturating_sub(1))? / 2)?; + let pair_index = preceding_rows.checked_add(right_limb.checked_sub(left_limb)?)?; + block_index + .checked_mul(self.pair_count)? + .checked_add(pair_index) + } +} + +/// Schedule-owned shape of the integer norm proof for one L2-selected A +/// matrix. +/// +/// The proof serializes no block or limb-pair identifiers. This shape and +/// [`LimbGramLayout`] derive their complete canonical order. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum PhysicalL2NormProofShape { + /// One direct square-sum claim over every physical response coefficient. + Direct { physical_response_len: usize }, + /// Blockwise balanced-limb Gram claims used when the direct integer sum + /// could wrap the base field. + LimbGram { + physical_response_len: usize, + block_len: usize, + limb_count: usize, + }, +} + +/// The single selected security route for an A commitment matrix. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum InnerCommitSecurityRoute { + /// Existing coefficient-L-infinity sizing and digit-range proof. + Linf(SisTableKey), + /// Complete physical L2 sizing with the scheduled integer norm proof. + L2 { + table_key: SisL2TableKey, + response_l2_sq_cap: u128, + norm_proof_shape: PhysicalL2NormProofShape, + }, +} + +impl InnerCommitSecurityRoute { + #[must_use] + pub const fn modulus_profile(self) -> SisModulusProfileId { + match self { + Self::Linf(key) => key.modulus_profile, + Self::L2 { table_key, .. } => table_key.modulus_profile, + } + } + + #[must_use] + pub const fn policy(self) -> SisSecurityPolicyId { + match self { + Self::Linf(key) => key.policy, + Self::L2 { table_key, .. } => table_key.policy, + } + } + + #[must_use] + pub const fn ring_dimension(self) -> u32 { + match self { + Self::Linf(key) => key.ring_dimension, + Self::L2 { table_key, .. } => table_key.ring_dimension, + } + } +} + +impl PhysicalL2NormProofShape { + /// Derive the canonical no-wrap proof shape for one physical response + /// domain and its existing balanced digit decomposition. + pub fn derive( + modulus_profile: SisModulusProfileId, + physical_response_len: usize, + fold_basis: usize, + fold_digit_count: usize, + ) -> Result { + if physical_response_len == 0 + || fold_digit_count == 0 + || fold_basis < 2 + || !fold_basis.is_power_of_two() + { + return Err(AkitaError::InvalidSetup( + "L2 norm shape requires a nonempty response and balanced power-of-two digits" + .into(), + )); + } + let direct = Self::Direct { + physical_response_len, + }; + if direct + .validate_integer_soundness(modulus_profile, fold_basis, fold_digit_count) + .is_ok() + { + return Ok(direct); + } + let modulus = modulus_profile.modulus(); + let digit_abs = (fold_basis / 2) as u128; + if modulus > i128::MAX as u128 { + return Err(AkitaError::InvalidSetup( + "L2 response is too wide for direct proof and its modulus has no centered-limb path" + .into(), + )); + } + let digit_square = digit_abs + .checked_mul(digit_abs) + .ok_or_else(|| AkitaError::InvalidSetup("L2 limb digit square overflow".into()))?; + let max_block = modulus + .checked_div(2) + .and_then(|half| half.checked_sub(1)) + .and_then(|limit| limit.checked_div(digit_square)) + .ok_or_else(|| { + AkitaError::InvalidSetup("L2 limb alphabet cannot fit a centered block".into()) + })?; + let shape = Self::LimbGram { + physical_response_len, + block_len: usize::try_from(max_block) + .unwrap_or(usize::MAX) + .min(MAX_LIMB_GRAM_BLOCK_LEN) + .min(physical_response_len), + limb_count: fold_digit_count, + }; + shape.validate_integer_soundness(modulus_profile, fold_basis, fold_digit_count)?; + Ok(shape) + } + + /// Validate that the shape rules out field wraparound using public bounds. + pub fn validate_integer_soundness( + self, + modulus_profile: SisModulusProfileId, + fold_basis: usize, + fold_digit_count: usize, + ) -> Result<(), AkitaError> { + self.validate()?; + if fold_digit_count == 0 || fold_basis < 2 || !fold_basis.is_power_of_two() { + return Err(AkitaError::InvalidSetup( + "L2 norm shape has an invalid balanced digit decomposition".into(), + )); + } + let modulus = modulus_profile.modulus(); + let digit_abs = (fold_basis / 2) as u128; + match self { + Self::Direct { + physical_response_len, + } => { + let mut max_response = 0u128; + let mut power = 1u128; + for _ in 0..fold_digit_count { + max_response = max_response + .checked_add(digit_abs.checked_mul(power).ok_or_else(|| { + AkitaError::InvalidSetup("direct norm response bound overflow".into()) + })?) + .ok_or_else(|| { + AkitaError::InvalidSetup("direct norm response bound overflow".into()) + })?; + power = power.checked_mul(fold_basis as u128).ok_or_else(|| { + AkitaError::InvalidSetup("direct norm basis power overflow".into()) + })?; + } + let worst = (physical_response_len as u128) + .checked_mul(max_response.checked_mul(max_response).ok_or_else(|| { + AkitaError::InvalidSetup("direct norm worst-case overflow".into()) + })?) + .ok_or_else(|| { + AkitaError::InvalidSetup("direct norm worst-case overflow".into()) + })?; + if worst >= modulus { + return Err(AkitaError::InvalidSetup( + "direct norm shape does not rule out field wraparound".into(), + )); + } + } + Self::LimbGram { + block_len, + limb_count, + .. + } => { + if limb_count != fold_digit_count || modulus > i128::MAX as u128 { + return Err(AkitaError::InvalidSetup( + "L2 limb-Gram shape disagrees with its field or digit count".into(), + )); + } + let claim_abs_bound = + (block_len as u128) + .checked_mul(digit_abs.checked_mul(digit_abs).ok_or_else(|| { + AkitaError::InvalidSetup("L2 limb bound overflow".into()) + })?) + .ok_or_else(|| AkitaError::InvalidSetup("L2 limb bound overflow".into()))?; + if claim_abs_bound >= modulus / 2 { + return Err(AkitaError::InvalidSetup( + "L2 limb block does not rule out centered-lift ambiguity".into(), + )); + } + } + } + Ok(()) + } + + /// Validate nonzero, bounded arithmetic for the schedule-derived shape. + pub fn validate(self) -> Result<(), AkitaError> { + if self.physical_response_len() == 0 { + return Err(AkitaError::InvalidSetup( + "L2 norm proof requires a nonempty physical response".into(), + )); + } + if let Self::LimbGram { + physical_response_len, + block_len, + limb_count, + } = self + { + LimbGramLayout::new(physical_response_len, block_len, limb_count)?; + } + Ok(()) + } + + #[must_use] + pub const fn physical_response_len(self) -> usize { + match self { + Self::Direct { + physical_response_len, + } + | Self::LimbGram { + physical_response_len, + .. + } => physical_response_len, + } + } + + /// Checked LimbGram layout, or `None` for the direct shape. + pub fn limb_gram_layout(self) -> Result, AkitaError> { + match self { + Self::Direct { .. } => Ok(None), + Self::LimbGram { + physical_response_len, + block_len, + limb_count, + } => LimbGramLayout::new(physical_response_len, block_len, limb_count).map(Some), + } + } + + #[must_use] + pub fn subclaim_count(self) -> Option { + match self.limb_gram_layout().ok()? { + None => Some(usize::default()), + Some(layout) => Some(layout.subclaim_count()), + } + } + + #[must_use] + pub const fn virtual_evaluation_count(self) -> usize { + match self { + Self::Direct { .. } => 1, + Self::LimbGram { limb_count, .. } => limb_count, + } + } + + pub(crate) fn append_descriptor_bytes(self, bytes: &mut Vec) { + match self { + Self::Direct { + physical_response_len, + } => { + bytes.push(1); + push_usize(bytes, physical_response_len); + } + Self::LimbGram { + physical_response_len, + block_len, + limb_count, + } => { + bytes.push(2); + push_usize(bytes, physical_response_len); + push_usize(bytes, block_len); + push_usize(bytes, limb_count); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn limb_gram_layout_owns_block_and_pair_order() { + let layout = LimbGramLayout::new(10, 4, 3).expect("layout"); + assert_eq!( + layout.block_ranges().collect::>(), + vec![0..4, 4..8, 8..10] + ); + assert_eq!( + layout.limb_pairs().collect::>(), + vec![(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)] + ); + for block in 0..layout.block_count() { + for (pair, (left, right)) in layout.limb_pairs().enumerate() { + assert_eq!( + layout.subclaim_index(block, left, right), + Some(block * layout.pair_count() + pair) + ); + } + } + assert_eq!(layout.subclaim_count(), 18); + assert_eq!(layout.subclaim_index(0, 2, 1), None); + assert_eq!(layout.subclaim_index(3, 0, 0), None); + } +} diff --git a/crates/akita-types/src/witness.rs b/crates/akita-types/src/witness.rs index 54ae39414..1e12d3299 100644 --- a/crates/akita-types/src/witness.rs +++ b/crates/akita-types/src/witness.rs @@ -648,9 +648,23 @@ impl WitnessLayout { h_quotient_row, }); } + // Extension-field tensor packing carries a grouped root witness into + // the successor A ring. Mixed native group dimensions can leave the + // relation suffix aligned only to the smaller common block, so make + // the declared logical witness include the zero padding that packing + // would otherwise add implicitly. + let successor_a_alignment = if num_groups > 1 { + group_geometry + .iter() + .map(|(_, _, role_dims, _, _)| role_dims.d_a()) + .max() + .ok_or_else(|| AkitaError::InvalidSetup("witness groups are empty".into()))? + } else { + relation_coefficient_block + }; let aligned_witness_end = checked_align_up( cursor, - relation_coefficient_block, + successor_a_alignment, "compression witness suffix alignment overflow", )?; if aligned_witness_end != cursor { diff --git a/crates/akita-verifier/Cargo.toml b/crates/akita-verifier/Cargo.toml index 066f4ef74..3e98e1b76 100644 --- a/crates/akita-verifier/Cargo.toml +++ b/crates/akita-verifier/Cargo.toml @@ -40,6 +40,7 @@ parallel = [ workspace = true [dev-dependencies] +akita-prover = { version = "0.1.0", path = "../akita-prover", default-features = false } akita-config = { version = "0.1.0", path = "../akita-config", default-features = false, features = [ "test-support", "schedules-fp128-dense", diff --git a/crates/akita-verifier/src/protocol/core.rs b/crates/akita-verifier/src/protocol/core.rs index 9e2fd681d..e733d7f38 100644 --- a/crates/akita-verifier/src/protocol/core.rs +++ b/crates/akita-verifier/src/protocol/core.rs @@ -12,7 +12,7 @@ use crate::protocol::ring_switch::{ }; use crate::stages::stage1::{derive_multi_group_stage1_challenges, AkitaStage1Verifier}; use crate::stages::stage2::AkitaStage2Verifier; -use crate::stages::SetupSumcheckVerifier; +use crate::stages::{verify_physical_l2_norm, PhysicalL2RangeClaim, SetupSumcheckVerifier}; use akita_challenges::{FoldDraw, LiveFoldDraw}; use akita_field::{ AkitaError, CanonicalField, ExtField, FieldCore, FrobeniusExtField, FromPrimitiveInt, @@ -36,9 +36,10 @@ use akita_types::{ ring_subfield_packed_extension_opening_point, root_tensor_projection_enabled, tensor_equality_factor_eval_at_point, AkitaStage1Proof, AkitaStage2Proof, AkitaVerifierSetup, BasisMode, CommittedGroupParams, EvaluationTraceInputs, ExtensionOpeningReductionProof, - FoldLevelProof, FoldSchedule, FpExtEncoding, OpeningClaims, OpeningClaimsLayout, - PolynomialGroupClaims, PreparedOpeningPoint, RecursiveFoldParams, RingRelationInstance, - RingVec, SetupContributionMode, SetupSumcheckProof, TerminalFoldParams, TerminalLevelProof, + FoldLevelProof, FoldSchedule, FpExtEncoding, InnerCommitSecurityRoute, OpeningClaims, + OpeningClaimsLayout, PhysicalResponsePlan, PolynomialGroupClaims, PreparedOpeningPoint, + RecursiveFoldParams, RelationRangeImagePlan, RingRelationInstance, RingVec, + SetupContributionMode, SetupSumcheckProof, TerminalFoldParams, TerminalLevelProof, TerminalResponse, TerminalWitnessTranscriptParts, }; use akita_types::{ diff --git a/crates/akita-verifier/src/protocol/core/fold/mod.rs b/crates/akita-verifier/src/protocol/core/fold/mod.rs index 1e9a5ca70..d51d86ddf 100644 --- a/crates/akita-verifier/src/protocol/core/fold/mod.rs +++ b/crates/akita-verifier/src/protocol/core/fold/mod.rs @@ -4,6 +4,7 @@ mod extension_claim; mod single_field; use super::*; +use akita_algebra::offset_eq::EqPairTensorFamily; use akita_types::{dispatch_for_field, DigitRangeEqualityPoint, DigitRangePlan}; pub(in crate::protocol::core) use extension_claim::{ @@ -65,16 +66,20 @@ struct Stage1Replay { binary_batching: Option, range_image_evaluation: E, stage1_point: Vec, + physical_l2_claim: E, + physical_l2_families: Vec>, } fn verify_stage1( proof: &AkitaStage1Proof, rs: &RingSwitchVerifyOutput, + lp: &CommittedGroupParams, + relation_plan: &RelationRangeImagePlan, transcript: &mut T, ) -> Result, AkitaError> where F: FieldCore + CanonicalField, - E: ExtField + FromPrimitiveInt + AkitaSerialize, + E: ExtField + FpExtEncoding + FromPrimitiveInt + AkitaSerialize, T: Transcript, { let num_rounds = rs.relation_address_geometry.relation_point_variable_count(); @@ -96,11 +101,65 @@ where )?; let plan = DigitRangePlan::new(rs.b)?; let stage1_verifier = AkitaStage1Verifier::new(equality_point, plan); - let stage1_point = { - let _sumcheck_span = tracing::info_span!("stage1_sumcheck").entered(); - stage1_verifier.verify::(proof, transcript)? - }; + let physical_plan = PhysicalResponsePlan::new(lp, relation_plan)?; + let (stage1_point, physical_l2_virtual_evaluations, physical_plan) = + match (physical_plan.as_ref(), proof.norm_proof.as_ref()) { + (None, None) => { + let point = { + let _sumcheck_span = tracing::info_span!("stage1_sumcheck").entered(); + stage1_verifier.verify::(proof, transcript)? + }; + (point, None, None) + } + (Some(plan), Some(norm_proof)) => { + let InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, .. + } = lp.inner_commit_matrix.security_route() + else { + return Err(AkitaError::InvalidSetup( + "physical response plan exists for a non-L2 route".into(), + )); + }; + let leaf = + stage1_verifier.verify_product_prefix::(&proof.stages, transcript)?; + let replay = verify_physical_l2_norm::( + plan, + norm_proof, + PhysicalL2RangeClaim { + equality_point: &leaf.equality_point, + input_claim: leaf.input_claim, + leaf_coefficients: &leaf.polynomial_coefficients, + image_evaluation: proof.range_image_evaluation, + }, + lp.inner_commit_matrix.sis_modulus_profile(), + response_l2_sq_cap, + transcript, + )?; + (replay.point, Some(replay.virtual_evaluations), Some(plan)) + } + _ => return Err(AkitaError::InvalidProof), + }; transcript.append_serde(ABSORB_RANGE_IMAGE_EVALUATION, &proof.range_image_evaluation); + let (physical_l2_claim, physical_l2_families) = + match (physical_l2_virtual_evaluations, physical_plan) { + (Some(evaluations), Some(plan)) => { + let eta = sample_ext_challenge::( + transcript, + akita_transcript::labels::CHALLENGE_L2_VIRTUAL_BATCH, + ); + let mut batching = Vec::with_capacity(evaluations.len()); + let mut power = E::one(); + let mut claim = E::zero(); + for evaluation in evaluations { + batching.push(power); + claim += evaluation * power; + power *= eta; + } + (claim, plan.virtualization_families(&batching)?) + } + (None, None) => (E::zero(), Vec::new()), + _ => return Err(AkitaError::InvalidProof), + }; let binary_batching = rs .compression_relation_weights .as_ref() @@ -111,6 +170,8 @@ where binary_batching, range_image_evaluation: proof.range_image_evaluation, stage1_point, + physical_l2_claim, + physical_l2_families, }) } @@ -186,6 +247,8 @@ where evaluation_trace, evaluation_trace_row_weight, evaluation_trace_opening_claim, + stage1.physical_l2_claim, + stage1.physical_l2_families, )?; let sumcheck_challenges = { @@ -426,12 +489,25 @@ where .map_err(|error| { AkitaError::InvalidInput(format!("compressed relation claim failed: {error:?}")) })?; - let stage1_replay = verify_stage1::(stage1, &rs, transcript).map_err(|error| { - AkitaError::InvalidInput(format!("compressed stage-1 replay failed: {error:?}")) - })?; // EvaluationTrace is the last padded relation row: weight openings by // `eq(tau1, EvaluationTrace_row_index)`. let opening_batch = relation_instance.opening_batch(); + let relation_range_image_plan = RelationRangeImagePlan::new( + rs.relation_address_geometry, + DigitRangePlan::new(rs.b)?, + rs.relation_matrix_evaluator.witness_layout()?.clone(), + opening_batch, + )?; + let stage1_replay = verify_stage1::( + stage1, + &rs, + prepared.lp, + &relation_range_image_plan, + transcript, + ) + .map_err(|error| { + AkitaError::InvalidInput(format!("compressed stage-1 replay failed: {error:?}")) + })?; let evaluation_trace_row = prepared.lp.evaluation_trace_row_index(opening_batch)?; let evaluation_trace_weight = evaluation_trace_row_weight(evaluation_trace_row, &rs.tau1)?; ensure_trace_stage2_supported(>::EXT_DEGREE)?; @@ -442,7 +518,7 @@ where actual: prepared.w_len, }); } - let trace_witness_layout = rs.relation_matrix_evaluator.witness_layout()?; + let trace_witness_layout = relation_range_image_plan.witness_layout(); let trace_preparation_span = tracing::info_span!( "stage2_evaluation_trace_preparation", claims = opening_batch.num_total_polynomials(), diff --git a/crates/akita-verifier/src/protocol/core/suffix.rs b/crates/akita-verifier/src/protocol/core/suffix.rs index e26f2a238..792134a16 100644 --- a/crates/akita-verifier/src/protocol/core/suffix.rs +++ b/crates/akita-verifier/src/protocol/core/suffix.rs @@ -322,13 +322,25 @@ where proof.terminal_response(), scheduled.response_shape.logical_num_elems(), )?; - let challenges = LiveFoldDraw::::new(transcript).draw_folding_challenges( + let operator_rejection = if params.response_l2_sq_cap().is_some() { + Some( + akita_challenges::selective_l2_operator_norm_rejection( + params.d_a(), + &scheduled.sparse_challenge_config, + ) + .ok_or(AkitaError::InvalidProof)?, + ) + } else { + None + }; + let challenges = LiveFoldDraw::::new(transcript).draw_folding_challenges_with_rejection( params.d_a(), 0, params.num_live_blocks, 1, &scheduled.sparse_challenge_config, proof.fold_grind_nonce, + operator_rejection, )?; transcript.absorb_and_record_bytes(ABSORB_TERMINAL_W_REMAINDER, &terminal_replay.response); super::terminal_direct::verify_terminal_ring_relations( diff --git a/crates/akita-verifier/src/protocol/core/terminal_direct.rs b/crates/akita-verifier/src/protocol/core/terminal_direct.rs index 3c50fe7ac..a14da81d6 100644 --- a/crates/akita-verifier/src/protocol/core/terminal_direct.rs +++ b/crates/akita-verifier/src/protocol/core/terminal_direct.rs @@ -183,6 +183,11 @@ where AkitaError::InvalidInput(format!("terminal z decode failed: {error:?}")) })? }; + if params.response_l2_sq_cap().is_some_and(|cap| { + akita_types::sis::checked_centered_l2_sq(&z_values).is_none_or(|norm| norm > cap) + }) { + return Err(AkitaError::InvalidProof); + } let z_centered = { let _span = tracing::info_span!( "terminal_direct_decode_z_rings", diff --git a/crates/akita-verifier/src/stages/mod.rs b/crates/akita-verifier/src/stages/mod.rs index f54b2178b..7b1c9ae2d 100644 --- a/crates/akita-verifier/src/stages/mod.rs +++ b/crates/akita-verifier/src/stages/mod.rs @@ -1,7 +1,9 @@ //! Akita-specific sumcheck verifier stages. +pub(crate) mod physical_l2_norm; pub(crate) mod stage1; pub(crate) mod stage2; pub(crate) mod stage3; +pub(crate) use physical_l2_norm::{verify_physical_l2_norm, PhysicalL2RangeClaim}; pub(crate) use stage3::SetupSumcheckVerifier; diff --git a/crates/akita-verifier/src/stages/physical_l2_norm.rs b/crates/akita-verifier/src/stages/physical_l2_norm.rs new file mode 100644 index 000000000..ada93cfd1 --- /dev/null +++ b/crates/akita-verifier/src/stages/physical_l2_norm.rs @@ -0,0 +1,525 @@ +//! Verifier replay for the schedule-selected physical response norm. + +use akita_algebra::eq_poly::EqPolynomial; +use akita_field::{AkitaError, CanonicalField, ExtField, FieldCore, FromPrimitiveInt}; +use akita_serialization::AkitaSerialize; +use akita_sumcheck::{SumcheckInstanceVerifier, SumcheckInstanceVerifierExt}; +use akita_transcript::labels::{ + ABSORB_L2_NORM_INTEGER, ABSORB_L2_NORM_SUBCLAIM, ABSORB_L2_VIRTUAL_EVALUATION, + CHALLENGE_L2_NORM_BATCH, CHALLENGE_L2_NORM_MERGE, CHALLENGE_SUMCHECK_ROUND, +}; +use akita_transcript::{sample_ext_challenge, Transcript}; +use akita_types::{ + reconstruct_l2_sq_from_gram, FpExtEncoding, PhysicalL2NormProof, PhysicalL2NormProofShape, + PhysicalResponsePlan, SisModulusProfileId, +}; + +pub(crate) struct PhysicalL2VerifierReplay { + pub(crate) point: Vec, + pub(crate) virtual_evaluations: Vec, +} + +pub(crate) struct PhysicalL2RangeClaim<'a, E> { + pub(crate) equality_point: &'a [E], + pub(crate) input_claim: E, + pub(crate) leaf_coefficients: &'a [E], + pub(crate) image_evaluation: E, +} + +struct PhysicalL2NormVerifier<'a, E: FieldCore> { + plan: &'a PhysicalResponsePlan, + proof: &'a PhysicalL2NormProof, + range_equality_point: &'a [E], + range_leaf_coefficients: &'a [E], + range_image_evaluation: E, + subclaim_weights: Vec, + input_claim: E, + norm_merge: E, +} + +impl SumcheckInstanceVerifier + for PhysicalL2NormVerifier<'_, E> +{ + fn num_rounds(&self) -> usize { + self.plan.domain().num_vars() + } + + fn degree_bound(&self) -> usize { + self.range_leaf_coefficients.len() + } + + fn input_claim(&self) -> E { + self.input_claim + } + + fn expected_output_claim(&self, point: &[E]) -> Result { + let range_equality = EqPolynomial::mle(self.range_equality_point, point)?; + let range_leaf = self + .range_leaf_coefficients + .iter() + .rev() + .fold(E::zero(), |acc, &coefficient| { + acc * self.range_image_evaluation + coefficient + }); + let norm = match self.plan.shape() { + PhysicalL2NormProofShape::Direct { .. } => { + let value = self + .proof + .virtual_evaluations + .first() + .copied() + .ok_or(AkitaError::InvalidProof)?; + value * value + } + shape @ PhysicalL2NormProofShape::LimbGram { .. } => { + let layout = shape.limb_gram_layout()?.ok_or(AkitaError::InvalidProof)?; + let mut pair_selectors = vec![E::zero(); layout.pair_count()]; + let mut block_start_sum = E::zero(); + for (block_index, block_range) in layout.block_ranges().enumerate() { + let block_end_sum = EqPolynomial::prefix_sum(point, block_range.end)?; + let block_weight = block_end_sum - block_start_sum; + for ((left, right), selector) in + layout.limb_pairs().zip(pair_selectors.iter_mut()) + { + let index = + layout + .subclaim_index(block_index, left, right) + .ok_or_else(|| { + AkitaError::InvalidSetup("L2 selector index overflow".into()) + })?; + let weight = self + .subclaim_weights + .get(index) + .copied() + .ok_or(AkitaError::InvalidProof)?; + *selector += weight * block_weight; + } + block_start_sum = block_end_sum; + } + let mut sum = E::zero(); + for ((left, right), selector) in layout.limb_pairs().zip(pair_selectors) { + let left = *self + .proof + .virtual_evaluations + .get(left) + .ok_or(AkitaError::InvalidProof)?; + let right = *self + .proof + .virtual_evaluations + .get(right) + .ok_or(AkitaError::InvalidProof)?; + sum += selector * left * right; + } + sum + } + }; + Ok(range_equality * range_leaf + self.norm_merge * norm) + } +} + +fn centered_lift(value: E, profile: SisModulusProfileId) -> Result +where + F: FieldCore + CanonicalField, + E: ExtField + FpExtEncoding, +{ + let coordinates = value.ext_coords(); + let Some((&first, tail)) = coordinates.split_first() else { + return Err(AkitaError::InvalidProof); + }; + if tail.iter().any(|coordinate| !coordinate.is_zero()) { + return Err(AkitaError::InvalidProof); + } + let modulus = profile.modulus(); + if modulus > i128::MAX as u128 { + return Err(AkitaError::InvalidSetup( + "centered limb lifting is only defined for small fields".into(), + )); + } + let canonical = first.to_canonical_u128(); + if canonical <= modulus / 2 { + i128::try_from(canonical).map_err(|_| AkitaError::InvalidProof) + } else { + let magnitude = modulus - canonical; + i128::try_from(magnitude) + .map(|value| -value) + .map_err(|_| AkitaError::InvalidProof) + } +} + +fn validate_integer_claim( + plan: &PhysicalResponsePlan, + proof: &PhysicalL2NormProof, + profile: SisModulusProfileId, + cap: u128, +) -> Result<(), AkitaError> +where + F: FieldCore + CanonicalField, + E: ExtField + FpExtEncoding, +{ + let modulus = profile.modulus(); + let modulus_minus_one = modulus + .checked_sub(1) + .ok_or_else(|| AkitaError::InvalidSetup("L2 modulus profile has an empty field".into()))?; + if F::from_canonical_u128_checked(modulus_minus_one).is_none() + || F::from_canonical_u128_checked(modulus).is_some() + { + return Err(AkitaError::InvalidSetup( + "L2 modulus profile disagrees with the proof base field".into(), + )); + } + if proof.response_l2_sq > cap { + return Err(AkitaError::InvalidProof); + } + plan.shape() + .validate_integer_soundness(profile, plan.fold_basis(), plan.fold_digit_count())?; + match plan.shape() { + PhysicalL2NormProofShape::Direct { .. } => { + if !proof.subclaims.is_empty() + || proof.virtual_evaluations.len() != 1 + || proof.response_l2_sq >= modulus + { + return Err(AkitaError::InvalidProof); + } + } + shape @ PhysicalL2NormProofShape::LimbGram { block_len, .. } => { + let layout = shape.limb_gram_layout()?.ok_or(AkitaError::InvalidProof)?; + if proof.subclaims.len() != layout.subclaim_count() + || proof.virtual_evaluations.len() != layout.limb_count() + { + return Err(AkitaError::InvalidProof); + } + let digit_abs = (plan.fold_basis() / 2) as u128; + let claim_abs_bound = (block_len as u128) + .checked_mul( + digit_abs + .checked_mul(digit_abs) + .ok_or_else(|| AkitaError::InvalidSetup("L2 limb bound overflow".into()))?, + ) + .ok_or_else(|| AkitaError::InvalidSetup("L2 limb bound overflow".into()))?; + let integers = proof + .subclaims + .iter() + .copied() + .map(|claim| centered_lift::(claim, profile)) + .collect::, _>>()?; + if integers + .iter() + .any(|value| value.unsigned_abs() > claim_abs_bound) + || reconstruct_l2_sq_from_gram(plan.shape(), plan.fold_basis(), &integers)? + != proof.response_l2_sq + { + return Err(AkitaError::InvalidProof); + } + } + } + Ok(()) +} + +pub(crate) fn verify_physical_l2_norm( + plan: &PhysicalResponsePlan, + proof: &PhysicalL2NormProof, + range: PhysicalL2RangeClaim<'_, E>, + profile: SisModulusProfileId, + cap: u128, + transcript: &mut T, +) -> Result, AkitaError> +where + F: FieldCore + CanonicalField, + E: ExtField + FpExtEncoding + FromPrimitiveInt + AkitaSerialize, + T: Transcript, +{ + if range.equality_point.len() != plan.domain().num_vars() || range.leaf_coefficients.len() < 3 { + return Err(AkitaError::InvalidSetup( + "fused Stage-1 leaf has inconsistent range geometry".into(), + )); + } + validate_integer_claim::(plan, proof, profile, cap)?; + transcript.append_serde(ABSORB_L2_NORM_INTEGER, &proof.response_l2_sq); + for claim in &proof.subclaims { + transcript.append_serde(ABSORB_L2_NORM_SUBCLAIM, claim); + } + let mut subclaim_weights = Vec::new(); + let norm_input_claim = match plan.shape() { + PhysicalL2NormProofShape::Direct { .. } => E::from_u128(proof.response_l2_sq), + PhysicalL2NormProofShape::LimbGram { .. } => { + let gamma = sample_ext_challenge::(transcript, CHALLENGE_L2_NORM_BATCH); + let mut power = E::one(); + for _ in 0..proof.subclaims.len() { + subclaim_weights.push(power); + power *= gamma; + } + proof + .subclaims + .iter() + .zip(&subclaim_weights) + .fold(E::zero(), |sum, (&claim, &weight)| sum + claim * weight) + } + }; + let norm_merge = sample_ext_challenge::(transcript, CHALLENGE_L2_NORM_MERGE); + let verifier = PhysicalL2NormVerifier { + plan, + proof, + range_equality_point: range.equality_point, + range_leaf_coefficients: range.leaf_coefficients, + range_image_evaluation: range.image_evaluation, + subclaim_weights, + input_claim: range.input_claim + norm_merge * norm_input_claim, + norm_merge, + }; + let point = verifier.verify::(&proof.sumcheck, transcript, |tr| { + sample_ext_challenge::(tr, CHALLENGE_SUMCHECK_ROUND) + })?; + for evaluation in &proof.virtual_evaluations { + transcript.append_serde(ABSORB_L2_VIRTUAL_EVALUATION, evaluation); + } + Ok(PhysicalL2VerifierReplay { + point, + virtual_evaluations: proof.virtual_evaluations.clone(), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::stages::stage1::AkitaStage1Verifier; + use akita_challenges::SparseChallengeConfig; + use akita_field::{FpExt4, Prime32Offset99}; + use akita_serialization::{AkitaDeserialize, AkitaSerialize}; + use akita_transcript::AkitaTranscript; + use akita_types::proof::PhysicalL2NormProofWireShape; + use akita_types::sis::{ + role_a_collision_l2_sq_for_response_bound, sis_l2_table_key_for_collision_sq, + DEFAULT_SIS_SECURITY_POLICY, + }; + use akita_types::{ + AkitaStage1Proof, CommitmentRingDims, CommittedGroupParams, DigitRangeEqualityPoint, + DigitRangePlan, InnerCommitMatrixParams, OpeningClaimsLayout, RelationAddressGeometry, + RelationRangeImagePlan, SisL2TableDigest, WitnessLayout, + }; + + type SmallExt = FpExt4; + + fn limb_gram_fixture() -> (PhysicalResponsePlan, Vec, u128) { + const RING_DIMENSION: usize = 64; + const POSITIONS_PER_BLOCK: usize = 4; + const LIVE_RING_ELEMENTS: usize = 8; + const FOLD_DIGITS: usize = 2; + const RESPONSE_L2_SQ_CAP: u128 = 1 << 20; + + let profile = SisModulusProfileId::Q32Offset99; + let shape = PhysicalL2NormProofShape::LimbGram { + physical_response_len: 512, + block_len: 128, + limb_count: FOLD_DIGITS, + }; + let collision_l2_sq = role_a_collision_l2_sq_for_response_bound(1, RESPONSE_L2_SQ_CAP) + .expect("collision square"); + let table_key = sis_l2_table_key_for_collision_sq( + DEFAULT_SIS_SECURITY_POLICY, + SisL2TableDigest::CURRENT, + profile, + RING_DIMENSION as u32, + collision_l2_sq, + ) + .expect("small-field L2 table row"); + let inner = InnerCommitMatrixParams::try_new_l2_with_min_rank( + table_key, + POSITIONS_PER_BLOCK * FOLD_DIGITS, + RESPONSE_L2_SQ_CAP, + shape, + ) + .expect("L2 A matrix"); + let mut params = CommittedGroupParams::params_only( + profile, + RING_DIMENSION, + 2, + inner.output_rank(), + 1, + 1, + SparseChallengeConfig::pm1_only(1), + ); + params.inner_commit_matrix = inner; + params = params + .with_decomp(POSITIONS_PER_BLOCK, LIVE_RING_ELEMENTS, FOLD_DIGITS, 1, 1) + .expect("complete scalar params"); + params.num_digits_fold = FOLD_DIGITS; + + let opening = OpeningClaimsLayout::new(9, 1).expect("opening layout"); + let witness_layout = WitnessLayout::new(¶ms, &opening, 1, 1).expect("witness layout"); + let relation_geometry = RelationAddressGeometry::new( + CommitmentRingDims::uniform(RING_DIMENSION), + RING_DIMENSION, + witness_layout.live_coeff_len(), + ) + .expect("relation geometry"); + let relation_plan = RelationRangeImagePlan::new( + relation_geometry, + DigitRangePlan::new(4).expect("digit range"), + witness_layout, + &opening, + ) + .expect("relation plan"); + let physical = PhysicalResponsePlan::new(¶ms, &relation_plan) + .expect("physical response plan") + .expect("L2 route"); + assert_eq!(physical.shape(), shape); + assert!( + physical + .shape() + .limb_gram_layout() + .expect("checked limb layout") + .expect("limb layout") + .block_count() + > 1 + ); + + let witness = (0..physical.domain().live_len()) + .map(|index| [-1, 0, 1, 0][index % 4]) + .collect(); + (physical, witness, RESPONSE_L2_SQ_CAP) + } + + fn prove_limb_gram( + plan: &PhysicalResponsePlan, + witness: Vec, + ) -> ( + AkitaStage1Proof, + Vec, + DigitRangeEqualityPoint, + ) { + let range_plan = DigitRangePlan::new(16).expect("range plan"); + let equality_point = DigitRangeEqualityPoint::from_column_then_ring_challenges( + &vec![SmallExt::zero(); plan.domain().num_vars()], + plan.domain().num_vars(), + 0, + ) + .expect("range equality point"); + let prover = akita_prover::DigitRangeProver::new( + std::sync::Arc::from(witness), + range_plan, + plan.domain(), + equality_point.clone(), + ) + .expect("L2 digit-range prover"); + let mut transcript = + AkitaTranscript::::new(b"akita/physical-l2-small-field-integration"); + let (proof, point) = prover + .prove::(&mut transcript, Some(plan)) + .expect("prove multi-block limb Gram norm"); + (proof, point, equality_point) + } + + fn verify_limb_gram( + plan: &PhysicalResponsePlan, + proof: &AkitaStage1Proof, + equality_point: DigitRangeEqualityPoint, + cap: u128, + ) -> Result, AkitaError> { + let mut transcript = + AkitaTranscript::::new(b"akita/physical-l2-small-field-integration"); + let stage1 = + AkitaStage1Verifier::new(equality_point, DigitRangePlan::new(16).expect("range plan")); + let leaf = + stage1.verify_product_prefix::(&proof.stages, &mut transcript)?; + let norm_proof = proof.norm_proof.as_ref().ok_or(AkitaError::InvalidProof)?; + verify_physical_l2_norm::( + plan, + norm_proof, + PhysicalL2RangeClaim { + equality_point: &leaf.equality_point, + input_claim: leaf.input_claim, + leaf_coefficients: &leaf.polynomial_coefficients, + image_evaluation: proof.range_image_evaluation, + }, + SisModulusProfileId::Q32Offset99, + cap, + &mut transcript, + ) + } + + #[test] + fn centered_lift_accepts_both_boundary_representatives() { + type F = Prime32Offset99; + let profile = SisModulusProfileId::Q32Offset99; + let modulus = profile.modulus(); + let half = modulus / 2; + let positive = F::from_canonical_u128_checked(half).expect("positive boundary"); + let negative = F::from_canonical_u128_checked(half + 1).expect("negative boundary"); + + assert_eq!( + centered_lift::(positive, profile).unwrap(), + half as i128 + ); + assert_eq!( + centered_lift::(negative, profile).unwrap(), + -(half as i128) + ); + } + + #[test] + fn small_field_multiblock_limb_gram_round_trip_and_mutations() { + let (plan, witness, cap) = limb_gram_fixture(); + let (stage1_proof, prover_point, equality_point) = prove_limb_gram(&plan, witness); + let proof = stage1_proof + .norm_proof + .as_ref() + .expect("physical norm proof"); + assert!(!proof.subclaims.is_empty()); + assert!(proof.response_l2_sq <= cap); + + let wire_shape = PhysicalL2NormProofWireShape { + subclaims: proof.subclaims.len(), + virtual_evaluations: proof.virtual_evaluations.len(), + sumcheck: proof + .sumcheck + .round_polys + .iter() + .map(|poly| poly.coeffs_except_linear_term.len()) + .collect(), + }; + let mut bytes = Vec::new(); + proof + .serialize_compressed(&mut bytes) + .expect("serialize physical norm proof"); + let decoded = + PhysicalL2NormProof::::deserialize_compressed(bytes.as_slice(), &wire_shape) + .expect("deserialize physical norm proof"); + assert_eq!(&decoded, proof); + let mut decoded_stage1 = stage1_proof.clone(); + decoded_stage1.norm_proof = Some(decoded.clone()); + let replay = verify_limb_gram(&plan, &decoded_stage1, equality_point.clone(), cap) + .expect("verify multi-block limb Gram norm"); + assert_eq!(replay.point, prover_point); + assert_eq!(replay.virtual_evaluations, decoded.virtual_evaluations); + + let mut over_cap = decoded_stage1.clone(); + over_cap + .norm_proof + .as_mut() + .expect("physical norm proof") + .response_l2_sq = cap + 1; + assert!(verify_limb_gram(&plan, &over_cap, equality_point.clone(), cap).is_err()); + + let mut bad_subclaim = decoded_stage1.clone(); + bad_subclaim + .norm_proof + .as_mut() + .expect("physical norm proof") + .subclaims[0] += SmallExt::one(); + assert!(verify_limb_gram(&plan, &bad_subclaim, equality_point.clone(), cap).is_err()); + + let mut bad_evaluation = decoded_stage1; + bad_evaluation + .norm_proof + .as_mut() + .expect("physical norm proof") + .virtual_evaluations[0] += SmallExt::one(); + assert!(verify_limb_gram(&plan, &bad_evaluation, equality_point, cap).is_err()); + + assert!(PhysicalL2NormProof::::deserialize_compressed( + &bytes[..bytes.len() - 1], + &wire_shape, + ) + .is_err()); + } +} diff --git a/crates/akita-verifier/src/stages/stage1.rs b/crates/akita-verifier/src/stages/stage1.rs index afe404261..54b4e1f86 100644 --- a/crates/akita-verifier/src/stages/stage1.rs +++ b/crates/akita-verifier/src/stages/stage1.rs @@ -20,6 +20,12 @@ use akita_types::{ type DigitRangeVerifyOutput = Vec; +pub(crate) struct RangeLeafVerifierInput { + pub(crate) equality_point: Vec, + pub(crate) input_claim: E, + pub(crate) polynomial_coefficients: Vec, +} + /// Absorb the prover's `v` rows once, then sample one [`Challenges`] set per /// commitment group in `OpeningClaims` order. /// @@ -58,14 +64,27 @@ where let group_lp = lp.group_params(opening_batch, group_index)?; let group_dims = lp.group_role_dims(opening_batch, group_index)?; let k_g = opening_batch.group_layout(group_index)?.num_polynomials(); + let challenge_config = group_lp.fold_challenge_config(); + let rejection = matches!( + group_lp.inner_commit_matrix_params().security_route(), + akita_types::InnerCommitSecurityRoute::L2 { .. } + ) + .then(|| { + akita_challenges::selective_l2_operator_norm_rejection( + group_dims.d_a(), + &challenge_config, + ) + }) + .flatten(); group_challenges.push( - LiveFoldDraw::::new(transcript).draw_folding_challenges( + LiveFoldDraw::::new(transcript).draw_folding_challenges_with_rejection( group_dims.d_a(), group_index, group_lp.num_live_blocks(), k_g, - &group_lp.fold_challenge_config(), + &challenge_config, grind_nonce, + rejection, )?, ); } @@ -175,34 +194,45 @@ impl AkitaStage1Verifier { } impl AkitaStage1Verifier { - /// Verify the full stage-1 tree proof and return the final `stage1_point`. - /// - /// # Errors - /// - /// Returns an error if the staged proof shape is inconsistent with `b`, if - /// any internal stage sumcheck fails, or if the final oracle check fails. - pub fn verify( + pub(crate) fn verify_product_prefix( &self, - proof: &AkitaStage1Proof, + product_stage_proofs: &[akita_types::AkitaStage1StageProof], transcript: &mut T, - ) -> Result, AkitaError> + ) -> Result, AkitaError> where F: FieldCore + CanonicalField, E: ExtField, T: Transcript, { - self.plan - .validate_proof_shape(proof, self.equality_point.coordinates().len())?; + let product_stage_arities = self.plan.product_stage_arities(); + if product_stage_proofs.len() != product_stage_arities.len() { + return Err(AkitaError::InvalidSize { + expected: product_stage_arities.len(), + actual: product_stage_proofs.len(), + }); + } + let rounds = self.equality_point.coordinates().len(); + for (stage_index, stage) in product_stage_proofs.iter().enumerate() { + let expected = self + .plan + .stage_shape(rounds, stage_index) + .ok_or(AkitaError::InvalidProof)?; + if stage.sumcheck_proof.round_polys.len() != expected.sumcheck_proof.0 + || stage.child_claims.len() != expected.child_claims + || stage + .sumcheck_proof + .round_polys + .iter() + .any(|round| round.coeffs_except_linear_term.len() != expected.sumcheck_proof.1) + { + return Err(AkitaError::InvalidProof); + } + } let leaf_coeffs = self.plan.leaf_coeffs::(); - let product_stage_arities = self.plan.product_stage_arities(); - let Some((leaf_stage_proof, product_stage_proofs)) = proof.stages.split_last() else { - return Err(AkitaError::InvalidProof); - }; let mut current_equality_point = self.equality_point.coordinates().to_vec(); let mut current_claim = E::zero(); let mut current_weights = vec![E::one()]; - for (&arity, stage_proof) in product_stage_arities .iter() .zip(product_stage_proofs.iter()) @@ -219,7 +249,6 @@ impl AkitaStage1Verifier { transcript, |tr| sample_ext_challenge::(tr, labels::CHALLENGE_SUMCHECK_ROUND), )?; - append_digit_range_child_claims::(&stage_proof.child_claims, transcript); let gamma = sample_ext_challenge::( transcript, @@ -232,15 +261,45 @@ impl AkitaStage1Verifier { .plan .batch_claims(¤t_weights, &stage_proof.child_claims)?; } + Ok(RangeLeafVerifierInput { + equality_point: current_equality_point, + input_claim: current_claim, + polynomial_coefficients: self + .plan + .batch_leaf_polynomials(¤t_weights, &leaf_coeffs)?, + }) + } + + /// Verify the full stage-1 tree proof and return the final `stage1_point`. + /// + /// # Errors + /// + /// Returns an error if the staged proof shape is inconsistent with `b`, if + /// any internal stage sumcheck fails, or if the final oracle check fails. + pub fn verify( + &self, + proof: &AkitaStage1Proof, + transcript: &mut T, + ) -> Result, AkitaError> + where + F: FieldCore + CanonicalField, + E: ExtField, + T: Transcript, + { + self.plan + .validate_proof_shape(proof, self.equality_point.coordinates().len())?; - let batched_leaf_coeffs = self - .plan - .batch_leaf_polynomials(¤t_weights, &leaf_coeffs)?; + let product_stage_arities = self.plan.product_stage_arities(); + let Some((leaf_stage_proof, product_stage_proofs)) = proof.stages.split_last() else { + return Err(AkitaError::InvalidProof); + }; + debug_assert_eq!(product_stage_proofs.len(), product_stage_arities.len()); + let leaf = self.verify_product_prefix::(product_stage_proofs, transcript)?; let leaf_verifier = RangePolynomialLeafVerifier { plan: self.plan, - equality_point: current_equality_point, - input_claim: current_claim, - poly_coeffs: batched_leaf_coeffs, + equality_point: leaf.equality_point, + input_claim: leaf.input_claim, + poly_coeffs: leaf.polynomial_coefficients, range_image_evaluation: proof.range_image_evaluation, }; leaf_verifier.verify::(&leaf_stage_proof.sumcheck_proof, transcript, |tr| { diff --git a/crates/akita-verifier/src/stages/stage2.rs b/crates/akita-verifier/src/stages/stage2.rs index a448dc7b3..b126f484e 100644 --- a/crates/akita-verifier/src/stages/stage2.rs +++ b/crates/akita-verifier/src/stages/stage2.rs @@ -2,7 +2,10 @@ use crate::protocol::evaluation_trace::PreparedEvaluationTrace; use crate::protocol::ring_switch::RelationMatrixEvaluator; -use akita_algebra::eq_poly::EqPolynomial; +use akita_algebra::{ + eq_poly::EqPolynomial, + offset_eq::{eval_boolean_pair_tensor_families, EqPairTensorFamily}, +}; use akita_field::{ AkitaError, CanonicalField, ExtField, FieldCore, FromPrimitiveInt, HalvingField, MulBaseUnreduced, @@ -30,6 +33,8 @@ pub(crate) struct AkitaStage2Verifier<'a, F: FieldCore, E: FieldCore> { evaluation_trace: PreparedEvaluationTrace, evaluation_trace_row_weight: E, evaluation_trace_opening_claim: E, + physical_l2_claim: E, + physical_l2_families: Vec>, _marker: std::marker::PhantomData, } @@ -60,6 +65,8 @@ where evaluation_trace: PreparedEvaluationTrace, evaluation_trace_row_weight: E, evaluation_trace_opening_claim: E, + physical_l2_claim: E, + physical_l2_families: Vec>, ) -> Result { let num_rounds = col_bits.checked_add(ring_bits).ok_or_else(|| { AkitaError::InvalidSetup("stage-2 variable count overflow".to_string()) @@ -70,6 +77,9 @@ where actual: stage1_point.len(), }); } + if physical_l2_families.is_empty() && !physical_l2_claim.is_zero() { + return Err(AkitaError::InvalidProof); + } Ok(Self { batching_coeff, range_image_evaluation, @@ -87,6 +97,8 @@ where evaluation_trace, evaluation_trace_row_weight, evaluation_trace_opening_claim, + physical_l2_claim, + physical_l2_families, _marker: std::marker::PhantomData, }) } @@ -109,6 +121,7 @@ where self.batching_coeff * self.range_image_evaluation + self.relation_claim + self.evaluation_trace_opening_claim + + self.physical_l2_claim } #[tracing::instrument(skip_all, name = "stage2_expected_output_claim")] @@ -148,17 +161,30 @@ where let trace_weight = self.evaluation_trace.evaluate_at_point(challenges)?; self.evaluation_trace_row_weight * w_eval * trace_weight }; + let physical_l2_oracle = if self.physical_l2_families.is_empty() { + E::zero() + } else { + let weight_eval = eval_boolean_pair_tensor_families::<_, false, false>( + challenges, + &self.stage1_point, + &self.physical_l2_families, + )?; + w_eval * weight_eval + }; // A zero batching challenge removes the virtual term. Avoid the // unnecessary EqPolynomial evaluation in that degenerate case. if self.batching_coeff.is_zero() { - return Ok(relation_oracle + trace_oracle); + return Ok(relation_oracle + trace_oracle + physical_l2_oracle); } let virtual_oracle = { let _span = tracing::info_span!("stage2_virtual_oracle").entered(); let eq_val = EqPolynomial::mle(&self.stage1_point, challenges)?; eq_val * w_eval * (w_eval + E::one()) }; - Ok(self.batching_coeff * virtual_oracle + relation_oracle + trace_oracle) + Ok(self.batching_coeff * virtual_oracle + + relation_oracle + + trace_oracle + + physical_l2_oracle) } } diff --git a/docs/verifier-contract.md b/docs/verifier-contract.md index 1ff4fce97..7e8ed8317 100644 --- a/docs/verifier-contract.md +++ b/docs/verifier-contract.md @@ -19,7 +19,7 @@ The verifier never invokes planner search. It accepts only an explicit Before setup access or transcript replay, it validates catalog identity and runtime hooks, resolves the public row digest, compares every ordered public `CommittedGroupProfile`, re-audits every A/B/D/recursive/terminal SIS matrix, -checks challenge and full terminal cap geometry, and confirms the schedule fits +checks challenge and full terminal L infinity or L2 cap geometry, and confirms the schedule fits the setup field capacity. Private polynomial representations and honest-prover witness models are not verifier inputs. diff --git a/scripts/gen_sis_table.py b/scripts/gen_sis_table.py index 3891c4ec4..58827c165 100644 --- a/scripts/gen_sis_table.py +++ b/scripts/gen_sis_table.py @@ -4,8 +4,8 @@ This script binary-searches for the maximum SIS width (in ring elements) that provides >= 128-bit security for each (d, collision_l2_sq, rank) triple. The -output is the Rust match arm body for `sis_max_widths` in the split -`crates/akita-types/src/sis/generated_sis_table/` modules. +output is the Rust match arm body for `sis_l2_max_widths` in the split +`crates/akita-types/src/sis/generated_l2_sis_table/` modules. Requires SageMath and the pinned lattice-estimator checkout under `third_party/lattice-estimator` (or an explicit override). @@ -28,19 +28,18 @@ --jobs N Run N independent Sage subprocess shards (default: 1). Collision bucket convention: - Each bucket is the per-ring-row squared Euclidean collision bound - `collision_l2_sq` (an exact integer). The SIS solution spans `width` ring - rows, each of squared norm <= collision_l2_sq, so the whole-vector Euclidean - length bound passed to lattice-estimator is `sqrt(width * collision_l2_sq)`. + Each bucket is the complete scalar collision vector's squared Euclidean + bound `collision_l2_sq` (an exact integer). The whole-vector Euclidean + length bound passed to lattice-estimator is `sqrt(collision_l2_sq)`. Buckets are exact powers of two; the Rust table rounds a raw key up via `next_power_of_two` and clamps to the same ladder as `MIN_LOG_BUCKET` / `MAX_LOG_BUCKET` in `sis/ajtai_key.rs`. -Modeling choices (matching the existing table): - - Reduction model: BDGL16 +Modeling choices: + - Reduction model: ADPS16 quantum - Norm: Euclidean (l2); `red_shape_model` is ignored on this path - Field modulus for estimation: selected by --family / --q - - length_bound = sqrt(width * collision_l2_sq) (per-row squared key) + - length_bound = sqrt(collision_l2_sq) (complete-vector squared key) The runtime protocol prime may be a different 128-bit pseudo-Mersenne prime, for example p = 2^128 - 2^32 + 22537. That distinction is immaterial for @@ -56,7 +55,6 @@ import argparse import os -import re import signal import subprocess import sys @@ -72,7 +70,6 @@ estimator_git_sha, estimator_remote_url, locate_estimator, - repo_root, ) if hasattr(signal, "SIGPIPE"): @@ -84,60 +81,26 @@ MAX_LOG_BUCKET = 84 SQUARED_BUCKETS = [1 << k for k in range(MIN_LOG_BUCKET, MAX_LOG_BUCKET + 1)] -def canonical_coeff_linf_buckets() -> list[int]: - source = ( - repo_root() - / "crates/akita-types/src/sis/ajtai_key.rs" - ).read_text(encoding="utf-8") - match = re.search( - r"pub const COEFF_LINF_BUCKETS: &\[u128\] = &\[(.*?)\];", - source, - flags=re.DOTALL, - ) - if match is None: - raise RuntimeError("could not read canonical COEFF_LINF_BUCKETS") - return [int(value.replace("_", "")) for value in re.findall(r"[\d_]+", match.group(1))] - - -COEFF_LINF_BUCKETS = canonical_coeff_linf_buckets() - -RING_DIMS = [32, 64, 128, 256] - - -def coeff_linf_bucket_sq(b: int) -> int: - """Return `B²` for a coefficient-L∞ bucket `B` without float rounding.""" - if b <= 3: - return b * b - # Buckets after `3` are `2^k - 1`; square via bit shifts. - k = (b + 1).bit_length() - 1 - return (1 << (2 * k)) - (1 << (k + 1)) + 1 - - -def derived_l2_collision_keys() -> list[int]: - keys: set[int] = set() - for d in RING_DIMS: - for b in COEFF_LINF_BUCKETS: - keys.add(d * coeff_linf_bucket_sq(b)) - return sorted(keys) +RING_DIMS = [32, 64, 128, 256, 512] FAMILIES: dict[str, tuple[int, str, list[int], list[int]]] = { "q32": ( (1 << 32) - 99, "2^32 - 99", - [32, 64, 128, 256], + RING_DIMS, SQUARED_BUCKETS, ), "q64": ( (1 << 64) - 59, "2^64 - 59", - [32, 64, 128, 256], + RING_DIMS, SQUARED_BUCKETS, ), "q128": ( (1 << 128) - ((1 << 32) - 22537), "2^128 - (2^32 - 22537)", - [32, 64, 128, 256], + RING_DIMS, SQUARED_BUCKETS, ), } @@ -218,9 +181,9 @@ def default_search_cap(d: int) -> int: def load_estimator(path: Path): sys.path.insert(0, str(path)) from estimator import SIS - from estimator.reduction import RC + from estimator.reduction import ADPS16 from sage.all import RealField, ZZ, log, oo - return SIS, RC, log, oo, ZZ, RealField + return SIS, ADPS16, log, oo, ZZ, RealField def family_entries(family: str) -> list[tuple[int, int]]: @@ -260,34 +223,32 @@ def select_entries(args: argparse.Namespace) -> list[tuple[int, int]]: return entries -def sis_length_bound(ZZ, RealField, width: int, collision: int): - """High-precision Euclidean SIS solution bound `sqrt(width * collision_l2_sq)`. +def sis_length_bound(ZZ, RealField, collision: int): + """High-precision Euclidean SIS solution bound `sqrt(collision_l2_sq)`. Build the integer product exactly, then convert it to an upward-rounded Sage real with precision scaled to the product size. This avoids Python's f64 `** 0.5` path while still giving lattice-estimator the numeric real it expects (rather than a symbolic `sqrt(...)` expression). """ - squared = ZZ(width) * ZZ(collision) + squared = ZZ(collision) precision = max(256, int(squared.nbits()) + 128) return RealField(precision, rnd="RNDU")(squared).sqrt() def estimate_bits( - SIS, RC, log, oo, ZZ, RealField, + SIS, ADPS16, log, oo, ZZ, RealField, q: int, d: int, rank: int, width: int, collision: int, ) -> float: - # `collision` is the per-ring-row squared Euclidean bound (collision_l2_sq). - # The SIS solution spans `width` ring rows, so the whole-vector Euclidean - # length bound is sqrt(width * collision_l2_sq). The SIS matrix still has - # m = width * d scalar columns and n = rank * d scalar rows. + # `collision` bounds the complete scalar collision vector across every + # input ring row. `width` affects m, but must not scale the norm again. n = rank * d m = width * d - length_bound = sis_length_bound(ZZ, RealField, width, collision) + length_bound = sis_length_bound(ZZ, RealField, collision) try: out = SIS.lattice( SIS.Parameters(n=n, q=q, m=m, length_bound=length_bound, norm=2, tag="sis_table"), - red_cost_model=RC.BDGL16, + red_cost_model=ADPS16(mode="quantum"), log_level=0, ) except ValueError as exc: @@ -301,7 +262,7 @@ def estimate_bits( def binary_search_max_width( - SIS, RC, log, oo, ZZ, RealField, + SIS, ADPS16, log, oo, ZZ, RealField, q: int, d: int, rank: int, collision: int, target_bits: float, search_cap: int, @@ -320,22 +281,22 @@ def binary_search_max_width( the common small-answer cells cheap (small `m = width*d`), instead of the cap-first binary search's ~log2(cap) huge-`m` probes per cell. """ - if estimate_bits(SIS, RC, log, oo, ZZ, RealField, q, d, rank, 1, collision) < target_bits: + if estimate_bits(SIS, ADPS16, log, oo, ZZ, RealField, q, d, rank, 1, collision) < target_bits: return 0 - if estimate_bits(SIS, RC, log, oo, ZZ, RealField, q, d, rank, search_cap, collision) >= target_bits: + if estimate_bits(SIS, ADPS16, log, oo, ZZ, RealField, q, d, rank, search_cap, collision) >= target_bits: return search_cap hi = 1 while True: nxt = min(hi * 2, search_cap) - if estimate_bits(SIS, RC, log, oo, ZZ, RealField, q, d, rank, nxt, collision) >= target_bits: + if estimate_bits(SIS, ADPS16, log, oo, ZZ, RealField, q, d, rank, nxt, collision) >= target_bits: hi = nxt continue lo, high = hi, nxt while lo < high - 1: mid = (lo + high) // 2 - if estimate_bits(SIS, RC, log, oo, ZZ, RealField, q, d, rank, mid, collision) >= target_bits: + if estimate_bits(SIS, ADPS16, log, oo, ZZ, RealField, q, d, rank, mid, collision) >= target_bits: lo = mid else: high = mid @@ -353,7 +314,7 @@ def print_provenance_header( print(f"// Generated by: sage -python scripts/gen_sis_table.py") print(f"// Family: {args.family.upper()}") print(f"// lattice-estimator: {remote} @ {sha}") - print(f"// Model: BDGL16, Euclidean (norm=2)") + print(f"// Model: ADPS16 quantum, Euclidean (norm=2), complete-vector L2 bound") print(f"// Representative q = {q_label}") print(f"// q = {q}") if args.search_cap is None: @@ -399,7 +360,7 @@ def run_entries( entries: list[tuple[int, int]], estimator_path: Path, ) -> list[tuple[int, int, list[int]]]: - SIS, RC, log, oo, ZZ, RealField = load_estimator(estimator_path) + SIS, ADPS16, log, oo, ZZ, RealField = load_estimator(estimator_path) family_q, _, _, _ = FAMILIES[args.family] q = args.q if args.q is not None else family_q @@ -415,7 +376,7 @@ def run_entries( for rank in range(1, args.max_rank + 1): t0 = time.time() w = binary_search_max_width( - SIS, RC, log, oo, ZZ, RealField, q, d, rank, collision, + SIS, ADPS16, log, oo, ZZ, RealField, q, d, rank, collision, args.target_bits, search_cap, ) elapsed = time.time() - t0 diff --git a/scripts/lattice_estimator_pin.py b/scripts/lattice_estimator_pin.py index 8629faa16..f5050c4c9 100644 --- a/scripts/lattice_estimator_pin.py +++ b/scripts/lattice_estimator_pin.py @@ -7,7 +7,8 @@ from pathlib import Path # malb/lattice-estimator#217 head; strict descendant of malb#213 @ 27a581b. -# Euclidean (BDGL16, norm=2) output is unchanged from 27a581b; infinity needs #217. +# Euclidean geometry is unchanged from 27a581b; Akita prices its required BKZ +# block size with ADPS16 quantum. Infinity needs #217. PINNED_LATTICE_ESTIMATOR_SHA = "c667a48546f140c3a5454c7503c3ca44a264cce2" diff --git a/scripts/operator_norm/README.md b/scripts/operator_norm/README.md new file mode 100644 index 000000000..672ae7a15 --- /dev/null +++ b/scripts/operator_norm/README.md @@ -0,0 +1,25 @@ +# Operator-norm accepted-support certificates + +This directory contains exact offline certificates for the sparse challenge +families used by operator-norm rejection sampling. + +- `d64/` certifies the selective-L2 shell with 31 magnitude-one and 11 + magnitude-two coefficients at true operator norm `Gamma <= 18`. +- `d128/` certifies the production signed weight-31 shell at true operator norm + `Gamma <= 13`. + +The runtime fixed-point predicates use strict thresholds one unit above these +true-subset thresholds. The exact certificates prove that each true subset has +at least 128 bits of accepted support. They do not rely on Monte Carlo data. + +Run both exact checkers through repository test discovery: + +```bash +python3 -m unittest scripts.tests.test_operator_norm_certificates +``` + +The D128 directory also contains the modular moment generator, CRT +reconstruction, numerical dual search, rational certificate emitter, and a +small exhaustive validation of the moment generator. Floating point is used +only to search for a candidate dual polynomial. Both final checkers use exact +rational arithmetic for every load-bearing inequality. diff --git a/scripts/operator_norm/d128/README.md b/scripts/operator_norm/d128/README.md new file mode 100644 index 000000000..5ee2e4d1b --- /dev/null +++ b/scripts/operator_norm/d128/README.md @@ -0,0 +1,57 @@ +# D128 operator-norm accepted-support certificate + +This directory certifies the production signed weight-31 shell in dimension 128. +The certified subset is `Gamma(c) <= 13`; a fixed-point implementation can use a +strict runtime threshold of 14 to contain that true subset. + +The final exact result is: + +``` +q1 <= 0.008120720198295826 +Pr[Gamma(c) <= 13] >= 0.480273907309067161 +log2(N_raw * p0) >= 128.563317131141 +``` + +The exact support-floor cutoff is `q1 < 0.010546520951777437`. + +## Final verification + +```bash +python3 validate_moment_generator.py +python3 -u check_cert.py +``` + +The first command compiles the modular moment generator, compares it with a +separate exhaustive enumeration on a small shell, and checks the independently +derived closed form for the D128 second moment. The second command checks all +eight saved modular residues, moment admissibility, the rational dual +expectation, exact polynomial positivity through a rational Sturm sequence, and +the exact accepted-support inequality. Pass `--check-bernstein` to additionally +replay all 4096 rational Bernstein subintervals used by the emitted certificate. + +## Reproduction pipeline + +`moments_mod.cpp` computes unnormalized spectral moments modulo a prime that has +a primitive `2d`-th root. The seven reconstruction primes have a 427-bit +product, above the 396-bit a priori bound `C(128,31) * 961^30`. The eighth prime +is not used by CRT and checks every reconstructed moment independently. + +Compile and regenerate the eight `moments_.txt` files with the prime and +primitive-generator pairs recorded in `reconstruct_moments.py`, then run: + +```bash +python3 reconstruct_moments.py +python3 solve_dual.py +python3 make_cert.py +python3 -u check_cert.py +``` + +`solve_dual.py` uses floating point only to search for a candidate polynomial. +It rounds the coefficients to exact rationals and adds an exact rational upward +shift. The final checker uses rational arithmetic for every load-bearing step. +The certificate uses degree 30 and 4096 rational Bernstein subintervals. + +For a fixed-seed 100,000-sample validation, the empirical acceptance rates at +thresholds 11, 12, 13, and 14 were respectively 0.24010, 0.55498, 0.79173, and +0.91811. The formal floor at 13 is intentionally much lower than the observed +rate. diff --git a/scripts/operator_norm/d128/cert_d128_w31_gamma13.json b/scripts/operator_norm/d128/cert_d128_w31_gamma13.json new file mode 100644 index 000000000..7e462e68d --- /dev/null +++ b/scripts/operator_norm/d128/cert_d128_w31_gamma13.json @@ -0,0 +1,121 @@ +{ + "description": "Exact accepted-support certificate for the production d=128, weight-31, signed unit sparse challenge family and true operator-norm subset Gamma<=13.", + "method": "degree-30 exact moment dual, exact Bernstein positivity, union bound", + "params": { + "d": 128, + "a_mag1": 31, + "b_mag2": 0, + "w_nonzero": 31, + "l1_norm": 31, + "l2_sq": 31, + "support_cap_B": 961, + "Gamma": 13, + "threshold_Gamma_sq": 169, + "lambda_bits": 128, + "num_distinct_freqs": 64 + }, + "N_raw": "1046949673839956231392050469602223718400", + "moments_M0_to_M30": { + "0": "1/1", + "1": "31/1", + "2": "239227/127", + "3": "21369757/127", + "4": "17461590689/889", + "5": "7491495007277/2667", + "6": "300016283022623/635", + "7": "173116170910960411/1905", + "8": "62168690736493131927/3175", + "9": "103408577572608259425823/22225", + "10": "43896017788308618452428981/36449", + "11": "183801868658040710237667122909/546735", + "12": "5579645573602775850127462738098669/55584725", + "13": "758524992814104068687949913903856783/23822025", + "14": "2795341443565826642362697324884286700439/262042275", + "15": "275567029883554451964554051295146145450863/73371837", + "16": "2537955314208707078700672765201638590603712917/1834295925", + "17": "88603027242695111052128395890165344301438601921/166754175", + "18": "6955243225905407491919722551289333520782282548101/32808545", + "19": "353580650847994650464198765484614486773449667737020753/4035451035", + "20": "424200787634199226562873642769280102971571640975261534653/11337695765", + "21": "2800746291860563985225106350446220366098835602072959219932093/170065436475", + "22": "73357257147317789745571292845250312084712810264795313197410497/9838496325", + "23": "75014006539539314527672481782155237058123222831772766535344640601/21644691915", + "24": "11911599593707442860166349854649417514345805535463291966143063260681/7214897305", + "25": "3483883435753471596029809503640027892864219046176949346878166813809121/4328938383", + "26": "49167502882012869775472120466146578582533337471480114070337371179882028733/122653254185", + "27": "324573914531509439173334666667580615997931953743415551229267426013995939191/1592899405", + "28": "41892460599293818910437754071099483121082944791088148723479756503615859947057031/396819351775", + "29": "1127041854115240737157838060612299152238295720193878775147213452786847706050637495147/20237786940525", + "30": "4555542358035470797553222973088563565331384495314600964792042129449096431219227382261543/152457994951955" + }, + "dual_poly": { + "basis": "shifted_Chebyshev", + "def": "Q(x)=sum_j r_j * T_j(2x/B - 1)", + "degree": 30, + "coeffs_r0_to_r30": { + "0": "70874690801685168376653777524151735085442001850468438098494726707561822152013055480276909786108733266628515279282767486882227379902102489070593685617358502040734879406071611/708744733874176823325584856815109134343770558204257295548482262786464456532715657163502532224376690925816854619861291552463884285312162381626991488684665455247360000000000", + "1": "100/1", + "2": "-7956356077651703/140737488355328", + "3": "-5044042429086369/70368744177664", + "4": "8819863677302075/562949953421312", + "5": "3267179593787647/70368744177664", + "6": "1972714873824157/4503599627370496", + "7": "-958567093027773/35184372088832", + "8": "-4131734174025267/562949953421312", + "9": "6561258051611841/562949953421312", + "10": "1364222514626679/140737488355328", + "11": "8064546158504621/4503599627370496", + "12": "-5023047458273155/562949953421312", + "13": "-7664768816939287/562949953421312", + "14": "704917114291341/140737488355328", + "15": "837384901897077/35184372088832", + "16": "5978906135308379/2251799813685248", + "17": "-4448585250987881/140737488355328", + "18": "-4129541329302559/281474976710656", + "19": "9599590954223/274877906944", + "20": "4366797487800789/140737488355328", + "21": "-4155978442782669/140737488355328", + "22": "-6951069863995161/140737488355328", + "23": "2562416733116175/281474976710656", + "24": "8490741757349835/140737488355328", + "25": "8613368514290197/281474976710656", + "26": "-5444272181574627/140737488355328", + "27": "-4781720915110827/70368744177664", + "28": "-3264368374136663/70368744177664", + "29": "-71123209394671/4398046511104", + "30": "-42056614224047/17592186044416" + } + }, + "bernstein_certificate": { + "num_subintervals": 4096, + "nonneg_interval_for_Q": [ + 0, + 961 + ], + "ge1_interval_for_Q_minus_1": [ + 169, + 961 + ] + }, + "claimed": { + "q1_star": "526484810858518509254328341822047967690027653896037490239341301687074846597300418786918908603110796207585347323112883997724423581479663299288352837700950549991549765218694908340669703/64832280635528364012421844397429539929532989010583246764712293587716392319700077709284395695158528757538731966211801344792707213247543743197671871172996285887351989707504353280000000000", + "p0": "486519574071612178439762976887788593708925299394325740459288285620993783398013295420649774133741215628957339648946512014661626625513207688175270149377116416998325073961060611659330297/1013004384930130687694091318709836561398952953290363230698629587308068629995313714207568682736852011836542686972059396012386050206992870987463622987078066966989874839179755520000000000", + "cutoff_q1_for_floor": "2570840686235961649540243751/243761966433365883164119550400", + "minimum_bernstein_Q": "807190246033626602164707755031841778553786348863771622382937057473183331225339845390493996604678739229370549085687512610391725236981532621693509809496508746437230470758006397303233894495196180217/2632150451086514534240669548701949095354995280178182631208823018402775742360198473221325111522241246463202104176607093589933840979071358559237525147039776425049183699946212828176587864145920000000000", + "minimum_bernstein_Q_minus_1": "1/10000000000" + }, + "moment_generation": { + "algorithm": "exact truncated bivariate EGF over finite-field primitive 256th roots, seven-prime CRT plus independent eighth-prime check", + "reconstruction_primes": [ + 2305843009213689601, + 2305843009213689089, + 2305843009213687297, + 2305843009213683713, + 2305843009213682689, + 2305843009213675777, + 2305843009213673729 + ], + "independent_check_prime": 2305843009213666049, + "a_priori_numerator_bound": "C(128,31)*961^m for moment m" + } +} diff --git a/scripts/operator_norm/d128/check_cert.py b/scripts/operator_norm/d128/check_cert.py new file mode 100644 index 000000000..2a3144673 --- /dev/null +++ b/scripts/operator_norm/d128/check_cert.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python3 +import json +import math +import sys +from fractions import Fraction as F +from math import comb +from pathlib import Path + + +def chebyshev_monomials(n): + polys = [[F(1)], [F(0), F(1)]] + for degree in range(2, n + 1): + current = [F(0)] * (degree + 1) + for i, coefficient in enumerate(polys[degree - 1]): + current[i + 1] += 2 * coefficient + for i, coefficient in enumerate(polys[degree - 2]): + current[i] -= coefficient + polys.append(current) + return polys + + +def trim(polynomial): + while polynomial and polynomial[-1] == 0: + polynomial.pop() + return polynomial + + +def polynomial_remainder(dividend, divisor): + remainder = dividend[:] + while remainder and len(remainder) >= len(divisor): + factor = remainder[-1] / divisor[-1] + shift = len(remainder) - len(divisor) + for i, coefficient in enumerate(divisor): + remainder[i + shift] -= factor * coefficient + trim(remainder) + return remainder + + +def sturm_sequence(polynomial): + derivative = [i * polynomial[i] for i in range(1, len(polynomial))] + sequence = [trim(polynomial[:]), trim(derivative)] + while sequence[-1]: + remainder = [-coefficient for coefficient in polynomial_remainder(sequence[-2], sequence[-1])] + if not remainder: + break + # Positive rescaling preserves the Sturm sign variations and keeps the + # exact rational coefficients small enough for a fast stdlib check. + scale = abs(remainder[-1]) + sequence.append([coefficient / scale for coefficient in remainder]) + return sequence + + +def evaluate(polynomial, point): + value = F(0) + for coefficient in reversed(polynomial): + value = value * point + coefficient + return value + + +def sign_variations(sequence, point): + signs = [] + for polynomial in sequence: + value = evaluate(polynomial, point) + if value != 0: + signs.append(value > 0) + return sum(left != right for left, right in zip(signs, signs[1:])) + + +def strictly_positive_on_interval(polynomial, lo, hi): + if evaluate(polynomial, lo) <= 0 or evaluate(polynomial, hi) <= 0: + return False, None + sequence = sturm_sequence(polynomial) + root_count = sign_variations(sequence, lo) - sign_variations(sequence, hi) + return root_count == 0, root_count + + +def positive_definite(matrix): + work = [row[:] for row in matrix] + pivots = [] + for k in range(len(work)): + pivot = work[k][k] + pivots.append(pivot) + if pivot <= 0: + return False, pivot + for i in range(k + 1, len(work)): + factor = work[i][k] / pivot + for j in range(k, len(work)): + work[i][j] -= factor * work[k][j] + return True, min(pivots) + + +def bernstein_min(coefficients, lo, hi, degree): + length = hi - lo + reparameterized = [F(0)] * (degree + 1) + for i, coefficient in enumerate(coefficients): + for power in range(i + 1): + reparameterized[power] += ( + coefficient * comb(i, power) * lo ** (i - power) * length ** power + ) + return min( + sum( + F(comb(k, i), comb(degree, i)) * reparameterized[i] + for i in range(k + 1) + ) + for k in range(degree + 1) + ) + + +def interval_certificate_min(coefficients, lo, hi, subdivisions, degree): + return min( + bernstein_min( + coefficients, + lo + (hi - lo) * F(i, subdivisions), + lo + (hi - lo) * F(i + 1, subdivisions), + degree, + ) + for i in range(subdivisions) + ) + + +def load_residues(path): + return { + int(line.split()[0]): int(line.split()[1]) + for line in path.read_text().splitlines()[1:] + } + + +def main(): + arguments = sys.argv[1:] + check_bernstein = "--check-bernstein" in arguments + arguments = [argument for argument in arguments if argument != "--check-bernstein"] + cert_path = Path(arguments[0]) if arguments else Path("cert_d128_w31_gamma13.json") + cert = json.loads(cert_path.read_text()) + params = cert["params"] + d = params["d"] + w = params["w_nonzero"] + b = params["b_mag2"] + B = params["support_cap_B"] + gamma = params["Gamma"] + nfreq = params["num_distinct_freqs"] + security_bits = params["lambda_bits"] + nraw = comb(d, w) * comb(w, b) * 2**w + moments = {int(k): F(v) for k, v in cert["moments_M0_to_M30"].items()} + degree = cert["dual_poly"]["degree"] + rational = {int(k): F(v) for k, v in cert["dual_poly"]["coeffs_r0_to_r30"].items()} + ok = True + + def check(name, condition, detail=""): + nonlocal ok + ok &= condition + print(f"[{'PASS' if condition else 'FAIL'}] {name}{': ' + detail if detail else ''}") + + check("production dimensions", d == 128 and w == 31 and b == 0) + check("B=l1^2", B == params["l1_norm"] ** 2 == 961) + check("Gamma^2=169", params["threshold_Gamma_sq"] == gamma * gamma == 169) + check("64 conjugacy-distinct odd frequencies", nfreq == d // 2 == 64) + check("raw support", str(nraw) == cert["N_raw"]) + check("M0=1 and M1=31", moments[0] == 1 and moments[1] == 31) + + support_count = comb(d, w) + residue_checks = True + for prime in cert["moment_generation"]["reconstruction_primes"] + [cert["moment_generation"]["independent_check_prime"]]: + path = cert_path.parent / f"moments_{prime}.txt" + if not path.exists(): + residue_checks = False + break + residues = load_residues(path) + for m in range(degree + 1): + numerator_sum = moments[m] * support_count + if numerator_sum.denominator != 1 or numerator_sum.numerator % prime != residues[m]: + residue_checks = False + break + check("all moments match eight modular generator outputs", residue_checks) + + half = degree // 2 + matrices = [ + [[moments[i + j] for j in range(half + 1)] for i in range(half + 1)], + [[moments[i + j + 1] for j in range(half)] for i in range(half)], + [[B * moments[i + j] - moments[i + j + 1] for j in range(half)] for i in range(half)], + ] + for label, matrix in zip(["Hankel", "x localizer", "B-x localizer"], matrices): + is_pd, minimum_pivot = positive_definite(matrix) + check(f"moment admissibility {label}", is_pd, f"minimum LDL pivot {float(minimum_pivot):.3e}") + + chebyshev = chebyshev_monomials(degree) + ez = [ + sum(comb(k, j) * F(2, B) ** j * (-1) ** (k - j) * moments[j] for j in range(k + 1)) + for k in range(degree + 1) + ] + expected_chebyshev = [ + sum(chebyshev[j][k] * ez[k] for k in range(len(chebyshev[j]))) + for j in range(degree + 1) + ] + q = sum(rational[j] * expected_chebyshev[j] for j in range(degree + 1)) + p0 = 1 - nfreq * q + check("claimed marginal tail bound", q == F(cert["claimed"]["q1_star"]), f"q={float(q):.15f}") + check("claimed acceptance floor", p0 == F(cert["claimed"]["p0"]), f"p0={float(p0):.15f}") + + z_coefficients = [F(0)] * (degree + 1) + for j in range(degree + 1): + for i, coefficient in enumerate(chebyshev[j]): + z_coefficients[i] += rational[j] * coefficient + positive, root_count = strictly_positive_on_interval(z_coefficients, F(-1), F(1)) + check("Q>0 exact Sturm certificate on [-1,1]", positive, f"roots={root_count}") + z_minus_one = z_coefficients[:] + z_minus_one[0] -= 1 + threshold_z = F(2 * gamma * gamma, B) - 1 + positive, root_count = strictly_positive_on_interval(z_minus_one, threshold_z, F(1)) + check("Q-1>0 exact Sturm certificate on the tail", positive, f"roots={root_count}") + + if check_bernstein: + x_coefficients = [F(0)] * (degree + 1) + for j in range(degree + 1): + for k, coefficient in enumerate(chebyshev[j]): + for i in range(k + 1): + x_coefficients[i] += ( + rational[j] * coefficient * comb(k, i) * F(2, B) ** i * (-1) ** (k - i) + ) + subdivisions = cert["bernstein_certificate"]["num_subintervals"] + gap0 = interval_certificate_min(x_coefficients, F(0), F(B), subdivisions, degree) + minus_one = x_coefficients[:] + minus_one[0] -= 1 + gap1 = interval_certificate_min(minus_one, F(gamma * gamma), F(B), subdivisions, degree) + check("Q>=0 exact Bernstein certificate", gap0 >= 0, f"minimum={float(gap0):.3e}") + check("Q-1>=0 exact Bernstein certificate", gap1 >= 0, f"minimum={float(gap1):.3e}") + check("claimed Bernstein minima", gap0 == F(cert["claimed"]["minimum_bernstein_Q"]) and gap1 == F(cert["claimed"]["minimum_bernstein_Q_minus_1"])) + + cutoff = F(1, nfreq) * (1 - F(2**security_bits, nraw)) + check("q below exact support-floor cutoff", q < cutoff, f"{float(q):.9f} < {float(cutoff):.9f}") + check("accepted support is at least 2^128", F(nraw) * p0 >= 2**security_bits) + accepted_bits = math.log2(nraw) + math.log2(p0.numerator) - math.log2(p0.denominator) + print(f"RESULT: {'ALL CHECKS PASS' if ok else 'FAILURE'}") + print(f"Pr[Gamma(c)<=13] >= {float(p0):.12f}") + print(f"log2(N_raw*p0) = {accepted_bits:.12f}") + raise SystemExit(0 if ok else 1) + + +if __name__ == "__main__": + main() diff --git a/scripts/operator_norm/d128/make_cert.py b/scripts/operator_norm/d128/make_cert.py new file mode 100644 index 000000000..2b70a4697 --- /dev/null +++ b/scripts/operator_norm/d128/make_cert.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +import json +from fractions import Fraction as F +from math import comb +from pathlib import Path + +D = 128 +W = 31 +GAMMA = 13 +LAMBDA = 128 +NFREQ = D // 2 +B = W * W + + +def main(): + moments = json.loads(Path("moments_d128_w31.json").read_text()) + coefficients = json.loads(Path("dual_coefficients.json").read_text()) + summary = json.loads(Path("dual_summary.json").read_text()) + nraw = comb(D, W) * 2**W + cert = { + "description": ( + "Exact accepted-support certificate for the production d=128, weight-31, " + "signed unit sparse challenge family and true operator-norm subset Gamma<=13." + ), + "method": "degree-30 exact moment dual, exact Bernstein positivity, union bound", + "params": { + "d": D, + "a_mag1": W, + "b_mag2": 0, + "w_nonzero": W, + "l1_norm": W, + "l2_sq": W, + "support_cap_B": B, + "Gamma": GAMMA, + "threshold_Gamma_sq": GAMMA * GAMMA, + "lambda_bits": LAMBDA, + "num_distinct_freqs": NFREQ, + }, + "N_raw": str(nraw), + "moments_M0_to_M30": moments, + "dual_poly": { + "basis": "shifted_Chebyshev", + "def": "Q(x)=sum_j r_j * T_j(2x/B - 1)", + "degree": 30, + "coeffs_r0_to_r30": coefficients, + }, + "bernstein_certificate": { + "num_subintervals": summary["subdivisions"], + "nonneg_interval_for_Q": [0, B], + "ge1_interval_for_Q_minus_1": [GAMMA * GAMMA, B], + }, + "claimed": { + "q1_star": summary["q"], + "p0": summary["p0"], + "cutoff_q1_for_floor": summary["cutoff"], + "minimum_bernstein_Q": summary["gap0"], + "minimum_bernstein_Q_minus_1": summary["gap1"], + }, + "moment_generation": { + "algorithm": "exact truncated bivariate EGF over finite-field primitive 256th roots, seven-prime CRT plus independent eighth-prime check", + "reconstruction_primes": [ + 2305843009213689601, + 2305843009213689089, + 2305843009213687297, + 2305843009213683713, + 2305843009213682689, + 2305843009213675777, + 2305843009213673729, + ], + "independent_check_prime": 2305843009213666049, + "a_priori_numerator_bound": "C(128,31)*961^m for moment m", + }, + } + Path("cert_d128_w31_gamma13.json").write_text(json.dumps(cert, indent=1) + "\n") + + +if __name__ == "__main__": + main() diff --git a/scripts/operator_norm/d128/moments_2305843009213666049.txt b/scripts/operator_norm/d128/moments_2305843009213666049.txt new file mode 100644 index 000000000..e9fb40d80 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213666049.txt @@ -0,0 +1,32 @@ +prime 2305843009213666049 root 983772545565526107 +0 271346961080334611 +1 1494226765849374794 +2 249676103236792905 +3 2105443655198459043 +4 483856035956984335 +5 1575578994575958439 +6 2292599994107568743 +7 1374742889775110601 +8 2171277788296566215 +9 1944435682157852044 +10 2230926315831938886 +11 1581462515123840899 +12 367056550225224510 +13 1302166982252811945 +14 770110848291709248 +15 121071548081251749 +16 391300511034214539 +17 657769155606191613 +18 199810954435373330 +19 1730753711785211197 +20 1820191644810616045 +21 40903166421067993 +22 2142813573980642192 +23 1602973782365244622 +24 1091302177589787339 +25 656532675429350460 +26 1595101161227441126 +27 758280321799026634 +28 1013611920746354945 +29 159826938664181476 +30 1498688412212619491 diff --git a/scripts/operator_norm/d128/moments_2305843009213673729.txt b/scripts/operator_norm/d128/moments_2305843009213673729.txt new file mode 100644 index 000000000..2157fdc45 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213673729.txt @@ -0,0 +1,32 @@ +prime 2305843009213673729 root 1420695913366196660 +0 269723180194362131 +1 1443889558384204874 +2 1802683145217253963 +3 968123825121260825 +4 869264441237015063 +5 1839492093023154052 +6 1787408740349208224 +7 381403435222489766 +8 408957614918458640 +9 1410403481205709814 +10 2277617247364559143 +11 80403458547590368 +12 435403981223671144 +13 406695184199242202 +14 647738880930476592 +15 1292658113238980710 +16 662133077474788908 +17 149577447267172692 +18 232720551461242012 +19 758691285840154314 +20 622357512246587840 +21 2032143258825055089 +22 1790776194784424760 +23 684995058969644289 +24 1826911628590803278 +25 928917712355586354 +26 509693393436547087 +27 481027308760730099 +28 837419265993208891 +29 702983330801471391 +30 549125123982702258 diff --git a/scripts/operator_norm/d128/moments_2305843009213675777.txt b/scripts/operator_norm/d128/moments_2305843009213675777.txt new file mode 100644 index 000000000..699b5c408 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213675777.txt @@ -0,0 +1,32 @@ +prime 2305843009213675777 root 878250968026800207 +0 269290171958102803 +1 1430466303060159562 +2 987035418164755019 +3 1894621475348274489 +4 2048100086980620672 +5 1448700322564399875 +6 730354732094777314 +7 885293259798180253 +8 2280618498424924845 +9 2081574640188319520 +10 2242880379820710859 +11 828083665627409764 +12 544658119071619105 +13 1037565590816254709 +14 1178602248325555067 +15 765822053384336397 +16 1772686414999751196 +17 1059796120605909956 +18 1407799003776146110 +19 211250851223195655 +20 1795300488352583200 +21 1583712490968383141 +22 1590836079582170947 +23 865139825598237339 +24 569041975376662234 +25 1317560075694838986 +26 1155022294849640328 +27 1172481852454974003 +28 1621339783717950878 +29 529444213436943643 +30 570580674935690093 diff --git a/scripts/operator_norm/d128/moments_2305843009213682689.txt b/scripts/operator_norm/d128/moments_2305843009213682689.txt new file mode 100644 index 000000000..d275f1418 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213682689.txt @@ -0,0 +1,32 @@ +prime 2305843009213682689 root 467758080632614518 +0 267828769160727571 +1 1385162816341506634 +2 540067348576253772 +3 409865026438047907 +4 550293244594348576 +5 994469241672442416 +6 45103898744740194 +7 1145285585893712766 +8 2079368009355368636 +9 1369115575403706113 +10 765356162174861982 +11 2186960404029040267 +12 1052237347277813478 +13 1826030933009435448 +14 1000458619130292547 +15 531891196361996686 +16 2169978398776537001 +17 1952485159837098641 +18 930808071217478774 +19 1726058823139066547 +20 1986742781409690935 +21 1063603400842835242 +22 1417911702793722079 +23 240428676321121580 +24 652926640890334134 +25 993777483919184969 +26 101104921874076514 +27 1150849716056511301 +28 1111230243399646736 +29 996428069583998111 +30 546274787168254790 diff --git a/scripts/operator_norm/d128/moments_2305843009213683713.txt b/scripts/operator_norm/d128/moments_2305843009213683713.txt new file mode 100644 index 000000000..76649abe8 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213683713.txt @@ -0,0 +1,32 @@ +prime 2305843009213683713 root 1751062625154885710 +0 267612265042597907 +1 1378451188679483978 +2 132243485050005324 +3 873113851551823027 +4 2292632572104155477 +5 1951994865506117744 +6 1822420653365360900 +7 244453159619729273 +8 1893340298538329354 +9 2168510617472584595 +10 2066242638384012980 +11 1664496940636593487 +12 263576506721048758 +13 1221462246478926813 +14 919082042929729065 +15 444696056197109714 +16 2225922385777823564 +17 527987952813825636 +18 628656784366591150 +19 958233654153393169 +20 2288774544343210521 +21 1183885335529085153 +22 523546123905348692 +23 426918781133433240 +24 1832662276797224733 +25 222035412513147673 +26 1985351541853980540 +27 1135826867527397561 +28 2156799796985995683 +29 1085479433324675331 +30 1382286349557732755 diff --git a/scripts/operator_norm/d128/moments_2305843009213687297.txt b/scripts/operator_norm/d128/moments_2305843009213687297.txt new file mode 100644 index 000000000..499d86d03 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213687297.txt @@ -0,0 +1,32 @@ +prime 2305843009213687297 root 1404240504602138521 +0 266854500629144083 +1 1354960491862404682 +2 1010702971921823053 +3 188641730236606698 +4 320369686170330251 +5 691648534750270030 +6 1125500982360904632 +7 550441794524277609 +8 1271894692168139291 +9 483001322944783245 +10 1798638876703150568 +11 447666961569436305 +12 1152775265052899972 +13 899616370290018585 +14 342638910584044096 +15 1544773616085579995 +16 1323920668304926173 +17 713302712695377455 +18 1008230790663098721 +19 1531937104464937523 +20 853440278952467012 +21 1416436133572520831 +22 1636167775182694504 +23 715848818027170651 +24 2068954731506052339 +25 368292360556768134 +26 585201718798791244 +27 1736913297828735632 +28 656947299087237067 +29 645850362617445728 +30 573606229683751533 diff --git a/scripts/operator_norm/d128/moments_2305843009213689089.txt b/scripts/operator_norm/d128/moments_2305843009213689089.txt new file mode 100644 index 000000000..53075f199 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213689089.txt @@ -0,0 +1,32 @@ +prime 2305843009213689089 root 1823593780277023706 +0 266475618422417171 +1 1343215143453865034 +2 297011210750890061 +3 999327174185990918 +4 1640081252434455079 +5 61475371853644349 +6 777041564212921106 +7 703516386251615585 +8 2131390032792066468 +9 1444467143975256969 +10 197833334660224436 +11 964745057586579230 +12 1036106045853178820 +13 1496969294882331465 +14 2163991139394353711 +15 1584494284939265288 +16 2196003751313337720 +17 1450360796463041638 +18 740785999257556223 +19 351724191003781775 +20 1808495810115641936 +21 931123306668335904 +22 747454460198361538 +23 796736682825195340 +24 264878593513898435 +25 1906457651743789595 +26 800358735525564220 +27 1496703758944640670 +28 642899551413536635 +29 264536572680543875 +30 863136810574043524 diff --git a/scripts/operator_norm/d128/moments_2305843009213689601.txt b/scripts/operator_norm/d128/moments_2305843009213689601.txt new file mode 100644 index 000000000..ad37db8e8 --- /dev/null +++ b/scripts/operator_norm/d128/moments_2305843009213689601.txt @@ -0,0 +1,32 @@ +prime 2305843009213689601 root 1062281476586377573 +0 266367366363352339 +1 1339859329622853706 +2 93099278987766349 +3 1230951586742976270 +4 1358329411593847233 +5 540238185390923613 +6 1665700214081108451 +7 1406074101737835359 +8 2049671941760479435 +9 2222444743148215761 +10 1537264086316198034 +11 167962662506572021 +12 1592857476699222184 +13 1384018705274603149 +14 680961268798565398 +15 1343050627056931955 +16 914521899274994646 +17 403948908976822724 +18 1459127894759566733 +19 229957871903820574 +20 2166816533175019163 +21 1855910548318239485 +22 1398294188221388524 +23 1667731420137749150 +24 1267553942475588034 +25 1597108026692910827 +26 83643366194958554 +27 1086098731241026093 +28 1520091786316533859 +29 1650400474783022326 +30 305164212458717679 diff --git a/scripts/operator_norm/d128/moments_mod.cpp b/scripts/operator_norm/d128/moments_mod.cpp new file mode 100644 index 000000000..50b1f3da3 --- /dev/null +++ b/scripts/operator_norm/d128/moments_mod.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using u64 = std::uint64_t; +using u128 = unsigned __int128; + +static u64 mod_mul(u64 a, u64 b, u64 p) { + return static_cast((static_cast(a) * b) % p); +} + +static u64 mod_pow(u64 a, u64 e, u64 p) { + u64 r = 1; + while (e != 0) { + if (e & 1) r = mod_mul(r, a, p); + a = mod_mul(a, a, p); + e >>= 1; + } + return r; +} + +static inline void add_assign(u64 &x, u64 y, u64 p) { + u64 z = x + y; + if (z >= p || z < x) z -= p; + x = z; +} + +int main(int argc, char **argv) { + if (argc != 4 && argc != 6) { + std::cerr << "usage: moments_mod PRIME PRIMITIVE_ROOT MAX_MOMENT [DIMENSION WEIGHT]\n"; + return 2; + } + const u64 mod = std::stoull(argv[1]); + const u64 primitive = std::stoull(argv[2]); + const int n = std::stoi(argv[3]); + const int d = argc == 6 ? std::stoi(argv[4]) : 128; + const int w = argc == 6 ? std::stoi(argv[5]) : 31; + if (d <= 0 || w < 0 || w > d || (mod - 1) % (2 * d) != 0) { + std::cerr << "invalid dimension, weight, or modulus\n"; + return 2; + } + const int side = n + 1; + const int area = side * side; + auto at = [side, area](int k, int a, int b) { + return k * area + a * side + b; + }; + + const u64 root = mod_pow(primitive, (mod - 1) / (2 * d), mod); + if (mod_pow(root, 2 * d, mod) != 1 || mod_pow(root, d, mod) != mod - 1) { + std::cerr << "supplied generator did not produce a primitive 256th root\n"; + return 2; + } + + std::vector fact(side, 1), invfact(side, 1); + for (int i = 1; i <= n; ++i) fact[i] = mod_mul(fact[i - 1], i, mod); + invfact[n] = mod_pow(fact[n], mod - 2, mod); + for (int i = n; i > 0; --i) invfact[i - 1] = mod_mul(invfact[i], i, mod); + + std::vector dp((w + 1) * area, 0); + std::vector even(area), odd(area), conv(area); + dp[at(0, 0, 0)] = 1; + + const auto started = std::chrono::steady_clock::now(); + for (int pos = 0; pos < d; ++pos) { + const u64 rp = mod_pow(root, pos, mod); + const u64 rn = mod_pow(rp, mod - 2, mod); + std::vector poscoef(side), negcoef(side); + poscoef[0] = negcoef[0] = 1; + for (int i = 1; i <= n; ++i) { + poscoef[i] = mod_mul(mod_mul(poscoef[i - 1], rp, mod), i == 1 ? 1 : 1, mod); + negcoef[i] = mod_mul(negcoef[i - 1], rn, mod); + } + for (int i = 0; i <= n; ++i) { + poscoef[i] = mod_mul(poscoef[i], invfact[i], mod); + negcoef[i] = mod_mul(negcoef[i], invfact[i], mod); + } + + for (int k = std::min(w, pos + 1); k >= 1; --k) { + std::fill(even.begin(), even.end(), 0); + std::fill(odd.begin(), odd.end(), 0); + std::fill(conv.begin(), conv.end(), 0); + const int prev = (k - 1) * area; + + for (int q = 0; q <= n; ++q) { + for (int p = 0; p <= n; ++p) { + u64 se = 0, so = 0; + for (int i = 0; i <= p; i += 2) + add_assign(se, mod_mul(dp[prev + (p - i) * side + q], poscoef[i], mod), mod); + for (int i = 1; i <= p; i += 2) + add_assign(so, mod_mul(dp[prev + (p - i) * side + q], poscoef[i], mod), mod); + even[p * side + q] = se; + odd[p * side + q] = so; + } + } + for (int p = 0; p <= n; ++p) { + for (int q = 0; q <= n; ++q) { + u64 s = 0; + for (int j = 0; j <= q; j += 2) + add_assign(s, mod_mul(even[p * side + q - j], negcoef[j], mod), mod); + for (int j = 1; j <= q; j += 2) + add_assign(s, mod_mul(odd[p * side + q - j], negcoef[j], mod), mod); + conv[p * side + q] = s; + } + } + const int dst = k * area; + for (int idx = 0; idx < area; ++idx) add_assign(dp[dst + idx], conv[idx], mod); + } + } + + std::cout << "prime " << mod << " root " << root << "\n"; + for (int m = 0; m <= n; ++m) { + u64 residue = dp[at(w, m, m)]; + residue = mod_mul(residue, fact[m], mod); + residue = mod_mul(residue, fact[m], mod); + std::cout << m << " " << residue << "\n"; + } + const auto elapsed = std::chrono::duration(std::chrono::steady_clock::now() - started).count(); + std::cerr << "elapsed_seconds " << elapsed << "\n"; +} diff --git a/scripts/operator_norm/d128/reconstruct_moments.py b/scripts/operator_norm/d128/reconstruct_moments.py new file mode 100644 index 000000000..e323134c7 --- /dev/null +++ b/scripts/operator_norm/d128/reconstruct_moments.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import glob +import json +from fractions import Fraction +from math import comb +from pathlib import Path + +from sympy.ntheory.modular import crt + +D = 128 +W = 31 +B = W * W +PRIMES = [ + 2305843009213689601, + 2305843009213689089, + 2305843009213687297, + 2305843009213683713, + 2305843009213682689, + 2305843009213675777, + 2305843009213673729, + 2305843009213666049, +] + + +def load_residues(prime): + lines = Path(f"moments_{prime}.txt").read_text().splitlines()[1:] + return {int(line.split()[0]): int(line.split()[1]) for line in lines} + + +def main(): + residues = {p: load_residues(p) for p in PRIMES} + support_count = comb(D, W) + moments = {} + reconstruction_primes = PRIMES[:7] + check_prime = PRIMES[7] + modulus_product = 1 + for p in reconstruction_primes: + modulus_product *= p + + for m in range(31): + value, modulus = crt( + reconstruction_primes, + [residues[p][m] for p in reconstruction_primes], + check=True, + ) + value = int(value) + assert int(modulus) == modulus_product + assert value <= support_count * (B ** m), (m, value.bit_length()) + assert value % check_prime == residues[check_prime][m], m + moment = Fraction(value, support_count) + moments[str(m)] = f"{moment.numerator}/{moment.denominator}" + print(m, moments[str(m)]) + + Path("moments_d128_w31.json").write_text(json.dumps(moments, indent=2) + "\n") + print(f"seven-prime CRT bits: {modulus_product.bit_length()}") + print(f"largest a priori bound bits: {(support_count * B**30).bit_length()}") + print(f"independent eighth-prime residue checks: PASS") + + +if __name__ == "__main__": + main() diff --git a/scripts/operator_norm/d128/solve_dual.py b/scripts/operator_norm/d128/solve_dual.py new file mode 100644 index 000000000..cf787f493 --- /dev/null +++ b/scripts/operator_norm/d128/solve_dual.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python3 +import json +from fractions import Fraction as F +from math import comb, log2 +from pathlib import Path + +import numpy as np +from scipy.optimize import linprog + +D = 128 +W = 31 +B = W * W +GAMMA = 13 +N = 30 + + +def chebyshev_monomials(n): + polys = [[F(1)], [F(0), F(1)]] + for degree in range(2, n + 1): + current = [F(0)] * (degree + 1) + for i, coefficient in enumerate(polys[degree - 1]): + current[i + 1] += 2 * coefficient + for i, coefficient in enumerate(polys[degree - 2]): + current[i] -= coefficient + polys.append(current) + return polys + + +def chebyshev_values(points, n): + values = np.zeros((len(points), n + 1)) + values[:, 0] = 1 + values[:, 1] = points + for degree in range(2, n + 1): + values[:, degree] = 2 * points * values[:, degree - 1] - values[:, degree - 2] + return values + + +def bernstein_min(coefficients, lo, hi, degree): + length = hi - lo + reparameterized = [F(0)] * (degree + 1) + for i, coefficient in enumerate(coefficients): + for power in range(i + 1): + reparameterized[power] += ( + coefficient * comb(i, power) * lo ** (i - power) * length ** power + ) + return min( + sum( + F(comb(k, i), comb(degree, i)) * reparameterized[i] + for i in range(k + 1) + ) + for k in range(degree + 1) + ) + + +def to_x_monomials(rational_coefficients, chebyshev): + coefficients = [F(0)] * (N + 1) + for j in range(N + 1): + for k, coefficient in enumerate(chebyshev[j]): + for i in range(k + 1): + coefficients[i] += ( + rational_coefficients[j] + * coefficient + * comb(k, i) + * F(2, B) ** i + * (-1) ** (k - i) + ) + return coefficients + + +def certificate_gap(coefficients, lo, hi, subdivisions): + return min( + bernstein_min( + coefficients, + lo + (hi - lo) * F(i, subdivisions), + lo + (hi - lo) * F(i + 1, subdivisions), + N, + ) + for i in range(subdivisions) + ) + + +def main(): + moments = {int(k): F(v) for k, v in json.loads(Path("moments_d128_w31.json").read_text()).items()} + chebyshev = chebyshev_monomials(N) + ez = [ + sum(comb(k, j) * F(2, B) ** j * (-1) ** (k - j) * moments[j] for j in range(k + 1)) + for k in range(N + 1) + ] + objective_exact = [ + sum(chebyshev[j][k] * ez[k] for k in range(len(chebyshev[j]))) + for j in range(N + 1) + ] + objective = np.array([float(value) for value in objective_exact]) + + threshold = 2 * GAMMA * GAMMA / B - 1 + nonnegative_points = set(np.linspace(-1, 1, 600)) + tail_points = set(np.linspace(threshold, 1, 600)) + result = None + for iteration in range(100): + points0 = np.array(sorted(nonnegative_points)) + points1 = np.array(sorted(tail_points)) + matrix0 = chebyshev_values(points0, N) + matrix1 = chebyshev_values(points1, N) + result = linprog( + objective, + A_ub=np.vstack([-matrix0, -matrix1]), + b_ub=np.concatenate([np.zeros(len(points0)), -np.ones(len(points1))]), + bounds=[(-100.0, 100.0)] * (N + 1), + method="highs", + ) + if not result.success: + raise RuntimeError(f"iteration {iteration}: {result.message}") + derivative_roots = np.polynomial.Chebyshev(result.x).deriv().roots() + real_roots = [float(root.real) for root in derivative_roots if abs(root.imag) < 1e-8] + candidates0 = [-1.0, 1.0] + [root for root in real_roots if -1 < root < 1] + candidates1 = [threshold, 1.0] + [root for root in real_roots if threshold < root < 1] + values0 = np.polynomial.chebyshev.chebval(candidates0, result.x) + values1 = np.polynomial.chebyshev.chebval(candidates1, result.x) - 1 + min0 = float(np.min(values0)) + min1 = float(np.min(values1)) + print(f"iteration {iteration + 1}: q={result.fun:.12f}, minima={min0:.3e},{min1:.3e}") + if min0 >= -1e-6 and min1 >= -1e-6: + print(f"exchange iterations: {iteration + 1}; minima {min0:.3e}, {min1:.3e}") + break + nonnegative_points.update(round(value, 12) for value in candidates0) + tail_points.update(round(value, 12) for value in candidates1) + else: + raise RuntimeError("exchange algorithm did not converge") + print(f"numerical optimum: {result.fun:.18f}") + + denominator = 2 ** 60 + rational = [F(round(value * denominator), denominator) for value in result.x] + x_coefficients = to_x_monomials(rational, chebyshev) + subdivisions = 4096 + gap0 = certificate_gap(x_coefficients, F(0), F(B), subdivisions) + minus_one = x_coefficients[:] + minus_one[0] -= 1 + gap1 = certificate_gap(minus_one, F(GAMMA * GAMMA), F(B), subdivisions) + print(f"pre-shift Bernstein gaps: {float(gap0):.12e}, {float(gap1):.12e}") + + shift = max(F(0), -gap0, -gap1) + F(1, 10**10) + rational[0] += shift + x_coefficients[0] += shift + minus_one[0] += shift + gap0 = certificate_gap(x_coefficients, F(0), F(B), subdivisions) + gap1 = certificate_gap(minus_one, F(GAMMA * GAMMA), F(B), subdivisions) + assert gap0 > 0 and gap1 > 0 + + q = sum(rational[j] * objective_exact[j] for j in range(N + 1)) + nraw = comb(D, W) * 2 ** W + p0 = 1 - (D // 2) * q + cutoff = F(1, D // 2) * (1 - F(2**128, nraw)) + print(f"shift: {float(shift):.12e}") + print(f"post-shift Bernstein gaps: {float(gap0):.12e}, {float(gap1):.12e}") + print(f"q: {float(q):.18f}") + print(f"cutoff: {float(cutoff):.18f}") + print(f"p0: {float(p0):.18f}") + print(f"accepted bits: {log2(nraw) + log2(float(p0)):.12f}") + + Path("dual_coefficients.json").write_text( + json.dumps({str(i): f"{v.numerator}/{v.denominator}" for i, v in enumerate(rational)}, indent=2) + "\n" + ) + Path("dual_summary.json").write_text( + json.dumps( + { + "degree": N, + "subdivisions": subdivisions, + "q": f"{q.numerator}/{q.denominator}", + "p0": f"{p0.numerator}/{p0.denominator}", + "cutoff": f"{cutoff.numerator}/{cutoff.denominator}", + "gap0": f"{gap0.numerator}/{gap0.denominator}", + "gap1": f"{gap1.numerator}/{gap1.denominator}", + }, + indent=2, + ) + + "\n" + ) + + +if __name__ == "__main__": + main() diff --git a/scripts/operator_norm/d128/validate_moment_generator.py b/scripts/operator_norm/d128/validate_moment_generator.py new file mode 100644 index 000000000..36325e093 --- /dev/null +++ b/scripts/operator_norm/d128/validate_moment_generator.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +import itertools +import json +import subprocess +import tempfile +from fractions import Fraction as F +from math import comb +from pathlib import Path + +PRIME = 2305843009213689601 +PRIMITIVE = 11 + + +def main(): + source_dir = Path(__file__).resolve().parent + with tempfile.TemporaryDirectory(prefix="akita-opnorm-") as build_dir: + executable = Path(build_dir) / "moments_mod" + subprocess.run( + [ + "clang++", + "-O3", + "-std=c++20", + str(source_dir / "moments_mod.cpp"), + "-o", + str(executable), + ], + check=True, + ) + generated_lines = subprocess.run( + [str(executable), str(PRIME), str(PRIMITIVE), "4", "8", "3"], + check=True, + capture_output=True, + text=True, + ).stdout.splitlines()[1:] + d, w, max_moment = 8, 3, 4 + generated = {int(line.split()[0]): int(line.split()[1]) for line in generated_lines} + + alpha = pow(PRIMITIVE, (PRIME - 1) // (2 * d), PRIME) + alpha_inverse = pow(alpha, PRIME - 2, PRIME) + inverse_sign_count = pow(2**w, PRIME - 2, PRIME) + exhaustive = [0] * (max_moment + 1) + for support in itertools.combinations(range(d), w): + support_moments = [0] * (max_moment + 1) + for signs in itertools.product((-1, 1), repeat=w): + value = sum(sign * pow(alpha, position, PRIME) for sign, position in zip(signs, support)) % PRIME + conjugate = sum( + sign * pow(alpha_inverse, position, PRIME) for sign, position in zip(signs, support) + ) % PRIME + squared = value * conjugate % PRIME + power = 1 + for m in range(max_moment + 1): + support_moments[m] = (support_moments[m] + power) % PRIME + power = power * squared % PRIME + for m in range(max_moment + 1): + exhaustive[m] = (exhaustive[m] + support_moments[m] * inverse_sign_count) % PRIME + assert generated == {m: exhaustive[m] for m in range(max_moment + 1)} + print("PASS: modular EGF generator matches exhaustive d=8,w=3 shell through moment 4") + + certificate = json.loads((source_dir / "cert_d128_w31_gamma13.json").read_text()) + moments = { + int(k): F(v) for k, v in certificate["moments_M0_to_M30"].items() + } + expected_second = 2 * 31**2 - 2 * 31 + F(31 * (128 - 31), 128 - 1) + assert moments[2] == expected_second + print(f"PASS: D128 M2 matches independent closed form: {moments[2]}") + + +if __name__ == "__main__": + main() diff --git a/scripts/operator_norm/d64/README.md b/scripts/operator_norm/d64/README.md new file mode 100644 index 000000000..3d1fc5b73 --- /dev/null +++ b/scripts/operator_norm/d64/README.md @@ -0,0 +1,83 @@ +# Operator-norm acceptance certificates + +Machine-checkable certificates for the family-level obligation of Appendix C of +the Akita paper: a rigorous lower bound on the rejection-sampling acceptance +probability + +``` +p = Pr[ Gamma(c) <= Gamma ] +``` + +for a `d = 64` exact-shell challenge family, where `Gamma(c)` is the negacyclic +operator norm (largest singular value of multiplication by `c`). The bound feeds +the accepted-support floor `log2(N_raw * p) >= lambda`. + +The method (paper appendix C, `sec:opnorm-moment-method`) has four steps: + +1. **Exact moments.** `M_m = E[X^m]` of `X = |c(zeta_k)|^2` for one frequency, + exact rationals from the sign-then-support generating function, computed + without floating point via multi-modular CRT over primes `p = 1 mod 2d`. +2. **Dual majorant.** A rational polynomial `Q` with `Q >= 0` on `[0, B]` and + `Q >= 1` on `[Gamma^2, B]` (here `B = ||c||_1^2`) gives + `Pr(X > Gamma^2) <= E[Q(X)] = sum_i q_i M_i`. +3. **Bernstein certificate.** `Q` and `Q - 1` are shown nonnegative on the two + intervals by subdividing into equal rational pieces and checking that every + degree-`n` Bernstein coefficient is `>= 0` (exact). +4. **Union bound.** `p >= 1 - (d/2) * E[Q(X)]`, since there are `d/2` distinct + magnitudes by conjugate symmetry. + +## Files + +- `cert_d64_a31_b11_gamma18.json` — certificate for the `(a, b) = (31, 11)` + shell at cap `Gamma = 18`. Holds the parameters, `N_raw`, the exact moments + `M_0 .. M_30`, the degree-30 dual polynomial `Q(x) = sum_j r_j T_j(2x/B - 1)` + in the shifted-Chebyshev basis (exact rational coefficients `r_j`), the + Bernstein subdivision spec, and the claimed `q1_star`, `p0`. +- `check_cert.py` — self-contained, floating-point-free checker (Python stdlib + only). Binds every moment to eight exact CRT residue files and an independent + ninth-prime residue, recomputes `q1_star`, re-verifies Bernstein + nonnegativity, checks moment admissibility, and confirms + `log2(N_raw * p0) >= lambda`. +- `moments_mod.cpp` and `reconstruct_moments.py` — the exact mixed-shell modular + moment generator and eight-prime CRT reconstruction. The CRT product has 488 + bits against a 432-bit degree-30 numerator bound. +- `validate_moment_generator.py` — compares the generator with exhaustive + enumeration on a small mixed shell and checks the D64 second moment against + an independent closed form. + +## Running + +```bash +python3 check_cert.py # checks the bundled (31,11), Gamma=18 cert +python3 check_cert.py path/to/other_cert.json # checks another certificate +python3 validate_moment_generator.py # optional generator implementation check +``` + +Exit code `0` iff all checks pass. Expected output for the bundled certificate: + +``` +Pr[Gamma(c) <= 18] >= p0 = 0.2349106543 +log2(N_raw * p0) = 128.062439 (>= 128 ? yes) +``` + +## Adding a new parameter setting `(d, a, b, Gamma)` + +1. Compute the exact moments `M_0 .. M_n` of `X = |c(zeta_0)|^2` for the new + family (Step 1). Bumping `n` tightens the bound. +2. Solve the truncated Chebyshev-Markov moment LP for the optimal dual `Q` at + `t = Gamma^2` and emit its exact rational coefficients. +3. Pick a subdivision count large enough that all Bernstein coefficients are + `>= 0` (Step 3). +4. Write a JSON with the same schema and run `check_cert.py` on it. + +### Notes and limits + +- The normal checker does not compile the generator. It verifies that all + supplied exact moments match the eight saved reconstruction residues and the + independent ninth-prime residue. Run `validate_moment_generator.py` when + changing the generator itself. +- The union bound can certify no floor above `1 - (d/2) * Pr(X > Gamma^2)`. When + `(d/2) * Pr(X > Gamma^2) >= 1` the union bound is vacuous and a second-order + Hunter-Worsley refinement (subtracting certified lower bounds on adjacent + joint exceedances) is needed. For `(31, 11)` this rules out `Gamma <= 16` via + this method; `Gamma = 18` clears `lambda = 128` first-order. diff --git a/scripts/operator_norm/d64/cert_d64_a31_b11_gamma18.json b/scripts/operator_norm/d64/cert_d64_a31_b11_gamma18.json new file mode 100644 index 000000000..80343ae71 --- /dev/null +++ b/scripts/operator_norm/d64/cert_d64_a31_b11_gamma18.json @@ -0,0 +1,123 @@ +{ + "description": "Certified lower bound on Pr[Gamma(c) <= Gamma] for the d=64 exact-shell challenge family, via exact spectral moments, a dual-polynomial marginal tail bound, and a union bound over the d/2 distinct frequencies. See appendix C (sec:opnorm-moment-method, sec:opnorm-worked) of the Akita paper.", + "method": "moment-LP union; Lemma (dual moment bound) + Lemma (Bernstein certificate) + Theorem (certified acceptance floor)", + "params": { + "d": 64, + "a_mag1": 31, + "b_mag2": 11, + "w_nonzero": 42, + "l1_norm": 53, + "l2_sq": 75, + "support_cap_B": 2809, + "Gamma": 18, + "threshold_Gamma_sq": 324, + "lambda_bits": 128, + "num_distinct_freqs": 32 + }, + "N_raw": "1512629743948280609404551579217617223680", + "moments_M0_to_M30": { + "0": "1/1", + "1": "75/1", + "2": "10957/1", + "3": "16374625/7", + "4": "422437319411/651", + "5": "47597034336715/217", + "6": "492166561885300109/5673", + "7": "73844463895139161165/1891", + "8": "37066649019311454395443/1891", + "9": "143018804496681583223310391/13237", + "10": "15138355050909436850228115171793/2342949", + "11": "3242317246707156980863845541726145/780983", + "12": "193199056239031520127827238226368108505/67945521", + "13": "20016737518119337397948995230463412222437/9706503", + "14": "96814513684428217345262683529132617603157635/61474519", + "15": "542386988168572635595830042784870239282081372575/430321633", + "16": "453053073465591095111922049562143618692811002488769/430321633", + "17": "20713366671919761219173020016378424367590525353453673/22648507", + "18": "1063249456624634004173325750781889486238935367345384995879/1290964899", + "19": "2480997074271719954409855334827549986054312289060731585579/3235501", + "20": "16675477897874032108397165879933903459211857048701744166691907/22648507", + "21": "270111791538810299093369551795209251143559725519897534750320101/371287", + "22": "886207465702409636793885333932726376273371886335740823055553609767155/1200370871", + "23": "922036122379021074607689471937214952729907012015619299761291477208754009/1200370871", + "24": "140280787387736552945445296854036194355756473979493988214135424945090585505/171481553", + "25": "60506183917606209204355745868863478220370380431104567329569916241944673722795/67945521", + "26": "22568713683935220354461614117836488555717634292053641030241902264155241225811404257/22807046549", + "27": "3652827572235445621806183229404955412415578070139623976320767731440222865070252060405/3258149507", + "28": "88514753852777982000831837883813147124405422450621829856668285589233774861195908363261111/68421139647", + "29": "38531271090257537834726393027999780707034653347299421529549386004590373901397227519422213/25369351", + "30": "72700103689138751217917917270331468295683002623666512343209629766613791320704231072618919535063/40108943931" + }, + "dual_poly": { + "basis": "shifted_Chebyshev", + "def": "Q(x)=sum_j r_j * T_j(2x/B - 1)", + "degree": 30, + "coeffs_r0_to_r30": { + "0": "4887960693640667787/53687091200000", + "1": "5592691079174171/68719476736", + "2": "-4474975820221405/68719476736", + "3": "-4294555265913667/68719476736", + "4": "1590246266689905/137438953472", + "5": "4172922631280839/2199023255552", + "6": "-5505487904258495/137438953472", + "7": "-1668464910867693/549755813888", + "8": "7162492740494733/137438953472", + "9": "7532400948780151/274877906944", + "10": "-5034614657258919/274877906944", + "11": "7698198877086597/35184372088832", + "12": "7716746045513427/274877906944", + "13": "-5620840409912367/1099511627776", + "14": "-2793575826404055/68719476736", + "15": "-5843089183418385/549755813888", + "16": "8415232010007969/274877906944", + "17": "8768550529049001/549755813888", + "18": "-5958868778057699/549755813888", + "19": "796698554860231/68719476736", + "20": "2993392950400403/68719476736", + "21": "2404033381200641/137438953472", + "22": "-5847249597260941/137438953472", + "23": "-4109648333002123/68719476736", + "24": "-1247178007275981/68719476736", + "25": "64459631404545/2147483648", + "26": "5935193666253689/137438953472", + "27": "7815017674872303/274877906944", + "28": "3036796981550909/274877906944", + "29": "2712193444462239/1099511627776", + "30": "8707608558650555/35184372088832" + } + }, + "bernstein_certificate": { + "num_subintervals": 80, + "nonneg_interval_for_Q": [ + 0, + 2809 + ], + "ge1_interval_for_Q_minus_1": [ + 324, + 2809 + ], + "note": "subdivide each interval into 80 equal rational pieces; all degree-30 Bernstein coeffs are >= 0" + }, + "moment_generation": { + "algorithm": "exact truncated mixed-shell bivariate EGF over finite-field primitive 128th roots, eight-prime CRT plus independent ninth-prime check", + "reconstruction_primes": [ + 2305843009213689601, + 2305843009213689089, + 2305843009213687297, + 2305843009213683713, + 2305843009213682689, + 2305843009213675777, + 2305843009213673729, + 2305843009213666049 + ], + "independent_check_prime": 2305843009213663489, + "a_priori_numerator_bound": "C(64,42)*C(42,11)*2809^m for moment m" + }, + "claimed": { + "q1_star": "1286602795927585610752443639335413812332933872589480200164233491727667403670823633395549125177879378762065448730043705701146808743/53812394201944403884711649880411630148936600336723969032301309746080890200397866702061105381913567531974807178729841624927436800000", + "q1_star_decimal": 0.02390904205264104, + "p0": "395034522883177010644795419427449629821334887933143832095182437837360415091609701043860418006919606612147275605263845077835591257/1681637318810762621397239058762863442154268760522624032259415929565027818762433334439409543184798985374212724335307550778982400000", + "p0_decimal": 0.23491065431548674, + "cutoff_q1_for_floor": "260313410166932911669319/10747880764571111522830560" + } +} diff --git a/scripts/operator_norm/d64/check_cert.py b/scripts/operator_norm/d64/check_cert.py new file mode 100644 index 000000000..cbca4d64a --- /dev/null +++ b/scripts/operator_norm/d64/check_cert.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +"""Exact, floating-point-free checker for an operator-norm acceptance certificate. + +Validates a certificate of the form produced for Appendix C of the Akita paper +(sec:opnorm-moment-method / sec:opnorm-worked): a lower bound on + p = Pr[ Gamma(c) <= Gamma ] +for a d=64 exact-shell challenge family, via exact spectral moments, a +dual-polynomial marginal tail bound, and a union bound over the d/2 distinct +frequencies. + +Every load-bearing check uses exact rational arithmetic (fractions.Fraction); +floating point appears only in the final log2 comparison, which clears its +threshold by a wide margin, and in human-readable printouts. + +Usage: + python3 check_cert.py [cert.json] +Exit code 0 iff all checks pass. +""" +import json +import math +import sys +from fractions import Fraction as F +from math import comb +from pathlib import Path + + +def load(path): + with open(path) as f: + return json.load(f) + + +def frac(s): + return F(s) + + +def load_residues(path): + return { + int(line.split()[0]): int(line.split()[1]) + for line in path.read_text().splitlines()[1:] + } + + +def cheb_monomial_coeffs(n): + """Integer monomial coefficients of T_0..T_n (Chebyshev, first kind).""" + T = [[F(1)], [F(0), F(1)]] + for k in range(2, n + 1): + prev, prev2 = T[k - 1], T[k - 2] + cur = [F(0)] * (k + 1) + for i, c in enumerate(prev): + cur[i + 1] += 2 * c + for i, c in enumerate(prev2): + cur[i] -= c + T.append(cur) + return T + + +def is_pos_def(mat): + """Exact symmetric LDL; returns (all_pivots_positive, min_pivot).""" + n = len(mat) + A = [row[:] for row in mat] + pivots = [] + for k in range(n): + d = A[k][k] + pivots.append(d) + if d <= 0: + return False, d + for i in range(k + 1, n): + f = A[i][k] / d + for j in range(k, n): + A[i][j] -= f * A[k][j] + return True, min(pivots) + + +def bernstein_min_on(coeffs_x, lo, hi, n): + """Minimum degree-n Bernstein coefficient of poly (x-monomial coeffs) on [lo,hi].""" + L = hi - lo + # reparameterize x = lo + L*t, get t-monomial coeffs d_i + d = [F(0)] * (n + 1) + for i in range(n + 1): + ci = coeffs_x[i] + if ci == 0: + continue + loi = [F(1)] + # binomial expansion (lo + L t)^i + for s in range(i + 1): + d[s] += ci * comb(i, s) * (lo ** (i - s)) * (L ** s) + mn = None + for k in range(n + 1): + bk = sum(comb(k, i) * d[i] / comb(n, i) for i in range(k + 1)) + if mn is None or bk < mn: + mn = bk + return mn + + +def main(): + path = sys.argv[1] if len(sys.argv) > 1 else ( + __file__.rsplit("/", 1)[0] + "/cert_d64_a31_b11_gamma18.json") + cert = load(path) + P = cert["params"] + d = P["d"] + a = P["a_mag1"] + b = P["b_mag2"] + w = P["w_nonzero"] + B = P["support_cap_B"] + Gamma = P["Gamma"] + g2 = P["threshold_Gamma_sq"] + lam = P["lambda_bits"] + nfreq = P["num_distinct_freqs"] + + ok = True + + def check(name, cond, detail=""): + nonlocal ok + ok = ok and cond + print(f" [{'PASS' if cond else 'FAIL'}] {name}{(' -- ' + detail) if detail else ''}") + + print(f"Checking {path}") + print(f"family d={d}, (a,b)=({a},{b}), B={B}, Gamma={Gamma}, lambda={lam}, freqs={nfreq}") + + # ---- structural params ---- + check("l1_norm = a + 2b", P["l1_norm"] == a + 2 * b, f"{P['l1_norm']}") + check("support cap B = l1^2", B == P["l1_norm"] ** 2) + check("threshold = Gamma^2", g2 == Gamma * Gamma) + Nraw = comb(d, w) * comb(w, b) * (2 ** w) + check("N_raw = C(d,w) C(w,b) 2^w", str(Nraw) == cert["N_raw"], cert["N_raw"]) + + # ---- moments ---- + Mr = cert["moments_M0_to_M30"] + N = max(int(k) for k in Mr) + M = {int(k): frac(v) for k, v in Mr.items()} + check("M0 = 1 and M1 = l2_sq (spectral mean)", + M[0] == 1 and M[1] == P["l2_sq"], f"M1={M[1]}") + fourth_power_sum = a + 16 * b + expected_M2 = (2 * P["l2_sq"] ** 2 - 2 * fourth_power_sum + + F(d * fourth_power_sum - P["l2_sq"] ** 2, d - 1)) + check("M2 matches independent mixed-shell closed form", + M[2] == expected_M2, f"M2={M[2]}") + + # Bind the supplied moment vector to the exact mixed-shell generator. Eight + # primes uniquely reconstruct every nonnegative numerator under the stated + # family bound; a ninth prime is reserved for an independent residue check. + generation = cert["moment_generation"] + reconstruction_primes = generation["reconstruction_primes"] + check_prime = generation["independent_check_prime"] + support_count = comb(d, w) * comb(w, b) + modulus_product = math.prod(reconstruction_primes) + check("CRT modulus exceeds the degree-30 a priori numerator bound", + modulus_product > support_count * (B ** N), + f"{modulus_product.bit_length()} > {(support_count * B ** N).bit_length()} bits") + residue_ok = True + certificate_directory = Path(path).resolve().parent + for prime in reconstruction_primes + [check_prime]: + residue_path = certificate_directory / f"moments_{prime}.txt" + if not residue_path.exists(): + residue_ok = False + break + residues = load_residues(residue_path) + for moment in range(N + 1): + numerator_sum = M[moment] * support_count + if (numerator_sum.denominator != 1 or + numerator_sum.numerator % prime != residues.get(moment)): + residue_ok = False + break + check("all moments match eight CRT generator outputs and the ninth check prime", + residue_ok) + + # moment admissibility on [0,B]: Hankel + localizers PSD + half = N // 2 + H = [[M[i + j] for j in range(half + 1)] for i in range(half + 1)] + Hx = [[M[i + j + 1] for j in range(half)] for i in range(half)] + HB = [[B * M[i + j] - M[i + j + 1] for j in range(half)] for i in range(half)] + for nm, mat in [("Hankel [M_{i+j}] PSD", H), + ("x>=0 localizer PSD", Hx), + ("B-x>=0 localizer PSD", HB)]: + pd, mn = is_pos_def(mat) + check(f"moment admissibility: {nm}", pd, f"min pivot ~ {float(mn):.3e}") + + # ---- dual polynomial ---- + R = cert["dual_poly"]["coeffs_r0_to_r30"] + r = {int(k): frac(v) for k, v in R.items()} + Tc = cheb_monomial_coeffs(N) + + # E[Z^k], Z = 2X/B - 1 + EZ = [sum(comb(k, j) * F(2, B) ** j * F((-1) ** (k - j)) * M[j] for j in range(k + 1)) + for k in range(N + 1)] + ETj = [sum(Tc[j][k] * EZ[k] for k in range(len(Tc[j]))) for j in range(N + 1)] + q1 = sum(r[j] * ETj[j] for j in range(N + 1)) + p0 = 1 - nfreq * q1 + + check("q1_star matches claimed (exact)", q1 == frac(cert["claimed"]["q1_star"]), + f"{float(q1):.18f}") + check("p0 matches claimed (exact)", p0 == frac(cert["claimed"]["p0"]), + f"{float(p0):.18f}") + cutoff = F(1, nfreq) * (1 - F(2 ** lam, Nraw)) + check("q1_star < per-frequency floor cutoff", q1 < cutoff, + f"q1={float(q1):.6f} < cutoff={float(cutoff):.6f}") + + # ---- Bernstein nonnegativity (exact) ---- + # Q in x-monomial basis + xc = [F(0)] * (N + 1) + for j in range(N + 1): + for k in range(len(Tc[j])): + ck = Tc[j][k] + if ck == 0: + continue + for i in range(k + 1): + xc[i] += r[j] * ck * comb(k, i) * F(2, B) ** i * F((-1) ** (k - i)) + + bc = cert["bernstein_certificate"] + nsub = bc["num_subintervals"] + + lo0, hi0 = bc["nonneg_interval_for_Q"] + g0 = None + for i in range(nsub): + lo = F(hi0 - lo0) * F(i, nsub) + lo0 + hi = F(hi0 - lo0) * F(i + 1, nsub) + lo0 + mn = bernstein_min_on(xc, lo, hi, N) + g0 = mn if g0 is None or mn < g0 else g0 + check(f"Q >= 0 on {bc['nonneg_interval_for_Q']} ({nsub} subintervals)", + g0 >= 0, f"min Bernstein coeff = {float(g0):.6e}") + + lo1, hi1 = bc["ge1_interval_for_Q_minus_1"] + xc1 = xc[:] + xc1[0] -= 1 + g1 = None + for i in range(nsub): + lo = F(hi1 - lo1) * F(i, nsub) + lo1 + hi = F(hi1 - lo1) * F(i + 1, nsub) + lo1 + mn = bernstein_min_on(xc1, lo, hi, N) + g1 = mn if g1 is None or mn < g1 else g1 + check(f"Q-1 >= 0 on {bc['ge1_interval_for_Q_minus_1']} ({nsub} subintervals)", + g1 >= 0, f"min Bernstein coeff = {float(g1):.6e}") + + # ---- support floor ---- + bits = math.log2(Nraw) + (math.log2(p0.numerator) - math.log2(p0.denominator)) + check(f"log2(N_raw * p0) >= {lam}", bits >= lam, f"{bits:.6f}") + + print() + print(f"RESULT: {'ALL CHECKS PASS' if ok else 'FAILURE'}") + print(f" Pr[Gamma(c) <= {Gamma}] >= p0 = {float(p0):.10f}") + print(f" log2(N_raw * p0) = {bits:.6f} (>= {lam} ? {'yes' if bits >= lam else 'no'})") + sys.exit(0 if ok else 1) + + +if __name__ == "__main__": + main() diff --git a/scripts/operator_norm/d64/moments_2305843009213663489.txt b/scripts/operator_norm/d64/moments_2305843009213663489.txt new file mode 100644 index 000000000..3b47fea60 --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213663489.txt @@ -0,0 +1,32 @@ +prime 2305843009213663489 root 2049015484468238033 +0 1462850932725194808 +1 1339198521347426617 +2 542912825784599217 +3 1791765379427705644 +4 280932395431095986 +5 1443226382088378645 +6 1492518837891038277 +7 892238312945105269 +8 412865468291276024 +9 1790701273535449010 +10 356023797018921081 +11 2212225145555736963 +12 384575132622438103 +13 201022537245153493 +14 729958580545736954 +15 1641168002882199417 +16 1899760343022938624 +17 1569441812176022199 +18 305243678423077858 +19 455877477257965160 +20 1087558042535695501 +21 893481076219167921 +22 2070218962525875788 +23 2064443399687165142 +24 604707367893198429 +25 1968349999530732635 +26 2088105886639600279 +27 136957292590932792 +28 787396653340149289 +29 856873630530791187 +30 1944402471902805408 diff --git a/scripts/operator_norm/d64/moments_2305843009213666049.txt b/scripts/operator_norm/d64/moments_2305843009213666049.txt new file mode 100644 index 000000000..e48c39e4b --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213666049.txt @@ -0,0 +1,32 @@ +prime 2305843009213666049 root 1277738329667760208 +0 1462850550883766328 +1 1339169883240170297 +2 538728989234949297 +3 898549632653679404 +4 1533067754201605918 +5 726187479715135223 +6 2015095595437205152 +7 1030576109588364676 +8 202782877391708637 +9 1990306714673434644 +10 1503545742545011699 +11 173314573552617060 +12 1186293689930000467 +13 553833899845532188 +14 1779611460756382110 +15 2039100853507611290 +16 1259704979122357592 +17 72958426602996417 +18 612063631584682859 +19 44393807184151964 +20 2227501226810338275 +21 2031505460512094719 +22 73897556444064857 +23 1680002586925197198 +24 987915384289691690 +25 1896392227477312249 +26 2141427599639970112 +27 864461203509154116 +28 333389978925293143 +29 644345130305398661 +30 1755898177252555365 diff --git a/scripts/operator_norm/d64/moments_2305843009213673729.txt b/scripts/operator_norm/d64/moments_2305843009213673729.txt new file mode 100644 index 000000000..00ee98747 --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213673729.txt @@ -0,0 +1,32 @@ +prime 2305843009213673729 root 675903313670637679 +0 1462849405359480888 +1 1339083968918401337 +2 526177479585999537 +3 524745401545274413 +4 677787812089106016 +5 880913782924890526 +6 1276983300202601648 +7 1445788155175195057 +8 1978094451830684045 +9 2212861378853601570 +10 2142129403061550769 +11 314201924731301073 +12 1901536438893165138 +13 776630945133734363 +14 403936817851394811 +15 2268285694481760116 +16 1522216630833204912 +17 167085830309858102 +18 838724526060677427 +19 1525428753767614277 +20 848522408026100834 +21 770706513448528198 +22 1540829286344233932 +23 1903257689090530152 +24 1621283124397485953 +25 804958136816062201 +26 1032759707437946782 +27 287349070280276744 +28 2293274747217630829 +29 969689142031681893 +30 1855886461078545474 diff --git a/scripts/operator_norm/d64/moments_2305843009213675777.txt b/scripts/operator_norm/d64/moments_2305843009213675777.txt new file mode 100644 index 000000000..52c2bebf1 --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213675777.txt @@ -0,0 +1,32 @@ +prime 2305843009213675777 root 1909838447626287997 +0 1462849099886338104 +1 1339061058432596281 +2 522830410346279601 +3 2116015813339731246 +4 757158895421764790 +5 1229619865291990304 +6 1695044935736629292 +7 634224489745999395 +8 478375069303308714 +9 1439019906013968330 +10 495271583463379485 +11 2029269073922843200 +12 3930069953748231 +13 149017380807722412 +14 2278917992157998394 +15 586318076975747159 +16 759652720101655888 +17 850725505325426551 +18 1341179010478639484 +19 703867302490458101 +20 1874501972346287531 +21 2062471422141367480 +22 728239247609286454 +23 865180502127352671 +24 1594212767607303856 +25 754802400181159434 +26 708673898845165700 +27 629296380417381206 +28 1935366714420366711 +29 1004554443778565290 +30 98449445715073981 diff --git a/scripts/operator_norm/d64/moments_2305843009213682689.txt b/scripts/operator_norm/d64/moments_2305843009213682689.txt new file mode 100644 index 000000000..58cc18272 --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213682689.txt @@ -0,0 +1,32 @@ +prime 2305843009213682689 root 1409443925573520377 +0 1462848068914481208 +1 1338983735543004217 +2 511534051662224817 +3 2010176306263556911 +4 448575549368668120 +5 677120637249403958 +6 1953081798612829806 +7 777657321769483877 +8 395265163967627566 +9 606257586825354543 +10 2182946816122258259 +11 524527560367960730 +12 252540658898956238 +13 1304338673673216049 +14 1956338153574487855 +15 1392085495809792269 +16 680439945161537598 +17 1996306483269086693 +18 1886979672533600025 +19 2036043265640857176 +20 1004281450056261463 +21 68694673015817946 +22 1234645939266940390 +23 1687073227646459659 +24 533567627318007275 +25 207299149328721146 +26 1064457005201732639 +27 1671921305054525837 +28 1469363074685174697 +29 2101449835072979249 +30 1454021156169492061 diff --git a/scripts/operator_norm/d64/moments_2305843009213683713.txt b/scripts/operator_norm/d64/moments_2305843009213683713.txt new file mode 100644 index 000000000..b27a5251e --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213683713.txt @@ -0,0 +1,32 @@ +prime 2305843009213683713 root 2264458105055299262 +0 1462847916177909816 +1 1338972280300101689 +2 509860517042364849 +3 1652890007553949487 +4 488261091035723779 +5 851473678678435063 +6 2162112713474768428 +7 371919193299435422 +8 820264571654059709 +9 782195327953756286 +10 1480511590432535241 +11 1236880875923924636 +12 961052083921718687 +13 1464796370554815596 +14 1473732821315276602 +15 1236068617971447147 +16 255841904055075715 +17 1408046319211267210 +18 1140269681247070758 +19 220130045878364505 +20 1719690722615820262 +21 1334986356135456936 +22 153420837922122000 +23 1951049197029868316 +24 252144427300852752 +25 1089246296826382016 +26 129797205037722622 +27 2044423414248076258 +28 710773529841880947 +29 1973414524378893135 +30 1163370710309808300 diff --git a/scripts/operator_norm/d64/moments_2305843009213687297.txt b/scripts/operator_norm/d64/moments_2305843009213687297.txt new file mode 100644 index 000000000..e1284f7a9 --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213687297.txt @@ -0,0 +1,32 @@ +prime 2305843009213687297 root 357304057573843661 +0 1462847381599909944 +1 1338932186949942841 +2 504003145872854961 +3 402387962070323503 +4 1780081991477955738 +5 308787819307523994 +6 587877998959385924 +7 104798965949087206 +8 1175781424913772593 +9 258274689225518093 +10 185592730396963125 +11 1862154034761633077 +12 2140498286224808886 +13 419224955348957908 +14 152755775046594067 +15 1034583933626567765 +16 2163738736758811950 +17 1591749200133826491 +18 521336605979250245 +19 557367899720332374 +20 1835275342901661052 +21 1640749723157046072 +22 1563095749453593105 +23 1672014472301661807 +24 428408911940298310 +25 2084666619055240405 +26 1245264762052955775 +27 904961801602440621 +28 407430028694369081 +29 204715026534015463 +30 2264608118381540867 diff --git a/scripts/operator_norm/d64/moments_2305843009213689089.txt b/scripts/operator_norm/d64/moments_2305843009213689089.txt new file mode 100644 index 000000000..d6c5245ae --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213689089.txt @@ -0,0 +1,32 @@ +prime 2305843009213689089 root 1904277408380145156 +0 1462847114310910008 +1 1338912140274863417 +2 501074460288100017 +3 2082979948542199600 +4 1273070937092633061 +5 1190366394365600492 +6 2106603704979600849 +7 2277106196805590539 +8 1365755102939320043 +9 964793240659115730 +10 24748967029296537 +11 1085145263728222380 +12 1491298634192045508 +13 1549427939672706296 +14 153556457484421993 +15 1783264099298948847 +16 1373243620261504490 +17 531276273573774820 +18 516642363654089494 +19 536138230949424536 +20 608107422310645317 +21 1550046377111775944 +22 1418654483946932041 +23 1566245721475080392 +24 159037941693377165 +25 894625534059376380 +26 1251350305450251466 +27 791164235408734790 +28 2302075653817155893 +29 821788803574096052 +30 1622125220353719479 diff --git a/scripts/operator_norm/d64/moments_2305843009213689601.txt b/scripts/operator_norm/d64/moments_2305843009213689601.txt new file mode 100644 index 000000000..63680f891 --- /dev/null +++ b/scripts/operator_norm/d64/moments_2305843009213689601.txt @@ -0,0 +1,32 @@ +prime 2305843009213689601 root 420359399294971515 +0 1462847037942624312 +1 1338906412653412153 +2 500237692978170033 +3 1904336799187396400 +4 139992203319580410 +5 124621410562537292 +6 2211119197717815472 +7 921331520416285351 +8 433310609209612466 +9 1991115242354257016 +10 556017424458730976 +11 1388529083976632683 +12 1295281700144810106 +13 850839498561959126 +14 116125208375600234 +15 2195876912858385870 +16 1464333447449173830 +17 1051860154851751990 +18 1765988959574015459 +19 349971385534671211 +20 2262795037349612998 +21 649275618111471985 +22 1412332586094462945 +23 239709367338797165 +24 1536658758155820439 +25 1079033121742043237 +26 2149026000650343316 +27 1684944386074814528 +28 244965991619914770 +29 2179689744361217999 +30 1669353965426972556 diff --git a/scripts/operator_norm/d64/moments_mod.cpp b/scripts/operator_norm/d64/moments_mod.cpp new file mode 100644 index 000000000..32b2d964f --- /dev/null +++ b/scripts/operator_norm/d64/moments_mod.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include + +using u64 = std::uint64_t; +using u128 = unsigned __int128; + +static u64 mod_mul(u64 a, u64 b, u64 p) { + return static_cast((static_cast(a) * b) % p); +} + +static u64 mod_pow(u64 a, u64 e, u64 p) { + u64 result = 1; + while (e != 0) { + if (e & 1) result = mod_mul(result, a, p); + a = mod_mul(a, a, p); + e >>= 1; + } + return result; +} + +static inline void add_assign(u64 &target, u64 value, u64 p) { + const u64 sum = target + value; + target = sum >= p ? sum - p : sum; +} + +int main(int argc, char **argv) { + if (argc != 4 && argc != 7) { + std::cerr << "usage: moments_mod PRIME PRIMITIVE_ROOT MAX_MOMENT [DIMENSION MAG1_COUNT MAG2_COUNT]\n"; + return 2; + } + const u64 mod = std::stoull(argv[1]); + const u64 primitive = std::stoull(argv[2]); + const int max_moment = std::stoi(argv[3]); + const int dimension = argc == 7 ? std::stoi(argv[4]) : 64; + const int mag1_count = argc == 7 ? std::stoi(argv[5]) : 31; + const int mag2_count = argc == 7 ? std::stoi(argv[6]) : 11; + if (dimension <= 0 || mag1_count < 0 || mag2_count < 0 || + mag1_count + mag2_count > dimension || (mod - 1) % (2 * dimension) != 0) { + std::cerr << "invalid dimension, shell counts, or modulus\n"; + return 2; + } + + const int side = max_moment + 1; + const int area = side * side; + const int mag2_stride = area; + const int mag1_stride = (mag2_count + 1) * area; + auto offset = [mag1_stride, mag2_stride, side](int a, int b, int r, int s) { + return a * mag1_stride + b * mag2_stride + r * side + s; + }; + + const u64 root = mod_pow(primitive, (mod - 1) / (2 * dimension), mod); + if (mod_pow(root, 2 * dimension, mod) != 1 || + mod_pow(root, dimension, mod) != mod - 1) { + std::cerr << "supplied generator did not produce a primitive 2d-th root\n"; + return 2; + } + + std::vector factorial(side, 1), inverse_factorial(side, 1); + for (int i = 1; i <= max_moment; ++i) + factorial[i] = mod_mul(factorial[i - 1], i, mod); + inverse_factorial[max_moment] = mod_pow(factorial[max_moment], mod - 2, mod); + for (int i = max_moment; i > 0; --i) + inverse_factorial[i - 1] = mod_mul(inverse_factorial[i], i, mod); + + std::vector dp((mag1_count + 1) * (mag2_count + 1) * area, 0); + std::vector even(area), odd(area), convolution(area); + dp[offset(0, 0, 0, 0)] = 1; + + auto convolve_add = [&](int source, int destination, + const std::vector &positive, + const std::vector &negative) { + std::fill(even.begin(), even.end(), 0); + std::fill(odd.begin(), odd.end(), 0); + std::fill(convolution.begin(), convolution.end(), 0); + for (int s = 0; s <= max_moment; ++s) { + for (int r = 0; r <= max_moment; ++r) { + u64 even_sum = 0; + u64 odd_sum = 0; + for (int i = 0; i <= r; i += 2) + add_assign(even_sum, + mod_mul(dp[source + (r - i) * side + s], positive[i], mod), + mod); + for (int i = 1; i <= r; i += 2) + add_assign(odd_sum, + mod_mul(dp[source + (r - i) * side + s], positive[i], mod), + mod); + even[r * side + s] = even_sum; + odd[r * side + s] = odd_sum; + } + } + for (int r = 0; r <= max_moment; ++r) { + for (int s = 0; s <= max_moment; ++s) { + u64 sum = 0; + for (int j = 0; j <= s; j += 2) + add_assign(sum, + mod_mul(even[r * side + s - j], negative[j], mod), mod); + for (int j = 1; j <= s; j += 2) + add_assign(sum, + mod_mul(odd[r * side + s - j], negative[j], mod), mod); + convolution[r * side + s] = sum; + } + } + for (int index = 0; index < area; ++index) + add_assign(dp[destination + index], convolution[index], mod); + }; + + const auto started = std::chrono::steady_clock::now(); + for (int position = 0; position < dimension; ++position) { + const u64 position_root = mod_pow(root, position, mod); + const u64 position_root_inverse = mod_pow(position_root, mod - 2, mod); + std::vector positive1(side), negative1(side), positive2(side), negative2(side); + positive1[0] = negative1[0] = positive2[0] = negative2[0] = 1; + for (int i = 1; i <= max_moment; ++i) { + positive1[i] = mod_mul(positive1[i - 1], position_root, mod); + negative1[i] = mod_mul(negative1[i - 1], position_root_inverse, mod); + positive2[i] = mod_mul(positive2[i - 1], mod_mul(position_root, 2, mod), mod); + negative2[i] = mod_mul(negative2[i - 1], mod_mul(position_root_inverse, 2, mod), mod); + } + for (int i = 0; i <= max_moment; ++i) { + positive1[i] = mod_mul(positive1[i], inverse_factorial[i], mod); + negative1[i] = mod_mul(negative1[i], inverse_factorial[i], mod); + positive2[i] = mod_mul(positive2[i], inverse_factorial[i], mod); + negative2[i] = mod_mul(negative2[i], inverse_factorial[i], mod); + } + + const int max_a = std::min(mag1_count, position + 1); + for (int a = max_a; a >= 0; --a) { + const int max_b = std::min(mag2_count, position + 1 - a); + for (int b = max_b; b >= 0; --b) { + if (a + b == 0 || a + b > position + 1) continue; + const int destination = offset(a, b, 0, 0); + if (a > 0) + convolve_add(offset(a - 1, b, 0, 0), destination, positive1, negative1); + if (b > 0) + convolve_add(offset(a, b - 1, 0, 0), destination, positive2, negative2); + } + } + } + + std::cout << "prime " << mod << " root " << root << "\n"; + for (int moment = 0; moment <= max_moment; ++moment) { + u64 residue = dp[offset(mag1_count, mag2_count, moment, moment)]; + residue = mod_mul(residue, factorial[moment], mod); + residue = mod_mul(residue, factorial[moment], mod); + std::cout << moment << " " << residue << "\n"; + } + const double elapsed = std::chrono::duration( + std::chrono::steady_clock::now() - started).count(); + std::cerr << "elapsed_seconds " << elapsed << "\n"; +} diff --git a/scripts/operator_norm/d64/reconstruct_moments.py b/scripts/operator_norm/d64/reconstruct_moments.py new file mode 100644 index 000000000..3d8a07b4c --- /dev/null +++ b/scripts/operator_norm/d64/reconstruct_moments.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""Reconstruct exact D64 mixed-shell moments from modular generator outputs.""" + +import json +from fractions import Fraction +from math import comb +from pathlib import Path + +from sympy.ntheory.modular import crt + +D = 64 +A = 31 +B = 11 +SUPPORT_CAP = (A + 2 * B) ** 2 +RECONSTRUCTION_PRIMES = [ + 2305843009213689601, + 2305843009213689089, + 2305843009213687297, + 2305843009213683713, + 2305843009213682689, + 2305843009213675777, + 2305843009213673729, + 2305843009213666049, +] +CHECK_PRIME = 2305843009213663489 + + +def load_residues(prime): + lines = Path(f"moments_{prime}.txt").read_text().splitlines()[1:] + return {int(line.split()[0]): int(line.split()[1]) for line in lines} + + +def main(): + primes = RECONSTRUCTION_PRIMES + [CHECK_PRIME] + residues = {prime: load_residues(prime) for prime in primes} + support_count = comb(D, A + B) * comb(A + B, B) + modulus_product = 1 + for prime in RECONSTRUCTION_PRIMES: + modulus_product *= prime + + moments = {} + for moment in range(31): + value, modulus = crt( + RECONSTRUCTION_PRIMES, + [residues[prime][moment] for prime in RECONSTRUCTION_PRIMES], + check=True, + ) + value = int(value) + assert int(modulus) == modulus_product + assert value <= support_count * SUPPORT_CAP**moment + assert value % CHECK_PRIME == residues[CHECK_PRIME][moment] + exact = Fraction(value, support_count) + moments[str(moment)] = f"{exact.numerator}/{exact.denominator}" + + Path("moments_d64_a31_b11.json").write_text(json.dumps(moments, indent=2) + "\n") + print(f"eight-prime CRT bits: {modulus_product.bit_length()}") + print(f"largest a priori bound bits: {(support_count * SUPPORT_CAP**30).bit_length()}") + print("independent ninth-prime residue checks: PASS") + + +if __name__ == "__main__": + main() diff --git a/scripts/operator_norm/d64/validate_moment_generator.py b/scripts/operator_norm/d64/validate_moment_generator.py new file mode 100644 index 000000000..841cf785e --- /dev/null +++ b/scripts/operator_norm/d64/validate_moment_generator.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +"""Compare the mixed-shell modular EGF generator with exhaustive enumeration.""" + +import itertools +import json +import subprocess +import tempfile +from fractions import Fraction as F +from pathlib import Path + +PRIME = 2305843009213689601 +PRIMITIVE = 11 +SOURCE_DIRECTORY = Path(__file__).resolve().parent + + +def main(): + with tempfile.TemporaryDirectory(prefix="akita-d64-moments-") as temporary_directory: + executable = str(Path(temporary_directory) / "moments_mod") + subprocess.run( + [ + "clang++", + "-O3", + "-march=native", + "-std=c++20", + str(SOURCE_DIRECTORY / "moments_mod.cpp"), + "-o", + executable, + ], + check=True, + ) + dimension, mag1_count, mag2_count, max_moment = 8, 2, 1, 4 + generated_lines = subprocess.run( + [ + executable, + str(PRIME), + str(PRIMITIVE), + str(max_moment), + str(dimension), + str(mag1_count), + str(mag2_count), + ], + check=True, + capture_output=True, + text=True, + ).stdout.splitlines()[1:] + generated = {int(line.split()[0]): int(line.split()[1]) for line in generated_lines} + + root = pow(PRIMITIVE, (PRIME - 1) // (2 * dimension), PRIME) + root_inverse = pow(root, PRIME - 2, PRIME) + sign_count = 2 ** (mag1_count + mag2_count) + inverse_sign_count = pow(sign_count, PRIME - 2, PRIME) + exhaustive = [0] * (max_moment + 1) + positions = range(dimension) + for mag2_positions in itertools.combinations(positions, mag2_count): + remaining = [position for position in positions if position not in mag2_positions] + for mag1_positions in itertools.combinations(remaining, mag1_count): + weighted_positions = [(position, 1) for position in mag1_positions] + weighted_positions += [(position, 2) for position in mag2_positions] + support_moments = [0] * (max_moment + 1) + for signs in itertools.product((-1, 1), repeat=len(weighted_positions)): + value = sum( + sign * magnitude * pow(root, position, PRIME) + for sign, (position, magnitude) in zip(signs, weighted_positions) + ) % PRIME + conjugate = sum( + sign * magnitude * pow(root_inverse, position, PRIME) + for sign, (position, magnitude) in zip(signs, weighted_positions) + ) % PRIME + squared = value * conjugate % PRIME + power = 1 + for moment in range(max_moment + 1): + support_moments[moment] = (support_moments[moment] + power) % PRIME + power = power * squared % PRIME + for moment in range(max_moment + 1): + exhaustive[moment] = ( + exhaustive[moment] + support_moments[moment] * inverse_sign_count + ) % PRIME + assert generated == {moment: exhaustive[moment] for moment in range(max_moment + 1)} + print("PASS: modular EGF generator matches exhaustive d=8,(a,b)=(2,1) shell through moment 4") + + certificate = json.loads( + (SOURCE_DIRECTORY / "cert_d64_a31_b11_gamma18.json").read_text() + ) + moments = {int(k): F(v) for k, v in certificate["moments_M0_to_M30"].items()} + spectral_mean = 31 + 4 * 11 + fourth_power_sum = 31 + 16 * 11 + expected_second = ( + 2 * spectral_mean**2 + - 2 * fourth_power_sum + + F(64 * fourth_power_sum - spectral_mean**2, 63) + ) + assert moments[2] == expected_second + print(f"PASS: D64 M2 matches independent closed form: {moments[2]}") + + +if __name__ == "__main__": + main() diff --git a/scripts/profile_bench_report.py b/scripts/profile_bench_report.py index db24cbf56..9d2a5b94e 100644 --- a/scripts/profile_bench_report.py +++ b/scripts/profile_bench_report.py @@ -56,6 +56,7 @@ "stage1_sumcheck_bytes", "stage1_interstage_claims_bytes", "stage1_range_image_evaluation_bytes", + "stage1_norm_proof_bytes", "stage2_sumcheck_bytes", "stage3_sumcheck_bytes", "next_w_payload_bytes", @@ -143,6 +144,11 @@ def case_metadata(mode: str) -> CaseMetadata: return CaseMetadata(field_family, workload, workload_label, config) +def quotient_digit_count(metadata: CaseMetadata, log_basis: int) -> int: + field_bits = int(metadata.field_family.removeprefix("fp")) + return (field_bits + log_basis - 1) // log_basis + + def workload_slug(metadata: CaseMetadata, num_polys: int) -> str: if metadata.workload == "onehot" and num_polys > 1: return "onehot-batched" @@ -312,6 +318,15 @@ def parse_kvs(line: str) -> dict[str, str]: return out +def parse_tracing_optional_int(value: str | None) -> int | None: + if value is None or value == "None": + return None + match = re.fullmatch(r"Some\((\d+)\)", value) + if match is None: + raise ValueError(f"invalid tracing optional integer: {value}") + return int(match.group(1)) + + def parse_witness_groups(value: str | None) -> list[dict[str, object]]: if not value: return [] @@ -362,15 +377,6 @@ def planned_current_w_len(kvs: dict[str, str]) -> list[dict[str, object]]: "z_bits_per_coord_packed", ) -TAIL_ENCODING_POLICIES = { - "segment_typed": "non-zk folded terminal (default in profile bench)", - "terminal_response": "non-zk quotient-free terminal response (default in profile bench)", - "packed_digits": "zk-feature folded terminal fallback", - "field_elements": "root-direct cleartext witness", - "none": "root-direct zero-fold (no cleartext tail)", -} - - def ingest_tail_summary_fields(summary: dict[str, object], kvs: dict[str, str]) -> None: if "final_w_encoding" in kvs: summary["tail_encoding"] = kvs["final_w_encoding"] @@ -417,12 +423,13 @@ def render_tail_encoding(current: dict[str, object]) -> None: if encoding is None: return - policy = current.get("tail_policy") - policy_hint = TAIL_ENCODING_POLICIES.get(str(encoding), str(policy or encoding)) - print(f"- Tail encoding: `{encoding}` ({policy_hint})") + print(f"- Tail encoding: `{encoding}`") if encoding == "packed_digits": - if current.get("tail_num_elems") is not None and current.get("tail_bits_per_elem") is not None: + if ( + current.get("tail_num_elems") is not None + and current.get("tail_bits_per_elem") is not None + ): print( f" - Wire: `{fmt_count(float(current['tail_num_elems']))}` logical elements at " f"`{current['tail_bits_per_elem']}` bits for each element (uniform `PackedDigits`)" @@ -443,152 +450,106 @@ def render_tail_encoding(current: dict[str, object]) -> None: "tail_log_basis_inner", current.get("tail_log_basis_open") ) if current.get("tail_num_elems") is not None and terminal_log_basis is not None: - basis_role = "inner" if encoding == "terminal_response" else "D/open" print( - f" - Logical witness: `{fmt_count(float(current['tail_num_elems']))}` elements, " - f"{basis_role} gadget basis width `{terminal_log_basis}` bits, " - "folded-witness (`z`) segment first on the wire" + " - Clear response: " + f"`{fmt_count(float(current['tail_num_elems']))}` coefficients across `z`, `e`, " + f"and `t`. The incoming witness uses a basis width of `{terminal_log_basis}` bits." ) z_prefix = current.get("tail_z_prefix_bytes") z_golomb = current.get("tail_z_golomb_bytes") - z_wire = current.get("tail_z_bytes") - z_field = current.get("tail_z_field_elems") - z_ring = current.get("tail_z_ring_elems") - if z_wire is not None and z_field is not None and z_ring is not None: - prefix_golomb = "" - if z_prefix is not None and z_golomb is not None: - prefix_golomb = ( - f" (length prefix `{fmt_bytes(float(z_prefix))} bytes` + Golomb " - f"`{fmt_bytes(float(z_golomb))} bytes`)" - ) - print( - f" - Folded-witness (`z`) segment: `{fmt_bytes(float(z_wire))} bytes`{prefix_golomb}, " - f"`{fmt_count(float(z_field))}` field coefficients, " - f"`{fmt_count(float(z_ring))}` ring elements" - ) - - for segment_label, bytes_key, field_key, ring_key in ( - ("Opening-digit (`e`)", "tail_e_bytes", "tail_e_field_elems", "tail_e_ring_elems"), + segment_rows = [] + for label, bytes_key, field_key, ring_key, segment_encoding in ( + ( + "Folded response (`z`)", + "tail_z_bytes", + "tail_z_field_elems", + "tail_z_ring_elems", + "Golomb", + ), + ( + "Opening values (`e`)", + "tail_e_bytes", + "tail_e_field_elems", + "tail_e_ring_elems", + "raw field elements", + ), ( - "Inner-commitment (`t`)", + "Inner-commitment values (`t`)", "tail_t_bytes", "tail_t_field_elems", "tail_t_ring_elems", + "raw field elements", ), ): - seg_bytes = current.get(bytes_key) - field_coeffs = current.get(field_key) - ring_elems = current.get(ring_key) - if seg_bytes is None: + if current.get(bytes_key) is None: continue - detail = f"`{fmt_bytes(float(seg_bytes))} bytes`" - if field_coeffs is not None: - detail += f", `{fmt_count(float(field_coeffs))}` field coefficients" - if ring_elems is not None: - detail += f", `{fmt_count(float(ring_elems))}` ring elements" - print(f" - {segment_label} segment: {detail}") - - if all( - current.get(key) is not None - for key in ("tail_z_bytes", "tail_e_bytes", "tail_t_bytes") - ): - wire_total = ( - int(current["tail_z_bytes"]) - + int(current["tail_e_bytes"]) - + int(current["tail_t_bytes"]) + if ( + bytes_key == "tail_z_bytes" + and z_prefix is not None + and z_golomb is not None + ): + segment_encoding = ( + f"{fmt_bytes(float(z_prefix))}-byte length prefix + " + f"{fmt_bytes(float(z_golomb))}-byte Golomb payload" + ) + field_coefficients = current.get(field_key) + ring_elements = current.get(ring_key) + segment_rows.append( + ( + label, + f"{fmt_bytes(float(current[bytes_key]))} bytes", + ( + fmt_count(float(field_coefficients)) + if field_coefficients is not None + else "—" + ), + fmt_count(float(ring_elements)) if ring_elements is not None else "—", + segment_encoding, + ) ) - print(f" - Wire total (z+e+t): `{fmt_bytes(float(wire_total))} bytes`") + if segment_rows: + print() + print("| Segment | Bytes | Field coefficients | Ring elements | Encoding |") + print("| --- | ---: | ---: | ---: | --- |") + for row in segment_rows: + print("| " + " | ".join(row) + " |") z_budget = current.get("tail_z_budget_bytes") - z_slack = current.get("tail_z_slack_bytes") if z_budget is not None and z_golomb is not None: - slack_note = ( - f", slack `{fmt_bytes(float(z_slack))} bytes` under planner upper bound" - if z_slack is not None - else "" - ) + parameter = current.get("z_rice_low_bits_wire") + scheduled_parameter = current.get("z_rice_low_bits_cap") + cap = current.get("z_witness_linf_cap") + details = [] + if parameter is not None: + details.append(f"Golomb parameter `{parameter}`") + if ( + scheduled_parameter is not None + and scheduled_parameter != parameter + ): + details.append(f"scheduled Golomb parameter `{scheduled_parameter}`") + if cap is not None: + details.append(f"coefficient limit `{cap}`") + suffix = f" ({', '.join(details)})" if details else "" print( - f" - Folded-witness Golomb budget: realized `{fmt_bytes(float(z_golomb))} bytes` out of " - f"a scheduled upper bound of `{fmt_bytes(float(z_budget))} bytes`{slack_note}" + f"- Golomb payload: `{fmt_bytes(float(z_golomb))} bytes` out of the scheduled " + f"`{fmt_bytes(float(z_budget))}-byte` budget{suffix}." ) - z_witness_linf_cap = current.get("z_witness_linf_cap") - z_rice_low_bits_wire = current.get("z_rice_low_bits_wire") - z_rice_low_bits_cap = current.get("z_rice_low_bits_cap") - z_field_coeffs = current.get("tail_z_field_elems") or current.get("z_coords") - z_ring_elems = current.get("tail_z_ring_elems") z_bits_golomb = current.get("z_bits_per_coord_golomb") z_bits_packed = current.get("z_bits_per_coord_packed") z_packed_hyp = current.get("z_packed_hypothetical_bytes") - z_savings = current.get("z_golomb_savings_bytes") - if z_witness_linf_cap is not None and z_rice_low_bits_wire is not None and z_field_coeffs is not None: - comparison = "" - if z_bits_golomb is not None and z_bits_packed is not None: - k_note = f"wire Golomb parameter=`{z_rice_low_bits_wire}`" - if z_rice_low_bits_cap is not None: - k_note += f", planner-cap Golomb parameter=`{z_rice_low_bits_cap}`" - comparison = ( - f", `{z_bits_golomb:.2f}` bits for each field coefficient " - f"({k_note}, derived from folded-witness infinity-norm cap " - f"`{z_witness_linf_cap}`) vs " - f"`{z_bits_packed:.2f}` bits for each field coefficient " - "(legacy uniform `PackedDigits` z planes)" - ) - savings_note = "" - if z_packed_hyp is not None and z_golomb is not None and z_savings is not None: - savings_note = ( - f"; hypothetical packed z `{fmt_bytes(float(z_packed_hyp))} bytes`, " - f"savings `{fmt_bytes(float(z_savings))} bytes`" - ) - ring_note = ( - f"`{fmt_count(float(z_ring_elems))}` ring elements, " - if z_ring_elems is not None + if z_bits_golomb is not None and z_bits_packed is not None: + packed_size = ( + f" and `{fmt_bytes(float(z_packed_hyp))} bytes` total" + if z_packed_hyp is not None else "" ) print( - f" - Folded-witness Golomb model: {ring_note}" - f"`{fmt_count(float(z_field_coeffs))}` field coefficients{comparison}{savings_note}" - ) - - -def render_terminal_response_components( - cases: list[dict[str, object]], include_heading: bool = True -) -> None: - rows = [ - case - for case in cases - if case_status(case) == "ok" - and case.get("tail_encoding") in ("segment_typed", "terminal_response") - and all( - case.get(key) is not None - for key in ("tail_z_bytes", "tail_e_bytes", "tail_t_bytes", "tail_bytes") - ) - ] - if not rows: - return - - if include_heading: - print("### Terminal response component breakdown") - print() - print( - "| Workload | Folded response (`z`) | Opening values (`e`) | " - "Inner-commitment values (`t`) | Total terminal response |" - ) - print("| --- | ---: | ---: | ---: | ---: |") - for case in rows: - print( - f"| {md_text(human_case_label(case))} | " - f"{fmt_bytes(float(case['tail_z_bytes']))} bytes | " - f"{fmt_bytes(float(case['tail_e_bytes']))} bytes | " - f"{fmt_bytes(float(case['tail_t_bytes']))} bytes | " - f"{fmt_bytes(float(case['tail_bytes']))} bytes |" + f"- Folded response encoding: `{z_bits_golomb:.2f}` bits per coefficient with " + f"Golomb coding, compared with `{z_bits_packed:.2f}` bits per coefficient" + f"{packed_size} for uniform packed digits." ) - print() - print( - "The `z` column includes its per-segment length prefixes and Golomb payload; `e` and `t` " - "are raw field bytes. These three columns sum exactly to the serialized terminal response." - ) def write_text(path: pathlib.Path, text: str) -> None: @@ -794,6 +755,7 @@ def extract_summary( } planned_levels: dict[int, dict[str, object]] = {} planned_groups: dict[int, list[dict[str, object]]] = {} + terminal_plan: dict[str, object] | None = None proof_levels: dict[int, dict[str, object]] = {} onehot_commit_schedules: list[dict[str, object]] = [] active_verify_mode = "multi threaded" @@ -901,6 +863,9 @@ def extract_summary( summary["extension_root_direct_fallback"] = True elif "planned fold group" in line and kvs.get("label") == mode: level = int(kvs["level"]) + challenge_operator_norm_threshold = parse_tracing_optional_int( + kvs.get("challenge_operator_norm_threshold") + ) planned_groups.setdefault(level, []).append( { "group": kvs["group"], @@ -914,9 +879,21 @@ def extract_summary( "d_a": int(kvs["d_a"]), "d_b": int(kvs["d_b"]), "d_d": int(kvs["d_d"]), + "a_width": int(kvs.get("a_width", "0")), + "b_width": int(kvs.get("b_width", "0")), + "d_width": int(kvs.get("d_width", "0")), "n_a": int(kvs["n_a"]), "n_b": int(kvs["n_b"]), "n_d": int(kvs["n_d"]), + "security_route": ( + "L2" + if parse_tracing_optional_int(kvs.get("response_l2_sq_cap")) + is not None + else "L-infinity" + ), + "response_l2_sq_cap": parse_tracing_optional_int( + kvs.get("response_l2_sq_cap") + ), "log_basis_inner": int(kvs["log_basis_inner"]), "log_basis_outer": int(kvs["log_basis_outer"]), "log_basis_open": int(kvs["log_basis_open"]), @@ -924,7 +901,29 @@ def extract_summary( "num_digits_outer": int(kvs["num_digits_outer"]), "num_digits_open": int(kvs["num_digits_open"]), "num_digits_fold": int(kvs["num_digits_fold"]), + "num_digits_quotient": int( + kvs.get( + "num_digits_quotient", + str( + quotient_digit_count( + metadata, int(kvs["log_basis_open"]) + ) + ), + ) + ), "challenge_l1_mass": int(kvs["challenge_l1_mass"]), + **{ + key: int(kvs[key]) + for key in ("challenge_count_pm1", "challenge_count_pm2") + if key in kvs + }, + **( + { + "challenge_operator_norm_threshold": challenge_operator_norm_threshold + } + if challenge_operator_norm_threshold is not None + else {} + ), "num_live_ring_elements_per_claim": int( kvs["num_live_ring_elements_per_claim"] ), @@ -990,15 +989,41 @@ def extract_summary( block_index_domain_size = int( kvs.get("block_index_domain_size", 1 << block_index_bits) ) + challenge_operator_norm_threshold = parse_tracing_optional_int( + kvs.get("challenge_operator_norm_threshold") + ) planned_levels[level] = { "level": level, "d_a": int(kvs.get("d_a", legacy_d)), "d_b": int(kvs.get("d_b", legacy_d)), "d_d": int(kvs.get("d_d", legacy_d)), + "a_width": int(kvs.get("a_width", "0")), + "b_width": int(kvs.get("b_width", "0")), + "d_width": int(kvs.get("d_width", "0")), "n_a": int(kvs["n_a"]), "n_b": int(kvs["n_b"]), "n_d": int(kvs["n_d"]), + "security_route": ( + "L2" + if parse_tracing_optional_int(kvs.get("response_l2_sq_cap")) is not None + else "L-infinity" + ), + "response_l2_sq_cap": parse_tracing_optional_int( + kvs.get("response_l2_sq_cap") + ), "challenge_l1_mass": int(kvs["challenge_l1_mass"]), + **{ + key: int(kvs[key]) + for key in ("challenge_count_pm1", "challenge_count_pm2") + if key in kvs + }, + **( + { + "challenge_operator_norm_threshold": challenge_operator_norm_threshold + } + if challenge_operator_norm_threshold is not None + else {} + ), "log_basis_inner": int(kvs.get("log_basis_inner") or kvs["log_basis"]), "log_basis_outer": int(kvs.get("log_basis_outer") or kvs["log_basis"]), "log_basis_open": int(kvs.get("log_basis_open") or kvs["log_basis"]), @@ -1012,6 +1037,17 @@ def extract_summary( "num_digits_outer": int(kvs.get("num_digits_outer") or kvs["delta_open"]), "num_digits_open": int(kvs.get("num_digits_open") or kvs["delta_open"]), "delta_fold": int(kvs["delta_fold"]), + "num_digits_quotient": int( + kvs.get( + "num_digits_quotient", + str( + quotient_digit_count( + metadata, + int(kvs.get("log_basis_open") or kvs["log_basis"]), + ) + ), + ) + ), "input_witness_len": input_witness_len, "current_w_len": planned_current_w_len(kvs), "next_w_len": output_witness_len, @@ -1026,6 +1062,62 @@ def extract_summary( # and is display-only (no correctness comparison), so keep it optional. if "level_bytes" in kvs: planned_levels[level]["level_bytes"] = int(kvs["level_bytes"]) + elif "planned terminal state" in line and kvs.get("label") == mode: + terminal_plan = { + "level": int(kvs["level"]) if "level" in kvs else None, + "input_witness_len": int( + kvs.get("input_witness_len") or kvs["terminal_response_len"] + ), + "d_a": int(kvs.get("d_a") or kvs["final_inner_ring_dimension"]), + "n_a": int(kvs.get("n_a") or kvs["final_inner_module_rank"]), + "inner_width": int(kvs.get("inner_width", "0")), + "log_basis_inner": int( + kvs.get("log_basis_inner") or kvs["final_inner_log_basis"] + ), + "num_digits_inner": int(kvs.get("num_digits_inner", "0")), + "fold_log_basis": int(kvs.get("fold_log_basis", "0")), + "fold_digit_count": int(kvs.get("fold_digit_count", "0")), + "security_route": ( + "L2" + if parse_tracing_optional_int(kvs.get("response_l2_sq_cap")) + is not None + else "L-infinity" + ), + "response_l2_sq_cap": parse_tracing_optional_int( + kvs.get("response_l2_sq_cap") + ), + "z_admission_linf_cap": parse_tracing_optional_int( + kvs.get("z_admission_linf_cap") + ), + **{ + key: int(kvs[key]) + for key in ( + "challenge_l1_mass", + "challenge_count_pm1", + "challenge_count_pm2", + "num_live_ring_elements_per_claim", + "num_positions_per_block", + "num_live_blocks", + "block_index_domain_size", + ) + if key in kvs + }, + **( + { + "challenge_operator_norm_threshold": ( + parse_tracing_optional_int( + kvs.get("challenge_operator_norm_threshold") + ) + ) + } + if parse_tracing_optional_int( + kvs.get("challenge_operator_norm_threshold") + ) + is not None + else {} + ), + "complete": "fold_log_basis" in kvs, + } elif "planned recursive setup edge" in line and kvs.get("label") == mode: producer_level = int(kvs["successor_level"]) - 1 if producer_level in planned_levels: @@ -1049,17 +1141,20 @@ def extract_summary( }, } if "grind_nonce" in kvs: - proof_levels[level]["grind_nonce_val"] = int(kvs["grind_nonce"]) - if "grind_attempts" in kvs: - proof_levels[level]["grind_attempts"] = int(kvs["grind_attempts"]) + grind_nonce = int(kvs["grind_nonce"]) + grind_attempts = int(kvs.get("grind_attempts", grind_nonce + 1)) + if grind_attempts != grind_nonce + 1: + raise ValueError( + "fold grinding attempts must equal accepted nonce plus one: " + f"level={level}, nonce={grind_nonce}, attempts={grind_attempts}" + ) + proof_levels[level]["grind_nonce_val"] = grind_nonce + proof_levels[level]["grind_attempts"] = grind_attempts + response_l2_sq = parse_tracing_optional_int(kvs.get("response_l2_sq")) + if response_l2_sq is not None: + proof_levels[level]["response_l2_sq"] = response_l2_sq if "root_variant" in kvs: proof_levels[level]["root_variant"] = kvs["root_variant"] - elif "fold grind summary" in line and kvs.get("label") == mode: - summary["grind_levels"] = int(kvs["grind_levels"]) - if int(kvs["grind_levels"]) > 0: - summary["grind_nonce_max"] = int(kvs["grind_nonce_max"]) - summary["grind_attempts_sum"] = int(kvs["grind_attempts_sum"]) - summary["grind_nonces"] = kvs["grind_nonces"] elif "proof tail summary" in line and kvs.get("label") == mode: ingest_tail_summary_fields(summary, kvs) elif "z fold encoding stats" in line and kvs.get("label") == mode: @@ -1100,8 +1195,32 @@ def extract_summary( warning = public_opening_groups_warning(summary) if warning is not None: summary.setdefault("warnings", []).append(warning) + if terminal_plan is not None: + if terminal_plan["level"] is None: + terminal_plan["level"] = ( + max(proof_levels) + if proof_levels + else max(planned_levels, default=-1) + 1 + ) + summary["terminal_plan"] = terminal_plan if proof_levels: summary["proof_levels"] = [proof_levels[level] for level in sorted(proof_levels)] + grind_rows = [ + proof_levels[level] + for level in sorted(proof_levels) + if proof_levels[level].get("grind_nonce_val") is not None + ] + if grind_rows: + summary["grind_levels"] = len(grind_rows) + summary["grind_nonce_max"] = max( + int(level["grind_nonce_val"]) for level in grind_rows + ) + summary["grind_attempts_sum"] = sum( + int(level["grind_attempts"]) for level in grind_rows + ) + summary["grind_nonces"] = ",".join( + str(level["grind_nonce_val"]) for level in grind_rows + ) if onehot_commit_schedules: summary["onehot_commit_schedules"] = onehot_commit_schedules @@ -1213,9 +1332,97 @@ def compact_sample_summary(summary: dict[str, object]) -> dict[str, object]: for key in SAMPLE_METRICS: if key in summary: sample[key] = summary[key] + l2_observations = l2_grind_observations_for_run(summary) + if l2_observations: + sample["l2_grind_observations"] = l2_observations return sample +def l2_grind_observations_for_run( + summary: dict[str, object], +) -> list[dict[str, object]]: + planned_levels = summary.get("planned_levels") + proof_levels = summary.get("proof_levels") + if not isinstance(planned_levels, list): + return [] + l2_planned_levels = [ + planned + for planned in planned_levels + if isinstance(planned, dict) and planned.get("security_route") == "L2" + ] + run_failed = int(summary.get("exit_code", 0)) != 0 + if not isinstance(proof_levels, list): + if l2_planned_levels and not run_failed: + raise ValueError("successful L2 run is missing proof-level grinding diagnostics") + return [] + proofs_by_level = { + int(level["level"]): level + for level in proof_levels + if isinstance(level, dict) and level.get("level") is not None + } + observations = [] + for planned in l2_planned_levels: + level = int(planned["level"]) + proof = proofs_by_level.get(level) + if proof is None or proof.get("grind_attempts") is None: + if run_failed: + continue + raise ValueError(f"L2 fold level {level} is missing grinding diagnostics") + nonce = int(proof["grind_nonce_val"]) + attempts = int(proof["grind_attempts"]) + if attempts != nonce + 1: + raise ValueError(f"L2 fold level {level} has inconsistent grinding attempts") + observations.append( + { + "level": level, + "response_l2_sq_cap": int(planned["response_l2_sq_cap"]), + "accepted_nonce": nonce, + "attempts": attempts, + "rejected_attempts": nonce, + } + ) + return observations + + +def combine_l2_grind_observations( + summaries: list[dict[str, object]], +) -> list[dict[str, object]]: + combined: dict[tuple[int, int], dict[str, object]] = {} + for summary in summaries: + for observation in l2_grind_observations_for_run(summary): + key = (int(observation["level"]), int(observation["response_l2_sq_cap"])) + aggregate = combined.setdefault( + key, + { + "level": key[0], + "response_l2_sq_cap": key[1], + "samples": 0, + "attempts": 0, + "rejected_attempts": 0, + "accepted_nonces": [], + }, + ) + aggregate["samples"] = int(aggregate["samples"]) + 1 + aggregate["attempts"] = int(aggregate["attempts"]) + int( + observation["attempts"] + ) + aggregate["rejected_attempts"] = int(aggregate["rejected_attempts"]) + int( + observation["rejected_attempts"] + ) + accepted_nonces = aggregate["accepted_nonces"] + if not isinstance(accepted_nonces, list): + raise TypeError("internal L2 grind nonce aggregate must be a list") + accepted_nonces.append(int(observation["accepted_nonce"])) + result = [] + for key in sorted(combined): + aggregate = combined[key] + aggregate["observed_failure_rate"] = int(aggregate["rejected_attempts"]) / int( + aggregate["attempts"] + ) + result.append(aggregate) + return result + + SUMMARY_CSV_COLUMNS = ( "case_id", "benchmark_shard", @@ -1283,6 +1490,9 @@ def combine_case_run_summaries(summaries: list[dict[str, object]]) -> dict[str, combined = dict(summaries[0]) combined["runs"] = len(summaries) combined["samples"] = [compact_sample_summary(summary) for summary in summaries] + l2_grind_observations = combine_l2_grind_observations(summaries) + if l2_grind_observations: + combined["l2_grind_observations"] = l2_grind_observations for key in TIMING_SAMPLE_METRICS: values = [float(summary[key]) for summary in summaries if summary.get(key) is not None] @@ -1691,19 +1901,12 @@ class Metric: MEASURED_METRICS = [ Metric("setup_s", "Setup and preparation", "s", fmt_seconds), - Metric("setup_expand_s", "Setup expansion", "s", fmt_seconds), - Metric("backend_prepare_s", "Backend preparation", "s", fmt_seconds), + Metric("setup_expand_s", "↳ Setup expansion", "s", fmt_seconds), + Metric("backend_prepare_s", "↳ Backend preparation", "s", fmt_seconds), Metric("commit_s", "Commit", "s", fmt_seconds), Metric("prove_total_s", "Prove", "s", fmt_seconds), Metric("verify_total_s", "Verify, multi-threaded", "ms", fmt_milliseconds), Metric("verify_single_total_s", "Verify, single-threaded", "ms", fmt_milliseconds), - Metric("verify_akita_s", "Verifier core, multi-threaded", "ms", fmt_milliseconds), - Metric( - "verify_single_akita_s", - "Verifier core, single-threaded", - "ms", - fmt_milliseconds, - ), Metric("max_rss_kib", "Peak process RSS", "MiB", fmt_mib), Metric( "num_setup_field_elements", @@ -2131,6 +2334,34 @@ def fold_dimension_schedule(summary: dict[str, object]) -> str: return " → ".join(f"{d_a}/{d_b}/{d_d}" for d_a, d_b, d_d in tuples) +def terminal_response_metric_value( + current: dict[str, object], + baseline: dict[str, object] | None, + show_delta: bool, +) -> str: + total = optional_value_with_baseline_delta( + current, + baseline, + "tail_bytes", + fmt_bytes, + " bytes", + show_delta, + "", + ) + if all( + current.get(key) is not None + for key in ("tail_z_bytes", "tail_e_bytes", "tail_t_bytes") + ): + total += ( + "
" + f"z {fmt_bytes(float(current['tail_z_bytes']))} · " + f"e {fmt_bytes(float(current['tail_e_bytes']))} · " + f"t {fmt_bytes(float(current['tail_t_bytes']))}" + "" + ) + return total + + def render_matrix_summary( current_cases: list[dict[str, object]], main_baseline: dict[str, dict[str, object]] | None, @@ -2211,17 +2442,26 @@ def render_matrix_summary( if include_fold_schedule: row.append(fold_dimension_schedule(current)) for metric in metrics: - row.append( - optional_value_with_baseline_delta( - current, - baseline, - metric.key, - metric.value_formatter, - metric.unit, - main_baseline is not None, - "", + if metric.key == "tail_bytes": + row.append( + terminal_response_metric_value( + current, + baseline, + main_baseline is not None, + ) + ) + else: + row.append( + optional_value_with_baseline_delta( + current, + baseline, + metric.key, + metric.value_formatter, + metric.unit, + main_baseline is not None, + "", + ) ) - ) print("| " + " | ".join(row) + " |") if main_baseline is not None: @@ -2372,28 +2612,89 @@ def planned_group_key(group: dict[str, object]) -> tuple[str, str, int]: ) -def planned_group_planner_value(group: dict[str, object]) -> str: - matrix = ( - f"Rings A/B/D: {fmt_count(float(group['d_a']))} / " - f"{fmt_count(float(group['d_b']))} / {fmt_count(float(group['d_d']))}
" - f"Rows A/B/D: {fmt_count(float(group['n_a']))} / " - f"{fmt_count(float(group['n_b']))} / {fmt_count(float(group['n_d']))}" - ) - decomposition = ( - f"Basis bits A/B/D: {fmt_count(float(group['log_basis_inner']))} / " - f"{fmt_count(float(group['log_basis_outer']))} / " - f"{fmt_count(float(group['log_basis_open']))}
" - f"Digits A/B/D/W: {fmt_count(float(group['num_digits_inner']))} / " - f"{fmt_count(float(group['num_digits_outer']))} / " - f"{fmt_count(float(group['num_digits_open']))} / " - f"{fmt_count(float(group['num_digits_fold']))}" +def matrix_line( + label: str, + ring_dimension: object, + input_width: object, + output_rank: object, +) -> str: + width = int(input_width) + width_text = f" · input width {fmt_count(float(width))}" if width > 0 else "" + return ( + f"{label}: ring D{fmt_count(float(ring_dimension))}{width_text} · " + f"module rank {fmt_count(float(output_rank))}" ) + + +def challenge_line(params: dict[str, object]) -> str: + challenge = f"Ring D{fmt_count(float(params['d_a']))}" + count_pm1 = params.get("challenge_count_pm1") + count_pm2 = params.get("challenge_count_pm2") + if count_pm1 is not None and count_pm2 is not None: + challenge += f" · shell {fmt_count(float(count_pm1))} at ±1" + if int(count_pm2) != 0: + challenge += f" and {fmt_count(float(count_pm2))} at ±2" + threshold = params.get("challenge_operator_norm_threshold") + if threshold is not None: + challenge += f" · operator norm threshold {fmt_count(float(threshold))}" + return challenge + + +def response_bound_lines(params: dict[str, object]) -> list[str]: + linf_cap = params.get("z_admission_linf_cap") + linf_line = "Maximum coefficient magnitude (Linf)" + if linf_cap is not None: + linf_line += f": ≤ {fmt_count(float(linf_cap))}" + if params.get("security_route") == "L2": + rows = [linf_line, "Sum of squared coefficients (L2)"] + cap = params.get("response_l2_sq_cap") + if cap is not None: + rows[-1] += f": ≤ {fmt_count(float(cap))}" + return rows + return [linf_line] + + +def digit_count_phrase(value: object, role: str = "") -> str: + count = int(value) + role_prefix = f"{role} " if role else "" + suffix = "" if count == 1 else "s" + return f"{fmt_count(float(count))} {role_prefix}digit{suffix}" + + +def planned_group_planner_value(group: dict[str, object]) -> str: + matrices = [ + matrix_line("A commitment", group["d_a"], group.get("a_width", 0), group["n_a"]), + matrix_line("B commitment", group["d_b"], group.get("b_width", 0), group["n_b"]), + matrix_line("D opening", group["d_d"], group.get("d_width", 0), group["n_d"]), + ] + segments = [ + "z response: " + f"{digit_count_phrase(group['num_digits_inner'], 'input')} " + f"(basis bits {fmt_count(float(group['log_basis_inner']))}) × " + f"{digit_count_phrase(group['num_digits_fold'], 'response')} " + f"(basis bits {fmt_count(float(group['log_basis_open']))})", + "e opening: " + f"{digit_count_phrase(group['num_digits_open'])} " + f"(basis bits {fmt_count(float(group['log_basis_open']))})", + "t matrix image: " + f"{digit_count_phrase(group['num_digits_outer'])} " + f"(basis bits {fmt_count(float(group['log_basis_outer']))})", + ] + if str(group.get("group_role")) in ("final", "folded") and int( + group.get("num_digits_quotient", 0) + ) > 0: + segments.append( + "r shared quotient: " + f"{digit_count_phrase(group['num_digits_quotient'])} " + f"(basis bits {fmt_count(float(group['log_basis_open']))})" + ) return detail_block( planned_group_label(group), [ - f"Matrix geometry
{matrix}", - f"
Decomposition
{decomposition}", - f"
Challenge
L1 mass: {fmt_count(float(group['challenge_l1_mass']))}", + f"Commitment matrices used at this fold
{'
'.join(matrices)}", + f"
Folded response check
{'
'.join(response_bound_lines(group))}", + f"
Outgoing witness segments
{'
'.join(segments)}", + f"
Challenge used at this fold
{challenge_line(group)}", ], ) @@ -2402,10 +2703,11 @@ def planned_group_work_value(group: dict[str, object]) -> str: role = str(group["group_role"]) label = planned_group_label(group) relation = ( - f"Live per claim: {fmt_count(float(group['num_live_ring_elements_per_claim']))}
" - f"Blocks × positions: {fmt_count(float(group['num_live_blocks']))} × " + "Live ring elements per claim: " + f"{fmt_count(float(group['num_live_ring_elements_per_claim']))}
" + f"Live blocks × positions: {fmt_count(float(group['num_live_blocks']))} × " f"{fmt_count(float(group['num_positions_per_block']))}
" - f"Domain slots: {fmt_count(float(group['block_index_domain_size']))}" + f"Block domain slots: {fmt_count(float(group['block_index_domain_size']))}" ) if group.get("legacy_level"): source = ( @@ -2420,8 +2722,13 @@ def planned_group_work_value(group: dict[str, object]) -> str: ) else: source = f"Field elements: {fmt_count(float(group['witness_field_elements']))}" + input_label = ( + "Setup prefix" + if role == "setup_offload" + else f"Input at L{int(group['consumer_level'])}" + ) parts = [ - f"{'Setup prefix' if role == 'setup_offload' else 'Witness'}
{source}", + f"{input_label}
{source}", f"
Relation geometry
{relation}", ] if group.get("legacy_level") and ( @@ -2444,6 +2751,12 @@ def render_group_choices( baseline_groups: list[dict[str, object]], value: callable, ) -> str: + def comparison_value(group: dict[str, object]) -> str: + comparable = dict(group) + for field in ("a_width", "b_width", "d_width", "num_digits_quotient"): + comparable[field] = 0 + return value(comparable) + current = {planned_group_key(group): group for group in groups} baseline = {planned_group_key(group): group for group in baseline_groups} keys = [*current, *(key for key in baseline if key not in current)] @@ -2468,7 +2781,14 @@ def render_group_choices( else None ) ) - rows.append(exact_choice(current_text, baseline_text)) + if ( + current_group is not None + and baseline_group is not None + and comparison_value(current_group) == comparison_value(baseline_group) + ): + rows.append(current_text) + else: + rows.append(exact_choice(current_text, baseline_text)) return "

".join(rows) @@ -2511,7 +2831,10 @@ def render_value(total: int, values: list[str]) -> str: def proof_cost_summary( - level: dict[str, object], baseline: dict[str, object] | None + level: dict[str, object], + baseline: dict[str, object] | None, + planned: dict[str, object] | None, + baseline_planned: dict[str, object] | None, ) -> str: total = value_with_baseline_delta( level["total_bytes"], @@ -2536,6 +2859,7 @@ def proof_cost_summary( ("stage1_sumcheck_bytes", "sumcheck"), ("stage1_interstage_claims_bytes", "claims"), ("stage1_range_image_evaluation_bytes", "range image"), + ("stage1_norm_proof_bytes", "L2 norm proof"), ), ), ("Stage 2", (("stage2_sumcheck_bytes", "sumcheck"),)), @@ -2555,14 +2879,91 @@ def proof_cost_summary( ) if rendered is not None: rows.append(rendered) + if level.get("response_l2_sq") is not None: + cap = planned.get("response_l2_sq_cap") if planned is not None else None + observed = fmt_count(float(level["response_l2_sq"])) + if cap is not None: + observed += f" ≤ cap {fmt_count(float(cap))}" + baseline_observed = ( + fmt_count(float(baseline["response_l2_sq"])) + if baseline is not None and baseline.get("response_l2_sq") is not None + else None + ) + baseline_cap = ( + baseline_planned.get("response_l2_sq_cap") + if baseline_planned is not None + else None + ) + if baseline_observed is not None and baseline_cap is not None: + baseline_observed += f" ≤ cap {fmt_count(float(baseline_cap))}" + rows.append( + "Sum of squared response coefficients
" + + exact_choice(observed, baseline_observed) + ) return "

".join(rows) +def planned_terminal_planner_value(terminal: dict[str, object]) -> str: + matrix = matrix_line( + "A commitment", + terminal["d_a"], + terminal.get("inner_width", 0), + terminal["n_a"], + ) + response = ( + "z response: " + f"{digit_count_phrase(terminal['num_digits_inner'], 'input')} " + f"(basis bits {fmt_count(float(terminal['log_basis_inner']))}) × " + f"{digit_count_phrase(terminal['fold_digit_count'], 'response')} " + f"(basis bits {fmt_count(float(terminal['fold_log_basis']))})" + ) + rows = [f"Commitment matrix used at this fold
{matrix}"] + if terminal.get("complete"): + rows.extend( + [ + "
Folded response check
" + + "
".join(response_bound_lines(terminal)), + f"
Response decomposition
{response}", + "
Challenge used at this fold
" + + challenge_line(terminal), + ] + ) + return detail_block("Terminal fold", rows) + + +def planned_terminal_work_value(terminal: dict[str, object]) -> str: + level = int(terminal["level"]) + input_label = "Input at terminal root" if level == 0 else f"Input from L{level - 1}" + rows = [ + f"{input_label}
Field elements: " + f"{fmt_count(float(terminal['input_witness_len']))}" + ] + if terminal.get("complete"): + relation = ( + "Live ring elements per claim: " + f"{fmt_count(float(terminal['num_live_ring_elements_per_claim']))}
" + "Live blocks × positions: " + f"{fmt_count(float(terminal['num_live_blocks']))} × " + f"{fmt_count(float(terminal['num_positions_per_block']))}
" + "Block domain slots: " + f"{fmt_count(float(terminal['block_index_domain_size']))}" + ) + rows.extend( + [ + f"
Relation geometry
{relation}", + "
Output
Clear z, e, and t terminal response", + ] + ) + return detail_block("Terminal fold", rows) + + def render_fold_details( planned_levels: list[dict[str, object]], proof_levels: list[dict[str, object]], + terminal_plan: dict[str, object] | None, baseline_planned_levels: list[dict[str, object]] | None, baseline_proof_levels: list[dict[str, object]] | None, + baseline_terminal_plan: dict[str, object] | None, ) -> None: planned = {int(level["level"]): level for level in planned_levels} proof = {int(level["level"]): level for level in proof_levels} @@ -2572,13 +2973,18 @@ def render_fold_details( baseline_proof = { int(level["level"]): level for level in (baseline_proof_levels or []) } - level_indices = sorted(set(planned) | set(proof)) + terminal_level = int(terminal_plan["level"]) if terminal_plan is not None else None + level_indices = sorted( + set(planned) + | set(proof) + | ({terminal_level} if terminal_level is not None else set()) + ) print("
") print("Fold schedule and proof cost") print() print("#### Fold by fold") print() - headers = ["Fold", "Step", "Planner choice", "Work at this fold", "Proof bytes"] + headers = ["Fold", "Step", "Fold parameters", "Input and output", "Proof bytes"] print("| " + " | ".join(headers) + " |") print("| --- | --- | --- | --- | --- |") @@ -2588,7 +2994,31 @@ def render_fold_details( baseline_schedule = baseline_planned.get(level_index) baseline_proof_level = baseline_proof.get(level_index) step = proof_step_label(proof_level) if proof_level is not None else "scheduled fold" - if schedule is None: + is_terminal = terminal_level == level_index + if schedule is None and is_terminal and terminal_plan is not None: + baseline_terminal = ( + baseline_terminal_plan + if baseline_terminal_plan is not None + and baseline_terminal_plan.get("complete") + else None + ) + schedule_choice = exact_choice( + planned_terminal_planner_value(terminal_plan), + ( + planned_terminal_planner_value(baseline_terminal) + if baseline_terminal is not None + else None + ), + ) + work = exact_choice( + planned_terminal_work_value(terminal_plan), + ( + planned_terminal_work_value(baseline_terminal) + if baseline_terminal is not None + else None + ), + ) + elif schedule is None: schedule_choice = "—" work = "—" else: @@ -2616,29 +3046,33 @@ def render_fold_details( ) work = ( f"{work}

" - f"{detail_block('Folded output', [exact_choice(next_w, baseline_next_w)])}" + f"{detail_block(f'Output to L{level_index + 1}', [exact_choice(next_w, baseline_next_w)])}" ) proof_bytes = "n/a" if proof_level is not None: - proof_bytes = proof_cost_summary(proof_level, baseline_proof_level) + proof_bytes = proof_cost_summary( + proof_level, + baseline_proof_level, + schedule, + baseline_schedule, + ) row = [f"L{level_index}", step, schedule_choice, work, proof_bytes] print("| " + " | ".join(row) + " |") print() print( - "Role tuples use A / B / D order. The digit tuple adds folded witness W as " - "its fourth value. Proof groups with zero bytes are omitted. Component details " - "appear below the group total when a group contains multiple fields. " - "Unchanged choices omit merge base text. Exact proof component comparisons " - "show merge base bytes without a percentage. The terminal response is " - "reported separately and is not part of the terminal fold byte total." + "Each row shows the matrices and challenge used at that fold. Output to the " + "next level becomes the input shown on the next row. Each group has z, e, and " + "t segments. The complete relation has one shared r segment. The terminal fold uses only A and " + "sends the clear z, e, and t response shown in the terminal response section. " + "Proof groups with zero bytes are omitted. The terminal response bytes are not " + "part of the terminal fold byte total." ) grind_rows = [ level for level in proof_levels if int(level.get("grind_nonce_val", 0)) != 0 - or int(level.get("grind_attempts", 0)) != 0 ] if grind_rows: print() @@ -2691,6 +3125,37 @@ def validate_case_consistency(summary: dict[str, object]) -> None: proof_levels = summary.get("proof_levels") if not isinstance(planned_levels, list) or not isinstance(proof_levels, list): return + terminal_plan = summary.get("terminal_plan") + if isinstance(terminal_plan, dict) and planned_levels: + terminal_level = int(terminal_plan["level"]) + expected_terminal_level = int(planned_levels[-1]["level"]) + 1 + if terminal_level != expected_terminal_level: + raise ValueError( + "planned terminal level mismatch: " + f"planned={terminal_level}, expected={expected_terminal_level}" + ) + predecessor_output = int(planned_levels[-1]["next_w_len"]) + terminal_input = int(terminal_plan["input_witness_len"]) + if terminal_input != predecessor_output: + raise ValueError( + "planned terminal input mismatch: " + f"terminal={terminal_input}, predecessor_output={predecessor_output}" + ) + matching_proof = next( + ( + proof + for proof in proof_levels + if int(proof["level"]) == terminal_level + ), + None, + ) + if matching_proof is not None and int(matching_proof["d"]) != int( + terminal_plan["d_a"] + ): + raise ValueError( + f"planned/proof terminal A ring dimension mismatch at L{terminal_level}: " + f"planned={terminal_plan['d_a']}, proof={matching_proof['d']}" + ) # The prover emits the direct terminal as an extra "proof fold level" # (`print_terminal_level_breakdown`), whereas the planner reports the # terminal separately as "planned terminal state" rather than a "planned @@ -2850,17 +3315,10 @@ def render_report(args: argparse.Namespace) -> int: print() render_matrix_summary(current_cases, baselines[0][1]) if args.compact: - print() - print("
") - print("Terminal response components") - print() - render_terminal_response_components(current_cases, include_heading=False) - print() - print("
") print() print( - "Detailed schedule and proof-size breakdowns by fold level are available in " - "the uploaded `report.md` benchmark artifact." + "The uploaded `report.md` benchmark artifact contains the detailed fold schedule, " + "proof-size breakdown, terminal response segments, and Golomb diagnostics." ) return 0 @@ -3018,8 +3476,10 @@ def render_report(args: argparse.Namespace) -> int: render_fold_details( planned_levels, proof_levels, + current.get("terminal_plan"), baseline_planned_levels, baseline_proof_levels, + main_case.get("terminal_plan") if main_case is not None else None, ) if len(current_cases) > 1: print() diff --git a/scripts/sis_golden/README.md b/scripts/sis_golden/README.md index cb7ea9b8c..69f39c5b9 100644 --- a/scripts/sis_golden/README.md +++ b/scripts/sis_golden/README.md @@ -17,7 +17,7 @@ Regenerates `golden.csv` and updates `metadata.json` from the grid in `grid.py`: sage -python scripts/sis_golden/refresh_golden.py ``` -The grid covers q32/q64/q128, `d ∈ {32,64,128,256}`, ranks `{1,5,20}`, and +The grid covers q32/q64/q128, `d ∈ {32,64,128,256,512}`, ranks `{1,5,20}`, and includes the degenerate knee at `(q32, d=32, collision_l2_sq=16384)`. ## Check @@ -30,12 +30,9 @@ sage -python scripts/sis_golden/check.py ## Euclidean comparison table regen -Generate the offline Euclidean comparison CSV. Do not use `--format rust-split` -for this command: that output shape is not the production L-infinity table. - -The generator uses `--max-rank 20`, the old 128-bit BDGL16 Euclidean profile, -and the same power-of-two plus derived `d * B^2` collision-key set as the legacy -Sage stitcher. This is not the production lookup path after the L∞ cutover. +Generate the Euclidean comparison CSV or the separate L2 table. The generator +uses the 128 bit quantum ADPS16 profile. Its key is a power of two bound on the +squared norm of the complete scalar collision vector. For a row-oriented comparison artifact: @@ -45,6 +42,10 @@ cargo run -p akita-sis-estimator --release --features parallel \ --output /tmp/euclidean_width_table_rust.csv --format csv ``` +Full `rust-split` output writes +`crates/akita-types/src/sis/generated_l2_sis_table/`. It does not replace the +production infinity norm table in `generated_sis_table/`. + The full comparison CSV is a local audit artifact, not a committed source file. The production table is generated by the policy-aware `infinity_width_table` command below; Rust CI does not require Sage or an initialized submodule for it. diff --git a/scripts/sis_golden/golden.csv b/scripts/sis_golden/golden.csv index 81381a4bc..54b3611d0 100644 --- a/scripts/sis_golden/golden.csv +++ b/scripts/sis_golden/golden.csv @@ -1,64 +1,73 @@ q,d,collision,rank,max_width,target_bits,search_cap -4294967197,32,16384,1,4,128.0,10000000000 -4294967197,32,16384,5,492,128.0,10000000000 -4294967197,32,16384,20,4564249232,128.0,10000000000 -4294967197,32,65536,1,4,128.0,10000000000 -4294967197,32,65536,5,123,128.0,10000000000 -4294967197,32,65536,20,1141062308,128.0,10000000000 -4294967197,32,262144,1,3,128.0,10000000000 -4294967197,32,262144,5,30,128.0,10000000000 -4294967197,32,262144,20,285265577,128.0,10000000000 -4294967197,64,16384,1,5,128.0,10000000000 -4294967197,64,16384,5,375787,128.0,10000000000 +4294967197,32,16384,1,6,128.0,10000000000 +4294967197,32,16384,5,10000000000,128.0,10000000000 +4294967197,32,16384,20,10000000000,128.0,10000000000 +4294967197,32,65536,1,5,128.0,10000000000 +4294967197,32,65536,5,10000000000,128.0,10000000000 +4294967197,32,65536,20,10000000000,128.0,10000000000 +4294967197,32,262144,1,4,128.0,10000000000 +4294967197,32,262144,5,10000000000,128.0,10000000000 +4294967197,32,262144,20,10000000000,128.0,10000000000 +4294967197,64,16384,1,6,128.0,10000000000 +4294967197,64,16384,5,10000000000,128.0,10000000000 4294967197,64,16384,20,10000000000,128.0,10000000000 -4294967197,64,65536,1,4,128.0,10000000000 -4294967197,64,65536,5,93946,128.0,10000000000 +4294967197,64,65536,1,5,128.0,10000000000 +4294967197,64,65536,5,10000000000,128.0,10000000000 4294967197,64,65536,20,10000000000,128.0,10000000000 4294967197,64,1048576,1,3,128.0,10000000000 -4294967197,64,1048576,5,5871,128.0,10000000000 +4294967197,64,1048576,5,10000000000,128.0,10000000000 4294967197,64,1048576,20,10000000000,128.0,10000000000 -4294967197,128,16384,1,91,128.0,50000000000 -4294967197,128,16384,5,4564249232,128.0,50000000000 +4294967197,128,16384,1,50000000000,128.0,50000000000 +4294967197,128,16384,5,50000000000,128.0,50000000000 4294967197,128,16384,20,50000000000,128.0,50000000000 -4294967197,128,65536,1,22,128.0,50000000000 -4294967197,128,65536,5,1141062308,128.0,50000000000 +4294967197,128,65536,1,50000000000,128.0,50000000000 +4294967197,128,65536,5,50000000000,128.0,50000000000 4294967197,128,65536,20,50000000000,128.0,50000000000 -4294967197,256,16384,1,34061,128.0,10000000000 +4294967197,256,16384,1,10000000000,128.0,10000000000 4294967197,256,16384,5,10000000000,128.0,10000000000 4294967197,256,16384,20,10000000000,128.0,10000000000 -4294967197,256,65536,1,8515,128.0,10000000000 +4294967197,256,65536,1,10000000000,128.0,10000000000 4294967197,256,65536,5,10000000000,128.0,10000000000 4294967197,256,65536,20,10000000000,128.0,10000000000 -18446744073709551557,32,16384,1,9,128.0,10000000000 -18446744073709551557,32,16384,5,375787,128.0,10000000000 +4294967197,512,137438953472,1,2,128.0,10000000000 +4294967197,512,137438953472,5,10000000000,128.0,10000000000 +4294967197,512,137438953472,20,10000000000,128.0,10000000000 +18446744073709551557,32,16384,1,13,128.0,10000000000 +18446744073709551557,32,16384,5,10000000000,128.0,10000000000 18446744073709551557,32,16384,20,10000000000,128.0,10000000000 -18446744073709551557,32,65536,1,8,128.0,10000000000 -18446744073709551557,32,65536,5,93946,128.0,10000000000 +18446744073709551557,32,65536,1,11,128.0,10000000000 +18446744073709551557,32,65536,5,10000000000,128.0,10000000000 18446744073709551557,32,65536,20,10000000000,128.0,10000000000 -18446744073709551557,64,16384,1,91,128.0,10000000000 -18446744073709551557,64,16384,5,4564249308,128.0,10000000000 +18446744073709551557,64,16384,1,10000000000,128.0,10000000000 +18446744073709551557,64,16384,5,10000000000,128.0,10000000000 18446744073709551557,64,16384,20,10000000000,128.0,10000000000 -18446744073709551557,64,65536,1,22,128.0,10000000000 -18446744073709551557,64,65536,5,1141062327,128.0,10000000000 +18446744073709551557,64,65536,1,10000000000,128.0,10000000000 +18446744073709551557,64,65536,5,10000000000,128.0,10000000000 18446744073709551557,64,65536,20,10000000000,128.0,10000000000 -18446744073709551557,128,16384,1,34061,128.0,50000000000 +18446744073709551557,128,16384,1,50000000000,128.0,50000000000 18446744073709551557,128,16384,5,50000000000,128.0,50000000000 18446744073709551557,128,16384,20,50000000000,128.0,50000000000 -18446744073709551557,256,16384,1,151967359,128.0,10000000000 +18446744073709551557,256,16384,1,10000000000,128.0,10000000000 18446744073709551557,256,16384,5,10000000000,128.0,10000000000 18446744073709551557,256,16384,20,10000000000,128.0,10000000000 -340282366920938463463374607427473266697,32,16384,1,91,128.0,10000000000 -340282366920938463463374607427473266697,32,16384,5,4564249308,128.0,10000000000 +18446744073709551557,512,4503599627370496,1,4,128.0,10000000000 +18446744073709551557,512,4503599627370496,5,10000000000,128.0,10000000000 +18446744073709551557,512,4503599627370496,20,10000000000,128.0,10000000000 +340282366920938463463374607427473266697,32,16384,1,10000000000,128.0,10000000000 +340282366920938463463374607427473266697,32,16384,5,10000000000,128.0,10000000000 340282366920938463463374607427473266697,32,16384,20,10000000000,128.0,10000000000 -340282366920938463463374607427473266697,32,65536,1,23,128.0,10000000000 -340282366920938463463374607427473266697,32,65536,5,1141062327,128.0,10000000000 +340282366920938463463374607427473266697,32,65536,1,10000000000,128.0,10000000000 +340282366920938463463374607427473266697,32,65536,5,10000000000,128.0,10000000000 340282366920938463463374607427473266697,32,65536,20,10000000000,128.0,10000000000 -340282366920938463463374607427473266697,64,16384,1,34061,128.0,10000000000 +340282366920938463463374607427473266697,64,16384,1,10000000000,128.0,10000000000 340282366920938463463374607427473266697,64,16384,5,10000000000,128.0,10000000000 340282366920938463463374607427473266697,64,16384,20,10000000000,128.0,10000000000 -340282366920938463463374607427473266697,128,16384,1,151967359,128.0,50000000000 +340282366920938463463374607427473266697,128,16384,1,50000000000,128.0,50000000000 340282366920938463463374607427473266697,128,16384,5,50000000000,128.0,50000000000 340282366920938463463374607427473266697,128,16384,20,50000000000,128.0,50000000000 340282366920938463463374607427473266697,256,16384,1,10000000000,128.0,10000000000 340282366920938463463374607427473266697,256,16384,5,10000000000,128.0,10000000000 340282366920938463463374607427473266697,256,16384,20,10000000000,128.0,10000000000 +340282366920938463463374607427473266697,512,9444732965739290427392,1,6,128.0,10000000000 +340282366920938463463374607427473266697,512,9444732965739290427392,5,10000000000,128.0,10000000000 +340282366920938463463374607427473266697,512,9444732965739290427392,20,10000000000,128.0,10000000000 diff --git a/scripts/sis_golden/grid.py b/scripts/sis_golden/grid.py index 9efbb2a26..2fd46e4e8 100644 --- a/scripts/sis_golden/grid.py +++ b/scripts/sis_golden/grid.py @@ -19,6 +19,7 @@ ("q32", 128, 65_536), ("q32", 256, 16_384), ("q32", 256, 65_536), + ("q32", 512, 137_438_953_472), # q64 ("q64", 32, 16_384), ("q64", 32, 65_536), @@ -26,10 +27,12 @@ ("q64", 64, 65_536), ("q64", 128, 16_384), ("q64", 256, 16_384), + ("q64", 512, 4_503_599_627_370_496), # q128 ("q128", 32, 16_384), ("q128", 32, 65_536), ("q128", 64, 16_384), ("q128", 128, 16_384), ("q128", 256, 16_384), + ("q128", 512, 9_444_732_965_739_290_427_392), ] diff --git a/scripts/sis_golden/metadata.json b/scripts/sis_golden/metadata.json index a2d8a9368..6a53033bf 100644 --- a/scripts/sis_golden/metadata.json +++ b/scripts/sis_golden/metadata.json @@ -1,7 +1,10 @@ { - "description": "21 work items \u00d7 ranks [1, 5, 20] = 63 golden cells across q32/q64/q128.", + "description": "24 work items \u00d7 ranks [1, 5, 20] = 72 golden cells across q32/q64/q128.", "lattice_estimator_remote": "https://github.com/malb/lattice-estimator.git", "lattice_estimator_sha": "c667a48546f140c3a5454c7503c3ca44a264cce2", + "reduction_model": "ADPS16 quantum", + "norm": "Euclidean", + "collision_key": "complete scalar collision squared L2 norm", "golden_ranks": [ 1, 5, @@ -58,6 +61,11 @@ "d": 256, "collision": 65536 }, + { + "family": "q32", + "d": 512, + "collision": 137438953472 + }, { "family": "q64", "d": 32, @@ -88,6 +96,11 @@ "d": 256, "collision": 16384 }, + { + "family": "q64", + "d": 512, + "collision": 4503599627370496 + }, { "family": "q128", "d": 32, @@ -112,6 +125,11 @@ "family": "q128", "d": 256, "collision": 16384 + }, + { + "family": "q128", + "d": 512, + "collision": 9444732965739290427392 } ] } diff --git a/scripts/sis_golden/refresh_golden.py b/scripts/sis_golden/refresh_golden.py index 2960d1f20..4c9bd9036 100644 --- a/scripts/sis_golden/refresh_golden.py +++ b/scripts/sis_golden/refresh_golden.py @@ -104,6 +104,9 @@ def main() -> int: ), "lattice_estimator_remote": estimator_remote_url(estimator_path), "lattice_estimator_sha": estimator_git_sha(estimator_path), + "reduction_model": "ADPS16 quantum", + "norm": "Euclidean", + "collision_key": "complete scalar collision squared L2 norm", "golden_ranks": GOLDEN_RANKS, "work_items": [ {"family": family, "d": d, "collision": collision} diff --git a/scripts/tests/test_operator_norm_certificates.py b/scripts/tests/test_operator_norm_certificates.py new file mode 100644 index 000000000..f3144f1bd --- /dev/null +++ b/scripts/tests/test_operator_norm_certificates.py @@ -0,0 +1,39 @@ +"""Run the bundled exact operator-norm accepted-support certificates.""" + +import subprocess +import sys +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +CERTIFICATE_ROOT = REPO_ROOT / "scripts" / "operator_norm" + + +class OperatorNormCertificateTests(unittest.TestCase): + def run_checker(self, dimension: str, certificate: str) -> None: + directory = CERTIFICATE_ROOT / dimension + result = subprocess.run( + [sys.executable, "check_cert.py", certificate], + cwd=directory, + check=False, + capture_output=True, + text=True, + timeout=180, + ) + self.assertEqual( + result.returncode, + 0, + msg=f"stdout:\n{result.stdout}\nstderr:\n{result.stderr}", + ) + self.assertIn("ALL CHECKS PASS", result.stdout) + + def test_d64_certificate(self) -> None: + self.run_checker("d64", "cert_d64_a31_b11_gamma18.json") + + def test_d128_certificate(self) -> None: + self.run_checker("d128", "cert_d128_w31_gamma13.json") + + +if __name__ == "__main__": + unittest.main() diff --git a/scripts/tests/test_profile_bench_report.py b/scripts/tests/test_profile_bench_report.py index 53080a480..9012a28ef 100644 --- a/scripts/tests/test_profile_bench_report.py +++ b/scripts/tests/test_profile_bench_report.py @@ -142,6 +142,12 @@ def test_terminal_response_encoding_renders_component_breakdown(self) -> None: "tail_t_bytes": 64, "tail_t_field_elems": 32, "tail_t_ring_elems": 1, + "tail_z_budget_bytes": 16, + "z_witness_linf_cap": "4096", + "z_rice_low_bits_wire": 10, + "z_bits_per_coord_golomb": 3.0, + "z_bits_per_coord_packed": 13.0, + "z_packed_hypothetical_bytes": 52, } output = io.StringIO() @@ -149,38 +155,44 @@ def test_terminal_response_encoding_renders_component_breakdown(self) -> None: render_tail_encoding(summary) report = output.getvalue() - self.assertIn("quotient-free terminal response", report) - self.assertIn("inner gadget basis width `6` bits", report) - self.assertIn("Folded-witness (`z`) segment", report) - self.assertIn("Opening-digit (`e`) segment", report) - self.assertIn("Inner-commitment (`t`) segment", report) - - def test_compact_report_renders_terminal_response_component_table(self) -> None: - from scripts.profile_bench_report import render_terminal_response_components + self.assertIn( + "Clear response: `96` coefficients across `z`, `e`, and `t`", report + ) + self.assertIn("incoming witness uses a basis width of `6` bits", report) + self.assertIn("| Folded response (`z`) | 20 bytes | 32 | 1 |", report) + self.assertIn("| Opening values (`e`) | 64 bytes | 32 | 1 |", report) + self.assertIn("| Inner-commitment values (`t`) | 64 bytes | 32 | 1 |", report) + self.assertIn("Golomb parameter `10`", report) + self.assertIn("coefficient limit `4096`", report) + self.assertIn("`3.00` bits per coefficient", report) + self.assertNotIn("Wire total", report) + self.assertNotIn("savings", report) + + def test_proof_table_embeds_terminal_response_components(self) -> None: + from scripts.profile_bench_report import normalize_case_summary, render_matrix_summary - case = { - "mode": "onehot_fp128", - "num_vars": 32, - "num_polys": 1, - "exit_code": 0, - "tail_encoding": "terminal_response", - "tail_z_bytes": 20, - "tail_e_bytes": 64, - "tail_t_bytes": 96, - "tail_bytes": 180, - } + case = normalize_case_summary( + { + "mode": "onehot_fp128", + "num_vars": 32, + "num_polys": 1, + "exit_code": 0, + "tail_encoding": "terminal_response", + "tail_z_bytes": 20, + "tail_e_bytes": 64, + "tail_t_bytes": 96, + "tail_bytes": 180, + } + ) output = io.StringIO() with contextlib.redirect_stdout(output): - render_terminal_response_components([case]) + render_matrix_summary([case], None) report = output.getvalue() - self.assertIn("Terminal response component breakdown", report) - self.assertIn("20 bytes", report) - self.assertIn("64 bytes", report) - self.assertIn("96 bytes", report) self.assertIn("180 bytes", report) - self.assertIn("sum exactly", report) + self.assertIn("z 20 · e 64 · t 96", report) + self.assertNotIn("Terminal response component breakdown", report) def test_z_fold_encoding_stats_prefers_wire_low_bits(self) -> None: from scripts.profile_bench_report import extract_summary @@ -318,9 +330,14 @@ def test_planned_fold_level_parses_physical_geometry(self) -> None: "d_a": 64, "d_b": 32, "d_d": 16, + "a_width": 0, + "b_width": 0, + "d_width": 0, "n_a": 2, "n_b": 3, "n_d": 4, + "security_route": "L-infinity", + "response_l2_sq_cap": None, "challenge_l1_mass": 8, "log_basis_inner": 5, "log_basis_outer": 5, @@ -335,6 +352,7 @@ def test_planned_fold_level_parses_physical_geometry(self) -> None: "num_digits_outer": 5, "num_digits_open": 5, "delta_fold": 6, + "num_digits_quotient": 26, "input_witness_len": 1024, # Legacy scalar `current_w_len` is not a group breakdown. "current_w_len": [], @@ -445,7 +463,9 @@ def test_rendered_schedule_uses_names_and_merge_base_deltas(self) -> None: current_log = ( 'INFO planned fold level label=onehot_fp128 level=0 d=64 d_a=64 d_b=32 d_d=16 ' - 'n_a=4 n_b=6 n_d=8 challenge_l1_mass=16 log_basis=6 position_index_bits=7 ' + 'n_a=4 n_b=6 n_d=8 response_l2_sq_cap=Some(100) challenge_l1_mass=53 ' + 'challenge_count_pm1=31 challenge_count_pm2=11 ' + 'challenge_operator_norm_threshold=Some(19) log_basis=6 position_index_bits=7 ' 'block_index_bits=3 num_live_ring_elements_per_claim=768 num_live_blocks=6 ' 'block_index_domain_size=8 num_positions_per_block=128 delta_commit=4 delta_open=5 ' 'delta_fold=6 current_w_len=1024 next_w_len=2048 level_bytes=4096\n' @@ -464,17 +484,28 @@ def test_rendered_schedule_uses_names_and_merge_base_deltas(self) -> None: output = io.StringIO() with contextlib.redirect_stdout(output): - render_fold_details(current, proof, baseline, proof) + render_fold_details(current, proof, None, baseline, proof, None) report = output.getvalue() self.assertIn("Fold schedule and proof cost", report) - self.assertIn("Rings A/B/D: 64 / 32 / 16", report) - self.assertIn("Rows A/B/D: 4 / 6 / 8", report) - self.assertIn("Matrix geometry", report) + self.assertIn("A commitment: ring D64 · module rank 4", report) + self.assertIn("B commitment: ring D32 · module rank 6", report) + self.assertIn("D opening: ring D16 · module rank 8", report) + self.assertIn("Sum of squared coefficients (L2)", report) + self.assertIn("Sum of squared coefficients (L2): ≤ 100", report) + self.assertIn( + "Ring D64 · shell 31 at ±1 and 11 at ±2 · operator norm threshold 19", + report, + ) + self.assertIn("Commitment matrices used at this fold", report) + self.assertIn("z response: 4 input digits", report) + self.assertIn("e opening: 5 digits", report) + self.assertIn("t matrix image: 5 digits", report) + self.assertIn("r shared quotient: 22 digits", report) self.assertIn( "Merge base
Final group
" - "Matrix geometry
Rings A/B/D: 64 / 32 / 16
" - "Rows A/B/D: 2 / 6 / 8", + "Commitment matrices used at this fold
" + "A commitment: ring D64 · module rank 2", report, ) self.assertNotIn("+100.0% vs base", report) @@ -483,6 +514,118 @@ def test_rendered_schedule_uses_names_and_merge_base_deltas(self) -> None: self.assertNotIn("| M |", report) self.assertNotIn("r_pos", report) + def test_new_display_fields_do_not_create_false_plan_deltas(self) -> None: + from scripts.profile_bench_report import extract_summary, render_fold_details + + common = ( + "INFO planned fold level label=onehot_fp128 level=0 d=64 " + "d_a=64 d_b=64 d_d=64 n_a=3 n_b=2 n_d=2 " + "challenge_l1_mass=53 log_basis_inner=5 log_basis_outer=6 " + "log_basis_open=6 position_index_bits=7 block_index_bits=3 " + "num_live_ring_elements_per_claim=768 num_live_blocks=6 " + "block_index_domain_size=8 num_positions_per_block=128 " + "num_digits_inner=1 num_digits_outer=22 num_digits_open=22 " + "delta_fold=2 input_witness_len=4096 output_witness_len=2048 " + "current_w_len=final=4096 next_w_len=2048" + ) + current_log = common + " a_width=128 b_width=264 d_width=132 num_digits_quotient=22\n" + baseline_log = common + "\n" + proof_log = ( + "INFO proof fold level label=onehot_fp128 level=0 d=64 " + "total_bytes=4 fold_grind_nonce_bytes=4\n" + ) + current = extract_summary(current_log, "onehot_fp128", 24, 1)["planned_levels"] + baseline = extract_summary(baseline_log, "onehot_fp128", 24, 1)["planned_levels"] + proof = extract_summary(proof_log, "onehot_fp128", 24, 1)["proof_levels"] + + output = io.StringIO() + with contextlib.redirect_stdout(output): + render_fold_details(current, proof, None, baseline, proof, None) + report = output.getvalue() + + self.assertIn("input width 128", report) + self.assertIn("r shared quotient: 22 digits", report) + self.assertNotIn("Merge base", report) + + def test_terminal_fold_reports_its_full_geometry(self) -> None: + from scripts.profile_bench_report import ( + extract_summary, + planned_terminal_planner_value, + render_fold_details, + ) + + log = "\n".join( + [ + "INFO planned fold level label=onehot_fp128 level=0 d=64 " + "d_a=64 d_b=64 d_d=64 a_width=128 b_width=64 d_width=64 " + "n_a=4 n_b=2 n_d=2 challenge_l1_mass=53 " + "challenge_count_pm1=31 challenge_count_pm2=11 " + "log_basis_inner=5 log_basis_outer=6 log_basis_open=6 " + "position_index_bits=7 block_index_bits=3 " + "num_live_ring_elements_per_claim=768 num_live_blocks=6 " + "block_index_domain_size=8 num_positions_per_block=128 " + "num_digits_inner=1 num_digits_outer=22 num_digits_open=22 " + "delta_fold=2 num_digits_quotient=22 input_witness_len=4096 " + "output_witness_len=2048 current_w_len=final=4096 next_w_len=2048", + "INFO planned terminal state label=onehot_fp128 level=1 " + "input_witness_len=2048 d_a=64 n_a=3 inner_width=128 " + "log_basis_inner=5 num_digits_inner=1 fold_log_basis=6 " + "fold_digit_count=2 challenge_l1_mass=53 " + "challenge_count_pm1=31 challenge_count_pm2=11 " + "challenge_operator_norm_threshold=Some(19) " + "response_l2_sq_cap=Some(633237013) " + "z_admission_linf_cap=Some(2570) " + "num_live_ring_elements_per_claim=1908 " + "num_positions_per_block=256 num_live_blocks=8 " + "block_index_domain_size=8", + "INFO proof fold level label=onehot_fp128 level=0 d=64 " + "total_bytes=4 fold_grind_nonce_bytes=4", + "INFO proof fold level label=onehot_fp128 level=1 d=64 " + "total_bytes=548 extension_opening_partials_bytes=64 " + "extension_opening_sumcheck_bytes=480 fold_grind_nonce_bytes=4 " + "root_variant=terminal", + ] + ) + summary = extract_summary(log, "onehot_fp128", 24, 1) + terminal = summary["terminal_plan"] + self.assertEqual(terminal["level"], 1) + self.assertEqual(terminal["d_a"], 64) + self.assertEqual(terminal["n_a"], 3) + self.assertEqual(terminal["inner_width"], 128) + terminal_block = planned_terminal_planner_value(terminal) + self.assertNotIn("B commitment", terminal_block) + self.assertNotIn("D opening", terminal_block) + + output = io.StringIO() + with contextlib.redirect_stdout(output): + render_fold_details( + summary["planned_levels"], + summary["proof_levels"], + terminal, + None, + None, + None, + ) + report = output.getvalue() + + self.assertIn( + "A commitment: ring D64 · input width 128 · module rank 3", report + ) + self.assertIn( + "z response: 1 input digit (basis bits 5) × " + "2 response digits (basis bits 6)", + report, + ) + self.assertIn( + "Ring D64 · shell 31 at ±1 and 11 at ±2 · operator norm threshold 19", + report, + ) + self.assertIn("Maximum coefficient magnitude (Linf): ≤ 2,570", report) + self.assertIn("Sum of squared coefficients (L2): ≤ 633,237,013", report) + self.assertIn("Input from L0
Field elements: 2,048", report) + self.assertIn("Clear z, e, and t terminal response", report) + self.assertNotIn("| L1 | terminal fold | — | — |", report) + def test_multi_group_root_and_setup_offload_keep_group_parameters(self) -> None: from scripts.profile_bench_report import extract_summary, render_fold_details @@ -589,22 +732,25 @@ def test_multi_group_root_and_setup_offload_keep_group_parameters(self) -> None: output = io.StringIO() with contextlib.redirect_stdout(output): - render_fold_details(planned, proof, planned, proof) + render_fold_details(planned, proof, None, planned, proof, None) report = output.getvalue() self.assertIn( - "Precommit 1
Matrix geometry
" - "Rings A/B/D: 64 / 64 / 64", + "Precommit 1
" + "Commitment matrices used at this fold
" + "A commitment: ring D64 · module rank 3", report, ) self.assertIn( - "Final group
Matrix geometry
" - "Rings A/B/D: 256 / 64 / 64", + "Final group
" + "Commitment matrices used at this fold
" + "A commitment: ring D256 · module rank 1", report, ) self.assertIn( - "Setup offload → L1
Matrix geometry
" - "Rings A/B/D: 256 / 64 / 64", + "Setup offload → L1
" + "Commitment matrices used at this fold
" + "A commitment: ring D256 · module rank 2", report, ) self.assertIn( @@ -613,9 +759,11 @@ def test_multi_group_root_and_setup_offload_keep_group_parameters(self) -> None: report, ) self.assertIn( - "Folded output
Field elements: 47,963,968", + "Output to L1
Field elements: 47,963,968", report, ) + self.assertIn("Maximum coefficient magnitude (Linf)", report) + self.assertEqual(report.count("r shared quotient:"), 1) self.assertNotIn("setup fields; relation", report) def test_proof_breakdown_omits_zero_components(self) -> None: @@ -626,16 +774,20 @@ def test_proof_breakdown_omits_zero_components(self) -> None: ) log = ( - 'INFO proof fold level label=onehot_fp128 level=0 d=64 total_bytes=20 ' + 'INFO proof fold level label=onehot_fp128 level=0 d=64 total_bytes=28 ' 'fold_grind_nonce_bytes=4 grind_nonce=3 grind_attempts=4 ' 'stage1_range_image_evaluation_bytes=16 ' + 'stage1_norm_proof_bytes=8 response_l2_sq=Some(14) ' 'root_variant=terminal\n' ) levels = extract_summary(log, "onehot_fp128", 24, 1)["proof_levels"] - self.assertEqual(proof_level_component_bytes(levels[0]), 20) + self.assertEqual(proof_level_component_bytes(levels[0]), 28) + self.assertEqual(levels[0]["response_l2_sq"], 14) planned_log = ( 'INFO planned fold level label=onehot_fp128 level=0 d=64 d_a=64 d_b=32 d_d=16 ' - 'n_a=4 n_b=6 n_d=8 challenge_l1_mass=16 log_basis=6 position_index_bits=7 ' + 'n_a=4 n_b=6 n_d=8 response_l2_sq_cap=Some(100) challenge_l1_mass=53 ' + 'challenge_count_pm1=31 challenge_count_pm2=11 ' + 'challenge_operator_norm_threshold=Some(19) log_basis=6 position_index_bits=7 ' 'block_index_bits=3 num_live_ring_elements_per_claim=768 num_live_blocks=6 ' 'block_index_domain_size=8 num_positions_per_block=128 delta_commit=4 delta_open=5 ' 'delta_fold=6 current_w_len=1024 next_w_len=2048\n' @@ -644,12 +796,15 @@ def test_proof_breakdown_omits_zero_components(self) -> None: output = io.StringIO() with contextlib.redirect_stdout(output): - render_fold_details(planned, levels, planned, levels) + render_fold_details(planned, levels, None, planned, levels, None) report = output.getvalue() self.assertIn("Fold by fold", report) - self.assertIn("Stage 1
16 bytes", report) - self.assertIn("range image 16", report) + self.assertIn("Stage 1
24 bytes", report) + self.assertIn("range image 16", report) + self.assertIn("L2 norm proof 8", report) + self.assertIn("Sum of squared response coefficients", report) + self.assertIn("14 ≤ cap 100", report) self.assertNotIn("Opening", report) self.assertNotIn("Stage 2", report) self.assertIn("+0.0% vs merge base", report) @@ -662,6 +817,104 @@ def test_proof_breakdown_omits_zero_components(self) -> None: ] self.assertEqual(len({line.count("|") for line in proof_table_lines}), 1) + def test_grind_attempts_are_truthful_and_nonzero(self) -> None: + from scripts.profile_bench_report import extract_summary + + derived_log = ( + "INFO proof fold level label=onehot_fp128_d64 level=0 d=64 total_bytes=4 " + "fold_grind_nonce_bytes=4 grind_nonce=0\n" + ) + level = extract_summary(derived_log, "onehot_fp128_d64", 24, 1)[ + "proof_levels" + ][0] + self.assertEqual(level["grind_attempts"], 1) + + impossible_log = derived_log.replace( + "grind_nonce=0", "grind_nonce=0 grind_attempts=0" + ) + with self.assertRaisesRegex(ValueError, "accepted nonce plus one"): + extract_summary(impossible_log, "onehot_fp128_d64", 24, 1) + + def test_l2_grinding_observations_survive_sample_aggregation(self) -> None: + from scripts.profile_bench_report import ( + combine_case_run_summaries, + extract_summary, + render_fold_details, + ) + + planned = ( + "INFO planned fold level label=onehot_fp128_d64 level=5 d=64 d_a=64 d_b=64 " + "d_d=64 n_a=4 n_b=4 n_d=4 response_l2_sq_cap=Some(4294967296) " + "challenge_l1_mass=8 log_basis=5 position_index_bits=7 block_index_bits=3 " + "num_live_ring_elements_per_claim=768 num_live_blocks=6 " + "block_index_domain_size=8 num_positions_per_block=128 delta_commit=4 " + "delta_open=5 delta_fold=6 current_w_len=1024 next_w_len=2048\n" + ) + summaries = [] + for run_index, nonce in enumerate((0, 2), start=1): + proof = ( + "INFO proof fold level label=onehot_fp128_d64 level=5 d=64 total_bytes=4 " + f"fold_grind_nonce_bytes=4 grind_nonce={nonce} grind_attempts={nonce + 1}\n" + ) + summary = extract_summary(planned + proof, "onehot_fp128_d64", 24, 1) + summary["run_index"] = run_index + summary["exit_code"] = 0 + summaries.append(summary) + + combined = combine_case_run_summaries(summaries) + observation = combined["l2_grind_observations"][0] + self.assertEqual(observation["samples"], 2) + self.assertEqual(observation["attempts"], 4) + self.assertEqual(observation["rejected_attempts"], 2) + self.assertEqual(observation["accepted_nonces"], [0, 2]) + self.assertEqual(observation["observed_failure_rate"], 0.5) + self.assertEqual( + combined["samples"][1]["l2_grind_observations"][0]["accepted_nonce"], 2 + ) + + output = io.StringIO() + with contextlib.redirect_stdout(output): + render_fold_details( + combined["planned_levels"], + combined["proof_levels"], + None, + None, + None, + None, + ) + report = output.getvalue() + self.assertNotIn("L2 cap grinding observations", report) + self.assertNotIn("50.00%", report) + + def test_failed_l2_run_preserves_partial_sample_without_grind_diagnostics(self) -> None: + from scripts.profile_bench_report import combine_case_run_summaries + + failed = { + "run_index": 1, + "exit_code": 1, + "error": "prover failed before measured L2 level", + "planned_levels": [ + { + "level": 5, + "security_route": "L2", + "response_l2_sq_cap": 100, + } + ], + "proof_levels": [ + { + "level": 0, + "grind_nonce_val": 0, + "grind_attempts": 1, + } + ], + } + + combined = combine_case_run_summaries([failed]) + + self.assertEqual(combined["exit_code"], 1) + self.assertEqual(combined["samples"][0]["exit_code"], 1) + self.assertNotIn("l2_grind_observations", combined) + def test_matrix_splits_metrics_and_embeds_merge_base_deltas(self) -> None: from scripts.profile_bench_report import normalize_case_summary, render_matrix_summary @@ -1042,6 +1295,7 @@ def test_full_report_renders_overhauled_tables(self) -> None: "stage1_sumcheck_bytes": 0, "stage1_interstage_claims_bytes": 0, "stage1_range_image_evaluation_bytes": 0, + "stage1_norm_proof_bytes": 0, "stage2_sumcheck_bytes": 0, "stage3_sumcheck_bytes": 0, "next_w_payload_bytes": 0, @@ -1098,7 +1352,7 @@ def test_full_report_renders_overhauled_tables(self) -> None: self.assertIn("Execution parameters", report) self.assertIn("Fold schedule and proof cost", report) self.assertIn("Fold by fold", report) - self.assertIn("Rings A/B/D", report) + self.assertIn("Commitment matrices used at this fold", report) self.assertIn("Proof bytes", report) self.assertNotIn("Proof byte components", report) self.assertNotIn("Planned fold-level proof bytes", report) diff --git a/specs/PRUNING.md b/specs/PRUNING.md index 4ff046eeb..f69f3e463 100644 --- a/specs/PRUNING.md +++ b/specs/PRUNING.md @@ -143,7 +143,6 @@ for a stacked follow-up. | `akita-pcs-crate-decomposition.md` | `how/architecture.md` | | `extension-field-opening-batching.md` | `how/proving/extension-opening-reduction.md` | | `terminal-fold-cutover.md` | `how/recursion.md` | -| `weak-binding-norm-fix.md` (committed-fold section) | `how/security.md` | | `akita-sis-consolidation.md` | `how/security.md` | | `planner-refactor.md`, `planner-owns-schedule-expansion.md` | `how/configuration.md` | | `transcript-hardening.md` | `how/transcript.md` | diff --git a/specs/archive/2026-Q2/l2-msis-opnorm-folded-witness.md b/specs/archive/2026-Q2/l2-msis-opnorm-folded-witness.md deleted file mode 100644 index d76310a21..000000000 --- a/specs/archive/2026-Q2/l2-msis-opnorm-folded-witness.md +++ /dev/null @@ -1,1606 +0,0 @@ -# Spec: L2 MSIS Cutover, Operator-Norm Challenges, and Folded-Witness L2 Certificates - -| Field | Value | -|---------------|-------| -| Author(s) | Quang Dao, Cursor agent draft | -| Created | 2026-06-04 | -| Status | historical (cert cancelled #247; op-norm rejection removed `remove/op-norm-rejection`) | -| PR | [#155](https://github.com/LayerZero-Labs/akita/pull/155) (L2 MSIS tables); [#207](https://github.com/LayerZero-Labs/akita/pull/207) (D64 op-norm rejection, split from [#195](https://github.com/LayerZero-Labs/akita/pull/195)); [#247](https://github.com/LayerZero-Labs/akita/pull/247) (L2 cert removal) | -| Superseded-by | — | -| Book-chapter | — | - -> **Ground truth (2026-06-29).** The folded-witness L2 certificate path (S6–S13, -> four-square slack, grouped-carry sumchecks) is cancelled and removed on main in -> [#247](https://github.com/LayerZero-Labs/akita/pull/247) (`four_square.rs`, -> grouped-carry verifier replay, certificate proof shape). -> **This branch (`remove/op-norm-rejection`)** additionally removes operator-norm -> rejection sampling and Γ-based collision pricing; production collision uses -> challenge L1 mass `ω` only (`committed_fold_collision_l2_sq` in `norm_bound.rs`). -> Treat certificate and op-norm sections below as historical design unless marked -> shipped. Interim live references: -> [`specs/fold-linf-rejection.md`](../../fold-linf-rejection.md), -> [`specs/sis-euclidean-estimator.md`](../../sis-euclidean-estimator.md). - -## Summary - -Akita currently prices committed-fold weak binding through coefficient `L∞` -collision buckets. -This spec cuts the protocol over to an `L2` / Euclidean MSIS security model and -adds the proof machinery needed to justify the tighter bound inside the -protocol. - -The cutover has three linked parts. -First, folding challenges are sampled from operator-norm accepted distributions, -starting with the D=64 signed-sparse family and production rejection threshold `gamma(c) <= 18`. -Second, the folded witness `z = sum_i c_i * s_i` carries a certified Euclidean -norm bound, proved over the finite field as an exact integer statement. -Third, the SIS planner, generated tables, public security model, transcript -descriptor, proof sizing, and verifier checks all move to the new L2 norm model -in one pass. - -This is intentionally a full cutover. -The branch does not keep parallel `collision_inf` and `collision_l2` pricing -paths, dual schedule tables, legacy aliases, or compatibility shims for the old -coefficient-`L∞` security model. - -## Intent - -### Goal - -Replace Akita's committed-fold coefficient-`L∞` SIS pricing with certified -Euclidean folded-witness pricing, backed by operator-norm accepted challenges -and an in-protocol `||z||_2^2 <= B` certificate. - -The primary protocol surfaces are: - -- `akita-challenges`: operator-norm accepted ring-challenge families, including - accepted-support accounting and transcript-stable rejection sampling. -- `akita-types::sis`: L2 MSIS security buckets, secure-rank lookup, folded - witness L2 bound derivation, and digit/certificate sizing. -- `akita-types::proof`: proof shape changes for the folded-witness L2 - certificate (`B_l2`, trailing `ell_hat` / `carry_hat`, masked `V`, carry - linear claim). -- `akita-prover`: computation of realized folded-witness square sums from - `DecomposeFoldWitness.centered_coeffs` / committed `z_hat` digit planes, - four-square slack and carry-limb construction, and integration into the fused - stage-2 proof flow. -- `akita-verifier`: replay of the L2 certificate, no-panic validation of all - certificate shapes, and consistency with the committed next witness. -- `akita-config` / `akita-planner`: schedule search, shipped-table selection, - generated table representation, and proof-size accounting under the L2 MSIS - model. -### Product scope (operator-norm rejection) — **removed this branch** - -> Historical: this section described per-level `op_norm_rejection` shipped in #207. -> `remove/op-norm-rejection` deletes the sampler, planner flag, and Γ collision path. - -Per-level `op_norm_rejection` on `LevelParams` is ring-dimension-agnostic -infrastructure: the planner may enable it only when Γ collision pricing -strictly lowers audited A-rank vs ω pricing **and** the fold-level witness -scoring cost (`(1 + n_a)·δ_open·2^r + δ_commit·δ_fold·m_eff`, same as -`optimal_block_geometry_split`) is strictly lower with rejection on at that geometry **and** -the fold draw samples at most `2^12` sparse challenges -(`num_live_blocks · num_claims`). -**Production scope today is D=64 only.** The only shipped binding preset is -`signed-sparse { count_mag1: 31, count_mag2: 11 }` with `T = 18` at ring degree 64. -D=128 and D=256 use ±1-only sparse challenges -(`proof_optimized_ring_challenge_config`). For those families -`operator_norm_cap` equals L1 mass, so the flag stays false and the sampler -skips the rejection oracle. D=128/D=256 flat folds may still use fold-linf -tail-bound digit tightening ([`fold-linf-rejection.md`](fold-linf-rejection.md)); -that is orthogonal to operator-norm rejection. -Extending rejection to other ring dimensions is deferred until a binding Γ -preset and a certified acceptance floor exist for that `(family, d)` pair. -L2 certificate geometry (`fold_l2_certificate`, `B_l2_pub`) is a separate -follow-up PR split from #195. - -**Implementation notes ([#207](https://github.com/LayerZero-Labs/akita/pull/207)).** -The certified op-norm predicate uses transposed frequency tables with `i64` -accumulators and fused 4-wide chunk paths (AVX2 / NEON). -`choose_op_norm_rejection_for_a_role` is recomputed per geometry during offline -schedule search and table expansion. - -### Invariants - -- **Single security table, per-role norm derivation.** All SIS binding decisions - price against one Euclidean (L2) MSIS floor table. - The committed-fold A-role contributes its L2 collision bound directly. - The B-role and D-role opening-digit collisions keep their natural coefficient - `L∞` bound `2^lb - 1` (the difference of two balanced digits) and are converted - into the same L2 table by the explicit inequality `||v||_2 <= sqrt(d)·||v||_inf`. - No committed-fold rank, schedule, or proof-size path uses the old coefficient - `L∞` collision-bucket *table* after the cutover. - The only surviving `L∞` quantities are the per-digit difference feeding that - conversion and the folded-witness `||z||_inf` bound that still sizes the digit - count of the next recursive witness (`num_digits_fold`); neither prices the - A-role binding rank. -- **Exact integer certificate via no-wrap limbs.** The verifier accepts the - realized folded-witness L2 certificate only when every field equality it relies - on is known to be an exact integer equality. - Two structural realizations, selected by a public field-capacity gate, deliver - this. The field-fitting realization, used when the worst-case square sum and - slack fit the field, checks `Σ_x z_aug(x)^2 = B_l2` in one sumcheck. The - grouped-carry realization, used otherwise (notably fp32 dense recursive levels, - where the square sum exceeds `q`), groups the committed digits into no-wrap - limbs and reconciles the wide integer with a carry chain. - Both are gated by validated structural bounds, never by the realized value - alone. Only when even single-digit grouping (`g = 1`) fails the gate does the - level emit no certificate and price the A-role at the deterministic worst-case - L2 bound. - The deterministic bound is still Euclidean and still far tighter than the old - `L∞` envelope; the certificate is a no-wrap-gated tightening, not a separate - security model. -- **Folded witness is the certified object.** The certified vector is the - centered integer folded witness represented by - `DecomposeFoldWitness.centered_coeffs`, not an unrelated evaluation table or - heuristic proxy. -- **Operator-norm challenge contract.** Every sampled accepted challenge - satisfies the configured negacyclic convolution operator-norm cap. - Prover and verifier must replay the same rejection-sampling transcript stream. -- **Accepted challenge entropy.** Each production challenge family has at least - 128 bits of accepted Fiat-Shamir support after rejection sampling. - For D=64 signed sparse, the target starting point is - `signed-sparse { count_mag1: 31, count_mag2: 11 }` with `gamma(c) <= 18`, whose - raw support is about `2^130.152`. - The rational acceptance floor `13/20` is certified for tail-bound sizing on - levels with `op_norm_rejection` enabled; a vendored checked ≥128-bit artifact - in CI remains open (S2). -- **No adversarial challenge bias hole.** The security proof must account for the - accepted challenge distribution used by the extractor. - Honest-pair experiments are calibration only and cannot justify the production - bound by themselves. -- **Stage-2 consistency.** The L2 certificate must be tied to the same folded - witness that is decomposed into the next recursive witness and used in the - ring relation. - A prover cannot certify one `z` and commit to a different `w`. -- **Verifier no-panic boundary.** Malformed verifier-facing challenges, - certificates, schedule entries, proof shapes, digit decompositions, or - overflow-prone dimensions are rejected with `AkitaError` or - `SerializationError`, never by panicking. -- **Transcript binding.** The instance descriptor binds the active MSIS norm - model, challenge family, operator-norm threshold, L2 bound policy, certificate - shape, and schedule. - A proof generated under the L2 model cannot verify under old L∞ parameters. -- **Generated schedule determinism.** Runtime DP fallback and shipped generated - schedules use the same L2 bound formulas and security tables. - Table-hit and table-miss schedule resolution must agree on every value that - affects transcript, proof shape, and setup dimensions. -- **Single certificate for transparent and ZK.** The realized certificate is the - same protocol in transparent and ZK builds: it never sends folded-witness inner - products, and its only public scalar is `B_l2`. - ZK builds toggle on the existing masking of the sumcheck messages, the claimed - sum `V`, and the committed `ell_hat` / `carry_hat`; transparent builds run the - identical claim structure without hiding witness. - The mask accounting stays linear except for the single explicitly recorded - quadratic relation (the squared-sum sumcheck). -- **Standalone code documentation.** Comments, docstrings, and implementations - must make sense on their own, without the reader opening this spec. - Do not tag source with slice identifiers (`S1`, `S8`, ...), do not cite "the - spec", and do not describe a symbol only by its future spec consumer. - Explain the math, the contract, and the symbol's role in codebase terms - (concrete types, functions, and protocol objects). - Slice and spec tracking belongs in commit messages and PR descriptions, not in - the code. - -### Non-Goals - -- No long-term support for the coefficient-`L∞` committed-fold pricing model. -- No compatibility mode for proofs or schedules generated under the old model. -- No attempt to use empirical challenge or witness distributions as a security - proof. -- No unrelated setup-offloading or terminal-proof refactor. -- No generic user-facing arbitrary rejection predicate API in the first cut. - Production challenge families are explicit policy variants with audited - support and norm facts. -- No weakening of the existing digit range checks. - The L2 certificate supplements the digit/ring-relation proof; it does not - replace the checks needed to bind decomposition and recursive witness layout. - -## Evaluation - -### Acceptance Criteria - -- [x] *(#155 partial)* Specs and `norm_bound.rs` agree on Euclidean MSIS lookup, - Lemma 7 on fold response `z` (`8·ω·β_inf·ν` → `collision_l2_sq_for_linf_envelope`), - and `β_inf = fold_witness_beta`. Full public security-doc cutover completes with - S6+ certificate wording. -- [x] *(#155, S5b)* `akita_types::sis` exposes `committed_fold_collision_l2_sq` / - `rounded_up_collision_norm_s`, derived `d·B²` table keys (`COEFF_LINF_BUCKETS`, - `collision_l2_sq_for_linf_envelope`), and pow2-ladder fallback; `collision_inf` is - removed from production call sites (`collision_l2_sq` on `AjtaiKeyParams`). -- [x] *(#155, S3 infra; D64 op-norm split PR)* signed-sparse operator-norm rejection - sampling, `operator_norm_cap`, per-level `op_norm_rejection` on `LevelParams`, - and descriptor binding are implemented. Production D=64 ships `(31, 11)` with - `T = 18`; the planner enables rejection sampling only on fold levels where - Γ pricing strictly lowers audited A-rank **and** witness-scoring cost is cheaper - with rejection on **and** sparse-draw count is at most `2^12`. -- [ ] The D=64 accepted family has a rigorous support lower bound of at least - 128 bits, not just a Monte Carlo estimate. - *(D64 op-norm split PR ships rational floor `13/20` at `T = 18`; - vendored checked cert in CI remains open.)* -- [ ] The prover derives the grouped `z_hat` limbs from the actual - `DecomposeFoldWitness.centered_coeffs` used for ring-switch witness - construction, and its reconstructed `Z_SQUARED` matches a direct integer - reference in tests. -- [ ] The realized certificate adds four-square slack `ell_0..ell_3` so the bound - becomes the equality `Σ_i z[i]^2 + Σ_h ell_h^2 = B_l2`, and commits - `ell_hat` (and, in the grouped-carry realization, `carry_hat`) as trailing - segments of `w_next`. No folded-witness inner product is ever sent. -- [ ] The field-fitting realization proves `Σ_x z_aug(x)^2 = B_l2` in one degree-2 - sumcheck, with `z_aug = z || ell_0..ell_3` recomposed from the committed - digits. -- [ ] The grouped-carry realization squeezes one challenge `alpha`, proves the - single sumcheck `Σ_x Z_alpha(x)^2 = V` for the `alpha`-weighted limb - recomposition `Z_alpha`, and reconciles - `V = Σ_e alpha^e T_e + Σ_e alpha^e (B·h_{e+1} - h_e)` against the public - bound digits `T_e` and the committed carries via one short linear claim. -- [ ] The verifier accepts a realized level only when the public no-wrap gate - holds for every convolution exponent - (`D_e + H'_e + (B-1) + B·H'_{e+1} < q`, with `H'_e` the committed carry - cell run's realizable budget), so each carry residual that is zero modulo - `q` is zero as an integer. A test pins which levels choose field-fitting, - grouped-carry, or deterministic-fallback tiers. -- [ ] The certified statement is over the committed `z_hat` / `ell_hat` / - `carry_hat` digit planes, and a test ties every limb, slack, and carry - evaluation to the committed `w_next` segment via gadget recomposition (a - tampered `z_hat`, `ell_hat`, or `carry_hat` fails the check). -- [x] *(#155, S5b)* B-role and D-role collisions use `collision_l2_sq_for_linf_envelope` - on `2^lb − 1` (`rounded_up_collision_norm_t/w`). Dedicated table-conversion test - remains a follow-up; pricing path is wired. -- [ ] The squared-sum sumcheck reduces to limb evaluations `a^{}(rho)` - (equivalently the single `Z_alpha(rho)`), and a linear virtualization step - ties those plus the carry evaluation `carry_hat(rho_c)` to the existing - `w_next` opening (batched or explicitly justified adjacent), without - duplicating witness scans more than necessary. -- [ ] On certifying levels the proof shape accounts for the masked claimed sum - `V`, the carry linear-claim transcript, and any stage-message changes (no - partial-sum payload exists). A test pins the per-level message shape, and - the descriptor binds it. -- [ ] The committed `z_hat` / `ell_hat` / `carry_hat` segments and `B_l2` are - transcript-bound before `alpha` or any squared-sum / carry challenge is - squeezed (wire-before-squeeze), and a logging-transcript test enforces the - ordering. -- [ ] Proof shape, proof-size formula, shape deserialization, and compressed - proof validation account for the certificate payload (`B_l2`, the - `ell_hat` / `carry_hat` witness growth, the masked `V`, and the carry - linear-claim layout, pinned by a serialization test). -- [x] *(#155, S5b)* Runtime DP, `expand_to_level_params`, and shipped generated - schedule tables size A-role ranks from `collision_l2_sq`; `num_digits_fold` - still uses `β_inf`. Certificate-tier `B_l2` sizing waits for S6. -- [x] *(#155, S5b)* ZK and non-ZK shipped schedule tables are separate DP optima under - different proof-byte accounting; drift guards run per feature set (see - [`sis-euclidean-estimator.md`](sis-euclidean-estimator.md) ZK vs non-ZK section). -- [ ] `cargo fmt -q`, `cargo clippy --all --message-format=short -q -- -D warnings`, - and `cargo test` pass on the cutover branch *(CI gate for merge)*. -- [ ] End-to-end prover/verifier tests fail if any one of the committed folded - witness, L2 certificate, next-witness commitment, or ring-relation rows is - tampered independently. - -### Testing Strategy - -Unit tests: - -- Challenge tests for D=64 signed-sparse acceptance: - deterministic rejection replay, support-domain bytes, accepted `gamma(c) <= T`, - and stable transcript behavior across prover and verifier. -- Exact or interval-certified tests for the challenge support lower bound. - These tests may validate a checked certificate artifact instead of enumerating - the full challenge space in CI. -- SIS tests pinning L2 secure-rank lookup against generated tables, including - bucket rounding and unsupported-bucket rejection. -- Folded-witness tests that compare `centered_coeffs` square sums with a direct - negacyclic integer reference for dense, one-hot, recursive, and batched folds. -- Grouped-carry tests covering field-fitting selection, single-digit grouping, - last short groups, negative `C_e` / carries, the integer carry recurrence - against a direct `Σ z[i]^2` reference, and no-wrap-gate fallback. - -Protocol tests: - -- Stage-2 prover/verifier round-trip with the L2 term active. -- Transparent and ZK proof paths, if the ZK feature remains enabled on this - branch. -- Root, recursive intermediate, and terminal paths. - Terminal paths may use a different bound shape, but must be explicit. -- Multipoint and same-point batching, so `num_claims` routing cannot certify the - wrong folded witness segment. -- Serialization/deserialization shape tests for the updated proof objects. - -Drift guards: - -- Generated schedule tables match runtime DP fallback. -- Proof-size model matches serialized proof bytes. -- Instance descriptor bytes change intentionally and are pinned by tests. -- Grep-style tests or review checks confirm no committed-fold production path - still uses `rounded_up_collision_norm_s` or `fold_witness_beta` as an L∞ - security price. - -### Performance - -Expected direction: - -- SIS A-rank should drop relative to the corrected L∞ committed-fold reprice - when the L2 bound is substantially below the coordinate worst case. -- The L2 certificate payload is `B_l2`, the masked `V`, the squared-sum and carry - sumcheck transcripts, and the `ell_hat` / `carry_hat` witness growth (no - partial sums are sent). The carry payload shrinks as the group size `g` grows - and `R` shrinks; it is empty in the field-fitting realization. -- Net proof size should improve only if the rank and recursive schedule savings - exceed the certificate overhead. -- fp32 dense recursive levels keep the deterministic `L2_BOUND_SQUARED` (no - certificate), so their gain comes only from the L2 reprice, not from the - realized tightening. - -Benchmarks and profile commands: - -```bash -AKITA_MODE=onehot_fp128_d64 AKITA_NUM_VARS=32 cargo run --release --example profile -AKITA_MODE=onehot_fp128_d64 AKITA_NUM_VARS=32 cargo run --release --example profile -``` - -#### Folded-witness L2 calibration (2026-06-04) - -Local profile instrumentation in the `akita` worktree logs exact integer -`||z||_2`, `||z||_∞`, and per-coordinate RMS from -`DecomposeFoldWitness.centered_coeffs` at the `validate_decompose_fold` -boundary. -Sample 0 runs full prove plus verify; extra samples reuse the same commitment -and cloned hint with distinct transcripts. - -```bash -AKITA_ALLOW_DEBUG_PROFILE=1 AKITA_PROFILE_TRACE=0 \ - AKITA_PROFILE_LOG=akita_prover::protocol::ring_relation=info \ - AKITA_PROFILE_SPAN_CLOSES=0 AKITA_PROFILE_ANSI=0 \ - AKITA_MODE= AKITA_NUM_VARS= \ - AKITA_PROFILE_Z_L2_SAMPLES= \ - cargo run -q -p akita-pcs --example profile -``` - -**Methodology.** - -- Certified object: `DecomposeFoldWitness.centered_coeffs` for - `z = sum_i c_i * s_i`. -- Fold width: `B = num_claims * num_live_blocks` (typically `num_claims = 1` at - root). -- Per-coordinate RMS: `z_rms = ||z||_2 / sqrt(coeffs)`. -- Current production D=64 signed sparse is `(31, 11)`, so - `rho2 = 31 + 4 * 11 = 75`. - Operator-norm rejection is enabled per fold level only when Γ pricing lowers - audited A-rank and witness-scoring cost favors rejection; the sampler enforces - `gamma(c) <= 18` on those levels. -- Formula comparisons in historical calibration notes use candidate `Gamma = 16`. -- Backsolved source second moment (calibration only): - `mu2_implied = z_rms^2 / (rho2 * B)`. - This is not a direct measurement of `sum_i ||s_i||_2^2`. -- Exploratory triangle reference (calibration only, **not** production sizing): - `det_rms = Gamma * B * sqrt(mu2_implied)`. -- Honest second-moment reference (fitted from the same sample): - `honest_rms = sqrt(rho2 * B * mu2_implied)`. -- Old coordinate envelope ratio: - `||z||_2 / linf_l2_envelope`, where `linf_l2_envelope` is the existing - `sqrt(coeffs) * beta_linf` planner proxy. - -**Caveats.** - -- All numbers below are honest-pair calibration, not a security proof. -- Dense profile runs may panic afterward on a pre-existing proof-size overcount - assertion (`planned` vs `actual` bytes). - Norm logs are emitted before that panic. -- Op-norm rejection on fixed-energy signed sparse does not change `rho2 = 75` for - `(31, 11)`; it tightens Γ-priced A-role ranks and tail behavior on enabled levels. -- Historical calibration tables below used the prior `(30, 12)` shell (`rho2 = 78`). - Re-measure under `(31, 11)` before feeding backsolved second moments into planner code. -- Next instrumentation: log `sum_i ||s_i||_2` and `sum_i ||s_i||_2^2` - directly at the decompose-fold source boundary before turning heuristics into - planner code. - -##### One-hot root level (terminal fold) - -| mode | nv | B | samples | rows | coeffs | `beta_linf` | old L∞ env | `||z||_2` mean | `||z||_2` range | `z_rms` | `mu2_implied` | old env ratio | obs/det | -|------|----|---|---------|------|--------|-------------|------------|---------------|-----------------|---------|---------------|---------------|---------| -| onehot_fp32_d64 | 16 | 4 | 100 | 256 | 16384 | 216 | 27648 | 186.716 | 183.728-190.683 | 1.458719 | 0.006820 | 0.00675 | 0.2760 | -| onehot_fp32_d64 | 18 | 8 | 20 | 512 | 32768 | 432 | 78200 | 373.633 | 369.816-376.215 | 2.064052 | 0.006828 | 0.00478 | 0.1952 | -| onehot_fp32_d64 | 20 | 16 | 50 | 1024 | 65536 | 864 | 221184 | 747.919 | 743.923-753.662 | 2.921560 | 0.006839 | 0.00338 | 0.1380 | -| onehot_fp128_d64 | 16 | 4 | 30 | 256 | 16384 | 216 | 27648 | 141.151 | 139.764-142.373 | 1.102739 | 0.003898 | 0.00511 | 0.2760 | - -One-hot observations: - -- `mu2_implied` is stable near `0.00682` for `fp32_d64` across - `nv = 16, 18, 20` despite `B` growing `4 -> 8 -> 16`. -- `||z||_2` scales like `sqrt(B)` at fixed density, as expected from the - second-moment model. -- `fp128_d64` one-hot has lower `mu2_implied` (`0.003898`) and lower absolute - `||z||_2`, consistent with sparser effective witness density at the same - terminal shape. -- Old L∞ envelope ratios stay near `0.005` to `0.007`, roughly - `150x` to `200x` pessimistic vs observed `||z||_2`. - -##### One-hot `fp32_d64`, `nv = 20` (multi-level, 50 samples) - -At `nv = 20`, one-hot proofs emit five folded-witness levels. -Root stays sparse; recursive levels inherit dense digit statistics. - -| rows | coeffs | B | `||z||_2` mean | `z_rms` | `mu2_implied` | obs/det | -|------|--------|---|---------------|---------|---------------|---------| -| 1024 | 65536 | 16 | 747.919 | 2.921560 | 0.006839 | 0.1380 | -| 663 | 42432 | 8 | 22177.698 | 107.663801 | 18.577085 | 0.1952 | -| 406 | 25984 | 8 | 34368.493 | 213.209959 | 72.852217 | 0.1952 | -| 309 | 19776 | 8 | 33650.917 | 239.291721 | 91.769170 | 0.1952 | -| 273 | 17472 | 8 | 33319.664 | 252.074724 | 101.833811 | 0.1952 | - -Recursive levels show the same rising-`mu2` pattern as dense proofs once the -witness is no longer one-hot sparse. - -##### Dense `fp32_d64`, `nv = 16` (20 samples, four levels) - -| rows | coeffs | B | `beta_linf` | old L∞ env | `||z||_2` mean | `||z||_2` range | `z_rms` | `mu2_implied` | old env ratio | obs/det | -|------|--------|---|-------------|-----------|---------------|-----------------|---------|---------------|---------------|---------| -| 896 | 57344 | 8 | 6912 | 1,655,189 | 51315.581 | 50828-51643 | 214.292 | 73.592 | 0.03100 | 0.1952 | -| 493 | 31552 | 8 | 6912 | 1,227,770 | 42388.828 | 42044-42809 | 238.637 | 91.265 | 0.03453 | 0.1952 | -| 342 | 21888 | 8 | 6912 | 1,022,602 | 35967.097 | 35609-36324 | 243.110 | 94.718 | 0.03517 | 0.1952 | -| 285 | 18240 | 8 | 6912 | 933,504 | 34104.167 | 33832-34340 | 252.520 | 102.191 | 0.03653 | 0.1952 | - -Dense observations at `nv = 16`: - -- Absolute `||z||_2` is orders of magnitude above one-hot, but old L∞ envelope - ratios remain `0.031` to `0.037` (roughly `30x` to `35x` pessimistic). -- `mu2_implied` rises from `73.6` to `102.2` deeper in the recursion tree. -- At fixed `B = 8`, `obs/det` is constant `0.1952` across all four levels. - -##### Dense `fp32_d64`, `nv = 18` (6 samples, seven levels) - -| rows | coeffs | B | `||z||_2` mean | `z_rms` | `mu2_implied` | obs/det | -|------|--------|---|---------------|---------|---------------|---------| -| 2048 | 131072 | 32 | 21260.877 | 58.725432 | 1.382041 | 0.0976 | -| 765 | 48960 | 32 | 15170.494 | 68.561295 | 1.891533 | 0.0974 | -| 675 | 43200 | 16 | 19657.419 | 94.576800 | 7.168233 | 0.1380 | -| 668 | 42752 | 8 | 26645.005 | 128.865773 | 26.613366 | 0.1952 | -| 408 | 26112 | 8 | 36070.090 | 223.216945 | 79.849858 | 0.1952 | -| 310 | 19840 | 8 | 34040.113 | 241.668560 | 93.600131 | 0.1952 | -| 273 | 17472 | 8 | 33432.820 | 252.930786 | 102.526111 | 0.1952 | - -Root levels at `B = 32` have much lower `mu2_implied` (`~1.4`) than recursive -levels at `B = 8` (`26` to `102`). - -##### Dense `fp128_d64`, `nv = 16` (8 samples, six levels) - -| rows | coeffs | B | `||z||_2` mean | `z_rms` | `mu2_implied` | obs/det | -|------|--------|---|---------------|---------|---------------|---------| -| 1024 | 65536 | 32 | 59251.337 | 231.450537 | 21.462808 | 0.0976 | -| 749 | 47936 | 8 | 21843.826 | 99.769506 | 15.952119 | 0.1952 | -| 658 | 42112 | 16 | 30208.971 | 147.208537 | 17.364938 | 0.1380 | -| 467 | 29888 | 8 | 30271.810 | 175.101536 | 49.136914 | 0.1952 | -| 361 | 23104 | 8 | 28590.044 | 188.092394 | 56.698332 | 0.1952 | -| 321 | 20544 | 8 | 27758.986 | 193.669440 | 60.109594 | 0.1952 | - -`fp128` dense levels span `mu2_implied` from `15.95` to `60.11`, lower than -the corresponding `fp32` dense band at similar recursive depths. - -##### Formula comparison - -Two candidate models were checked against the same logs. - -**Exploratory triangle bound (calibration only, not production sizing)** - -```text -||z||_2 <= Gamma * sum_i ||s_i||_2 -``` - -This decoupled `Gamma · B · ‖s‖_2` envelope is **not** Lemma 7 and must not -appear in planner or MSIS table code. With `mu2_implied` backsolved from each -sample, the fitted exploratory RMS is -`det_rms = Gamma * B * sqrt(mu2_implied)`. -The observed ratio `z_rms / det_rms` depends primarily on `B`: - -| B | observed / deterministic (`Gamma = 16`, `rho2 = 78`) | -|---|------------------------------------------------------| -| 4 | 0.2760 | -| 8 | 0.1952 | -| 16 | 0.1380 | -| 32 | 0.0975 to 0.0976 | - -This matches the closed form - -```text -observed / deterministic ~= sqrt(rho2) / (Gamma * sqrt(B)) -``` - -so the triangle bound is still pessimistic by about `3.6x` at `B = 4`, -`5.1x` at `B = 8`, `7.2x` at `B = 16`, and `10.2x` at `B = 32`. -It is much tighter than the old L∞ envelope (roughly `30x` to `200x` loose on -these runs), but not tight enough to replace a certified Euclidean bound. - -**Honest second-moment bound** - -```text -E ||z||_2^2 <= rho2 * sum_i ||s_i||_2^2 -``` - -Equivalently, with per-coordinate source second moment `mu2`: - -```text -E[z_rms^2] <= rho2 * B * mu2 -``` - -When `mu2_implied` is computed from the same sample, `honest_rms` matches -`z_rms` by construction. -The substantive content is therefore in `mu2_implied` itself: - -- One-hot terminal levels: `mu2_implied ~ 0.00682` (`fp32`) or - `~ 0.00390` (`fp128`). -- Dense recursive levels: `mu2_implied` varies by level and field, typically - rising from tens to about `102` in the deepest `fp32` levels logged here. - -**Interpretation for planner work.** - -- Do not price Euclidean security from `sqrt(coeffs) * beta_linf`; the old - envelope is far too loose even when `||z||_2` is large in absolute terms. -- `Gamma * sum ||s_i||_2` is a usable worst-case skeleton, but honest data - sit at roughly `sqrt(rho2) / (Gamma * sqrt(B))` of that skeleton. -- The second-moment model tracks honest scaling when `sum_i ||s_i||_2^2` is - taken at the actual source blocks for each level. - One-hot and dense levels need different policies. -- Direct source-block L2 sum logging is the gating step before any of this - becomes planner input. - -## Design - -### Notation - -| Symbol | Meaning | -|--------|---------| -| `s` | Committed witness (A-role, Ajtai) | -| `z` | Fold response / folded witness: `z = Σ_i c_i · s_i` | -| `ẑ` | Decomposed digits of `z` at the next level | -| `z^{}` | Grouped folded-witness limb assembled from a contiguous group of `ẑ` digit planes | -| `β_inf` | Deterministic `‖z‖_inf` envelope ([`fold_witness_beta`]) | -| `ν` | `ring_subfield_norm_bound` | -| `b` | Original gadget basis `2^lb` | -| `B` (`b_grp`) | Grouped basis `b^g`, where `g` is the number of original `ẑ` digits per grouped limb | -| `R` | Grouped-limb count `ceil(K / g)`, `K = num_digits_fold` | -| `ell_h` | Lagrange four-square slack integers, `Σ_h ell_h^2 = B_l2 − Z_SQUARED`; committed as `ell_hat` | -| `a^{}` | Augmented limb family over the size-`(N+4)` domain (folded witness for `x < N`, slack at the tail) | -| `C_e` | Un-reduced base-`B` coefficient of the squared norm, `Σ_{r+s=e} }, a^{}>` | -| `T_e` | Public base-`B` digit of the bound, `B_l2 = Σ_e B^e T_e` | -| `h_e` | Signed carry, `C_e + h_e − T_e − B·h_{e+1} = 0`, `h_0 = h_E = 0`; committed as `carry_hat` | -| `δ_carry(e)` | Balanced digit cells committed for `h_e` (base-2 weights); realizable budget `H'_e = (b/2)(2^{δ_carry}−1) ≥ H_e` | -| `α` | Challenge-field randomizer folding the limbs and carries into one sumcheck | -| `Z_α` | `α`-weighted recomposition `Σ_j α^j a^{}`, the squared-sum sumcheck's polynomial | - -Do not confuse `z` with `ŵ` (D-role opening witness). - -### Security object (Lemma 7, L2 instantiation) - -Weak binding prices the **fold response** `z`, not committed `s`: - -```text -‖z_A‖_2 ≤ 8 · op_norm(c) · ‖z‖_2 · ν -``` - -with `op_norm(c)` realized as `ω = ‖c‖_1` for sizing today. - -### Layer 1 — L2 MSIS table lookup (shipped) - -Convert the Lemma-7 collision into the Euclidean SIS floor per ring row: - -```text -collision_A_inf = 8 · ω · β_inf · ν, -collision_l2_sq = lookup_L2(d, collision_A_inf). -``` - -`lookup_L2` is `collision_l2_sq_for_linf_envelope` in `ajtai_key.rs`: prefer the -tabulated derived key `K = d · B²` with `B = ceil_coeff_linf_bucket(linf)` (same -coefficient-`L∞` ladder as pre-cutover main), else round `d · linf²` up to the next -generated power-of-two bucket. - -`committed_fold_collision_l2_sq` / `rounded_up_collision_norm_s` in -`crates/akita-types/src/sis/norm_bound.rs` call this path. -B/D roles pass digit collisions `2^lb − 1` through the same helper. - -### Layer 2 — Deterministic `‖z‖_2` envelope (shipped, pre-certificate) - -No realized `‖z‖_2` certificate in production yet. The planner bounds -`‖z‖_inf` by `β_inf` and converts to L2 for the estimator: - -```text -β_inf = fold_witness_beta(...) - = num_claims · 2^block_index_bits · - min(||c||_inf · ‖s‖_1, ‖c‖_1 · ‖s‖_inf), - -‖z‖_inf ≤ β_inf, -‖z‖_2 ≤ √d · β_inf (hence collision_l2_sq = lookup_L2(d, 8ωβ_inf ν)). -``` - -`β_inf` is shared with `num_digits_fold` and prover -`validate_decompose_fold` (`DecomposeFoldWitness.centered_inf_norm`). - -Operator-norm rejection (`gamma(c) <= Gamma`) is a separate challenge-family -contract. No Lemma-7 factor (`8`, `ν`, fold arity, or `β_inf`) may be dropped -or replaced by a decoupled `Gamma · B · ‖s‖_2` triangle bound. - -B-role and D-role collisions stay at `2^lb − 1` with the same -`‖v‖_2^2 ≤ d · ‖v‖_inf^2` conversion. - -### Realized-certificate tier (default, transparent and ZK) - -The certificate certifies the **fold response** `z`, not committed `s`. -It proves the integer inequality - -```text -Z_SQUARED = sum_{row, coeff} z[row][coeff]^2 <= B_l2 -``` - -without revealing `Z_SQUARED` or any folded-witness inner product, in both -transparent and ZK builds. -When a certificate is emitted, the prover chooses a bucket `B_l2` from the L2 -MSIS ladder with `Z_SQUARED <= B_l2`. The deterministic ceiling (no-wrap gate -fallback when no certificate is emitted) is - -```text -Z_SQUARED <= L2_BOUND_SQUARED -``` - -derived from the same `β_inf` / digit-range contract as `num_digits_fold`: -each coefficient of `z` is bounded by `balanced_digit_max(lb, num_digits_fold)`, -so - -```text -L2_BOUND_SQUARED = coeffs · balanced_digit_max(lb, num_digits_fold)^2 -``` - -This bounds **`z`**, never `‖s‖_2` or any per-block `s_l2_max` surrogate. - -Until this path ships, A-role table lookup uses only Lemma 7 plus -`collision_l2_sq_for_linf_envelope` on `8 · ω · β_inf · ν` (Layer 1–2 above). No -`Gamma · B · ‖s‖_2` triangle bound is used for security sizing. - -### Grouped-Carry L2 Certificate - -The realized certificate proves `Z_SQUARED <= B_l2` directly from the committed -digit planes of `z`, without forming a single wrapped field sum and without -revealing any inner product. -It is the default on every certifying level in both transparent and ZK builds. - -First convert the inequality to an equality with Lagrange four-square slack: - -```text -sum_i z[i]^2 + sum_{h=0}^{3} ell_h^2 = B_l2. -``` - -The slack integers `ell_0..ell_3` are committed as balanced base-`b` digit planes -`ell_hat` inside `w_next`, exactly like `z_hat`. -Because `ell_h^2 >= 0`, the equality implies `sum_i z[i]^2 <= B_l2`. - -Let `K = num_digits_fold`, `b = 2^lb`, and write the committed fold digits as - -```text -z[i] = sum_{d=0}^{K-1} b^d · z_hat_d[i], -``` - -each `z_hat_d[i]` a balanced digit already range-checked by stage 1. -Choose a deterministic group size `g >= 1`, set the grouped basis `B = b^g`, -`R = ceil(K / g)`, and `g_j = min(g, K - jg)` for the last short group. -The grouped limb is a fixed linear view of the committed digits: - -```text -z^{}[i] = sum_{t=0}^{g_j-1} b^t · z_hat_{jg+t}[i], so z[i] = sum_{j=0}^{R-1} B^j · z^{}[i]. -``` - -Apply the same grouping to each slack integer `ell_h`, and append the four slack -values as four extra coordinates at the tail of the certified domain (length -`N + 4`, `N = coeffs`), so one augmented limb family covers witness and slack: - -```text -a^{}(x) = z^{}[x] for x < N, -a^{}(N + h) = ell_h^{} for 0 <= h < 4. -``` - -This notation is intentionally tied to `z`. -Do not call the grouped limb `u` in the paper or code, because `u` is too easy to -confuse with outer commitment notation. -Suggested code names are `FoldNormGrouping`, `group_digits`, `group_log_basis`, -`grouped_fold_limb`, and `carry_limbs`. - -The squared norm is then a polynomial in the grouped basis `B`: - -```text -sum_i z[i]^2 + sum_h ell_h^2 = sum_e B^e · C_e, - C_e = sum_{r+s=e} }, a^{}> (ordered pairs, so cross terms count twice). -``` - -The `C_e` are the un-reduced base-`B` coefficients of the wide squared norm. -Each is a small signed integer (bounded by `D_e`; see the gate below) and **none -is ever revealed**. - -**One squared-sum sumcheck.** -Squeeze one challenge `alpha` from the challenge (extension) field after `z_hat`, -`ell_hat`, `carry_hat`, and `B_l2` are transcript-bound. -Define the `alpha`-weighted recomposition, a single polynomial that is a public -linear view of the committed digits: - -```text -Z_alpha(x) = sum_{j=0}^{R-1} alpha^j · a^{}(x). -``` - -Since `sum_x Z_alpha(x)^2 = sum_{r,s} alpha^{r+s} }, a^{}> = sum_e alpha^e C_e`, -the only quadratic obligation is the single sumcheck - -```text -sum_x Z_alpha(x)^2 = V. -``` - -This one degree-2 instance forms the full ordered-pair convolution implicitly, so -no pairwise inner product is ever materialized or sent: the proof carries the -masked `V` and round polynomials, not `O(R^2)` (or upper-triangular `O(R^2/2)`) -pair claims. The prover forms each honest `C_e` from the upper triangle (`r <= s`, -cross terms doubled) as a constant-factor speedup with no proof impact. - -This has the same shape as the field-fitting sumcheck `sum_x z_aug(x)^2 = B_l2`; -the differences are the digit weights (`alpha^j · b^t` instead of `b^d`) and that -the claimed sum `V` is private and tied to the carries below instead of equal to -the public `B_l2`. - -**Carry reconciliation, folded by the same `alpha`.** -Let `T_e` be the public base-`B` digits of the bound (`B_l2 = sum_e B^e T_e`) and -let `h_e` be signed carries with `h_0 = 0`, `h_E = 0`, satisfying - -```text -C_e + h_e - T_e - B · h_{e+1} = 0 for every e, -``` - -whose telescoping gives `sum_e B^e C_e = B_l2`. -The carries are committed as balanced base-`b` digit planes `carry_hat` inside -`w_next`. -Folding all carry equations by the same `alpha` reuses the sumcheck's claimed sum: - -```text -V = sum_e alpha^e C_e = sum_e alpha^e T_e + sum_e alpha^e (B · h_{e+1} - h_e). -``` - -The first right-hand term is a public scalar; the second is a fixed public-linear -view of the committed carries, discharged by one short `ceil(log2 E)`-round linear -claim that reduces to `carry_hat(rho_c)` (batchable into the stage-2 opening). -The individual `C_e` and `h_e` are never sent; only the masked `V` and the masked -limb / carry evaluations appear, so the certificate's sole public scalar is -`B_l2`. - -**Field-fitting realization.** -When the whole squared sum and the bound fit the field, - -```text -coeffs · balanced_digit_max(lb, K)^2 + 4 · B_l2 < q, -``` - -no grouping or carries are needed: the prover proves `sum_x z_aug(x)^2 = B_l2` -directly with `z_aug = z || ell_0..ell_3` and the public claimed sum `B_l2`. -This is the degenerate single-coefficient instance of the certificate and shares -its machinery (one degree-2 sumcheck plus the `ell_hat` virtualization); the -grouped-carry realization adds only `alpha`, `carry_hat`, and the folded carry -claim. - -### Group Selection And No-Wrap Gate - -Soundness requires every coefficient `C_e` and every carry `h_e` to be exactly -recoverable as integers, so that each field carry equation is an integer -equation. - -Structural coefficient bounds (every balanced digit lies in `[-b/2, b/2 - 1]`, -the same per-coefficient bound `‖s‖_inf = b/2` the scheme already relies on for -committed digits): - -```text -A_j = (b/2) · (b^{g_j} - 1) / (b - 1) (folded-witness limb j) -A^ell_j = the same bound for the slack limbs -D_e = sum_{r+s=e} [ N · A_r · A_s + 4 · A^ell_r · A^ell_s ] (ordered pairs) -``` - -The honest carry recurrence `h_0 = 0`, `h_{e+1} = (C_e + h_e - T_e) / B` gives the -smallest sound magnitude budget `H_0 = 0`, -`H_{e+1} = ceil( (D_e + H_e + (B - 1)) / B )`. -`H_e` is in general **not** a power of `B` (it is a ceiling of a ratio), so the -carry is never range-checked against `H_e` directly. -Each carry is committed as a balanced-digit cell run inside `carry_hat` with public -base-2 recomposition weights, `h_e = sum_k 2^k · carry_hat[e][k]`, where every cell -is an ordinary balanced digit (`|cell| <= b/2`). -The realizable, power-of-two-granular budget is then - -```text -H'_e = (b/2) · (2^{delta_carry(e)} - 1), -``` - -and `delta_carry(e)` is the smallest cell count with `H'_e >= H_e` (completeness). -Because the cells are ordinary balanced digits, their per-cell bound is exactly the -one the scheme already enforces on `z_hat`; the carry segment adds no new range -obligation, only a different public weight vector in the carry virtualization. - -Then `|C_e| <= D_e` and `|h_e| <= H'_e`, so the carry residual -`res_e = C_e + h_e - T_e - B · h_{e+1}` obeys -`|res_e| <= D_e + H'_e + (B - 1) + B · H'_{e+1}`. -The level accepts the grouped-carry certificate only if, for every exponent `e`, - -```text -D_e + H'_e + (B - 1) + B · H'_{e+1} < q, -``` - -where `q` is the characteristic of the accumulation field. -Under this gate the `alpha`-folded carry claim, which forces `res_e ≡ 0 (mod q)`, -forces `res_e = 0` as an integer, because the only multiple of `q` with absolute -value below `q` is `0`. - -Base-2 carry weights keep `H'_e` within a factor 2 of the tight `H_e`. -Reusing the gadget weights `b^k` for carries would round each budget up to a -base-`b` boundary (up to a factor `b`), inflating the dominant `B · H'_{e+1}` term -by roughly `b` and costing about `lb` bits of certifying headroom. -The carry segment is tiny (about `2R - 1` carries, each `delta_carry` cells, versus -`N >= 10^6` witness cells), so the finer base-2 weighting is essentially free in -witness size. - -The gate is structural and public. -It is checked from level parameters before any carry value is trusted as an -integer; it is not enough that the honest realized values happen to be small. - -The level selects its realization deterministically from public parameters: - -```text -if coeffs · balanced_digit_max(lb, K)^2 + 4 · B_l2 < q: - field-fitting realization (no grouping, no carries) -else: - choose the largest g in 1..K-1 such that the per-exponent gate holds for all e; - if some g works: grouped-carry realization with that g - else: no certificate; price A-role at L2_BOUND_SQUARED -``` - -The largest valid `g` minimizes `R`, hence the carry count `E` and the carry -witness `carry_hat`. -The gate's binding terms are `D_e` and `B·H'_{e+1}`, both of order -`R · N · (b/2)^2` at the middle exponent, so single-digit grouping (`g = 1`) -certifies up to roughly `N ~ q / (R · b^2)` coefficients. -With proof-optimized `lb = 3`, `q ≈ 2^31`, `D = 64`, that is on the order of -`10^4`–`10^5` D64 rings per level (decreasing as `R = num_digits_fold` grows), so -typical fp31 / fp32 dense recursive levels certify rather than fall back; only the -largest levels hit the fallback. - -Extension fields do **not** widen the gate. -`F_{q^k}` has characteristic `q`, so every base-embedded coefficient still reduces -modulo `q`. A larger base prime widens the gate; an extension over the same base -prime does not. - -### Sumcheck And Virtualization - -The certified statement is about the recomposed integer folded witness, but the -committed object is `w_next`, whose `z_hat`, `ell_hat`, and `carry_hat` segments -hold the base-`b` digit planes. -The certificate has three algebraic parts, all tied back to that one commitment: - -1. the single degree-2 squared-sum sumcheck `sum_x Z_alpha(x)^2 = V`; -2. the folded carry claim - `V = sum_e alpha^e T_e + sum_e alpha^e (B·h_{e+1} - h_e)`; and -3. a linear virtualization tying every evaluation the first two produce to the - committed digit planes of `w_next`. - -The squared-sum sumcheck reduces to the single evaluation `Z_alpha(rho)`. -This is a public linear view of `z_hat` and `ell_hat`: with the digit-major -layout and segment offsets used by `emit_z_folded_block_inner` and the -`fold_gadget = gadget_row_scalars(depth_fold, log_basis)` family, fold digit -`df = jg + t` inside group `j` carries the public weight `alpha^j · b^t`, and the -slack digits carry the analogous scalar gadget weights, with zero outside the -`z_hat` / `ell_hat` segments. - -The carry claim reduces (via one short `ceil(log2 E)`-round linear sumcheck, or by -batching into the stage-2 point) to `carry_hat(rho_c)`, a public linear view of -the `carry_hat` segment: reindexing `sum_e alpha^e (B·h_{e+1} - h_e)` puts weight -`B · alpha^{e-1} - alpha^e` on carry `h_e`, and each carry expands as -`h_e = sum_k 2^k · carry_hat[e][k]`, so cell `(e, k)` carries the public weight -`(B · alpha^{e-1} - alpha^e) · 2^k`. - -Both `Z_alpha(rho)` and `carry_hat(rho_c)` are discharged onto the existing -`w_next` opening. -They may be merged into the stage-2 opening point when the final `w_next(rho')` -claim can be shared, or kept as adjacent structured linear claims at separately -derived points; the proof shape and descriptor bind the choice. -Either way the certified object is the same committed `w_next`, so a prover cannot -certify one set of digit planes and commit a different recursive witness. - -### Stage Placement And Batching - -The certificate's only nonlinear part is the one squared-sum sumcheck; everything -else is linear in `w_next`. -Certifying levels therefore add, relative to a deterministic level: - -- `ell_hat` and (grouped-carry only) `carry_hat` trailing segments of `w_next`, -- the masked claimed sum `V` (the field-fitting realization uses the public - `B_l2` instead), -- the squared-sum sumcheck transcript fused into stage 1, and -- the carry linear claim plus limb / carry virtualization, batched into stage 2. - -No grouped partial-sum payload is sent. -Each stage derives an unambiguous batching vector from its transcript point. -The descriptor binds the realization (field-fitting, grouped-carry, or -deterministic), the group size `g`, `R`, the carry exponent count `E`, the bound -digits `T_e` layout, and whether the carry / virtualization claims are merged into -the stage-2 point or carried adjacent. -The existing single `CHALLENGE_SUMCHECK_BATCH` scalar is kept only where the -transcript derives a full coefficient vector for every active claim at that stage; -the grouped-carry realization additionally squeezes `alpha` before the squared-sum -sumcheck. - -### Footguns For Implementation - -- Wire before squeeze. - `ell_hat` and `carry_hat` are committed through `next_w_commitment`, and `B_l2` - is transcript-bound, before `alpha` or any squared-sum / carry challenge is - squeezed. -- The no-wrap gate is on the carry residual, not the realized values. - Check `D_e + H'_e + (B-1) + B·H'_{e+1} < q` for every `e` from public parameters - (with the realizable carry budget `H'_e`) before trusting any carry equation as - an integer equation. -- Carries are signed, and bounded by the committed cell run, not by `H_e`. - `C_e` can be negative, so `carry_hat` is a balanced decomposition with public - base-2 recomposition weights. Size `delta_carry(e)` as the smallest cell count - with `H'_e = (b/2)(2^{delta_carry} - 1) >= H_e`, and evaluate the no-wrap gate - with `H'_e` (never with `H_e`). The cells are ordinary balanced digits, so they - need no range machinery beyond the existing `z_hat` digit bound; do not reuse the - `b^k` gadget weights for carries (that wastes ~`lb` bits of headroom). -- Boundary carries are fixed. - Enforce `h_0 = 0` and `h_E = 0`; the closing `h_E = 0` is what forces the total - to match `B_l2`. -- Slack can exceed `u64`. - On small fields `B_l2 - Z_SQUARED` can exceed `2^64`, so the four-square solver - needs a `u128` target path; the verifier must reject (not assume) any slack that - does not fit the encoded budget. -- No inner products are sent. - The certificate never serializes `P_{r,s}` or `Z_SQUARED`; only `B_l2`, the - committed digit growth, the masked `V`, and the sumcheck / carry transcripts - appear. Do not reintroduce a public-partial-sum path for transparent builds. -- Reuse the committed `z_hat` layout. - Limbs, slack, and carries must read the same `num_digits_fold` and physical - segment layout as `build_w_coeffs`; a second decomposition is allowed only if - the protocol also proves it recomposes to the committed planes. -- Terminal levels need an explicit policy. - They may use the same certificate if `z_hat` is committed in `w_next`, or must - fall back to deterministic pricing. - -### Operator-Norm Rejection Sampling - -For D=64 the initial production candidate is: - -```text -SparseChallengeConfig::signed-sparse { - count_mag1: 31, - count_mag2: 11, -} -operator_norm_threshold = 18 -``` - -The raw support is: - -```text -binom(64, 42) · binom(42, 31) · 2^42 ~= 2^130.152255. -``` - -To retain 128 accepted challenge bits, the proof must establish: - -```text -Pr[gamma(c) <= 18] >= 2^(128 - 130.152255...) ~= 0.225. -``` - -The implementation must not rely on machine floating-point FFTs to enforce -acceptance. -The reference predicate is the exact negacyclic convolution operator norm. -Let `M_D(c)` be the integer matrix for multiplication by `c` in -`Z[X] / (X^D + 1)`. -Equivalently, for the negacyclic roots -`zeta_j = exp((2j + 1) * pi * i / D)`, `0 <= j < D`, - -```text -gamma_D(c)^2 - = lambda_max(M_D(c)^T M_D(c)) - = max_j |sum_k c_k * zeta_j^k|^2. -``` - -The exact acceptance check is therefore: - -```text -accept(c) iff T^2 * I - M_D(c)^T M_D(c) is positive semidefinite over Q. -``` - -This check is dimension-generic for `D in {32, 64, 128}` and gives the -specification truth value. -It may be implemented by rational interval arithmetic over the DFT expression, -a fraction-free LDL/Sturm certificate for the PSD condition, or an offline -accepted-support certificate whose verifier checks the same predicate. - -The production path should use the DFT diagonalization with fixed-point integer -intervals. -Precompute signed `Q`-bit tables - -```text -C[j][k] ~= 2^Q * cos((2j + 1) * pi * k / D) -S[j][k] ~= 2^Q * sin((2j + 1) * pi * k / D) -``` - -with certified componentwise entry error at most `eps_root` in scaled integer -units. -For a candidate challenge, compute integer accumulators - -```text -R_j = sum_k c_k * C[j][k] -I_j = sum_k c_k * S[j][k] -A_j = R_j^2 + I_j^2. -``` - -Let `L1 = ||c||_1` and `r = L1 * eps_root`. -The true scaled real and imaginary parts obey - -```text -real(2^Q * c(zeta_j)) in [R_j - r, R_j + r], -imag(2^Q * c(zeta_j)) in [I_j - r, I_j + r]. -``` - -Thus a conservative integer upper bound is - -```text -upper_j = - A_j - + 2 * (|R_j| + |I_j|) * r - + 2 * r^2. -``` - -The sampler accepts only when - -```text -upper_j <= T^2 * 2^(2Q) -``` - -for every `j`. -If any frequency falls in the narrow interval band where the upper bound -rejects but the centered fixed-point value is close to the threshold, the -implementation may either reject the candidate or call the exact predicate. -Always accepting from the lower bound is forbidden unless the exact predicate -has been run. -If the implementation rejects the boundary band without exact fallback, the -accepted-support proof must be for this stricter fixed-point predicate, not for -the mathematical predicate `gamma_D(c) <= T`. - -This fast path is deterministic, integer-only, and works without changing the -transcript stream. -`D = 64` with `T = 18` is the first production target, but the same table -format should cover `D = 32` and `D = 128`. -Only one representative of each conjugate frequency pair needs to be checked, -though tests should compare the reduced loop against the full `0..D` formula. -Use `i128` accumulators for the current coefficient ranges and `D <= 128`; -the implementation must validate the worst-case accumulator and square bounds -at construction time. -With, for example, `Q = 48`, `D <= 128`, and `L1 <= 256`, the table error term -is far below one unit in the unscaled operator norm, so the exact fallback -should trigger only for candidates extremely close to the threshold. - -The sampler must consume transcript randomness in a stable way. -Rejected candidates are not allowed to create prover/verifier divergence. -The challenge domain separator must include the signed sparse parameters and -operator-norm threshold. - -### Folded-Witness ∞-Norm Rejection (digit-count tightening) - -This is a stacked follow-on to #155, not part of the L2 rank pricing. -Operator-norm rejection (above) and the L2 certificate price the **A-role rank**; -this section instead tightens the **digit count** `num_digits_fold` of the next -recursive witness `z_hat`, which is sized by the `‖z‖_inf` envelope `β_inf` and is -orthogonal to the A-role collision bound. -The analysis is specific to the D=64 signed-sparse family. - -**What sizes the digit count today.** -`z` enters the next level only through its balanced base-`b` digit planes `z_hat`, -and the plane count `K = num_digits_fold` is what stage 1 turns into the structural -per-coordinate bound `balanced_digit_max(lb, K) = (b/2)·(b^K − 1)/(b − 1)` -([`decomposition_digits.rs::num_digits_fold`]). `K` is chosen so - -```text -balanced_digit_max(lb, K) >= β_inf - = fold_witness_beta(...) - = num_claims · 2^block_index_bits · min(‖c‖_inf · ‖s‖_1, ‖c‖_1 · ‖s‖_inf) -``` - -i.e. `β_inf = T_p · ω · σ_inf` in the worst case (`T_p = num_claims · 2^block_index_bits`, -`ω = ‖c‖_1`, `σ_inf = ‖s‖_inf`). This worst case assumes all `T_p · ω` -challenge-coefficient products align in sign at one output coordinate, which the -honest fold never attains. The prover already aborts when the realized -`‖z‖_inf` exceeds `β_inf` ([`ring_relation.rs::validate_decompose_fold`]). - -**Rejection-sampled tightening.** -Replace the abort with a transcript-bound grind: re-derive the fold challenge from -an incremented nonce, re-fold, and accept the first `z` with `‖z‖_inf <= t` for a -threshold `t < β_inf`. A level then commits the smallest `K` with -`balanced_digit_max(lb, K) >= t`, which crosses a base-`b` digit boundary wherever -`t` and `β_inf` straddle a power of `b`. - -**Why it terminates in poly time (D=64).** -The D=64 signed sparse `(count_mag1, count_mag2)` places `count_mag1` coordinates of -magnitude 1 and `count_mag2` of magnitude 2 on a uniform support, each nonzero -coordinate carrying an *independent uniform sign* (`sample_signed_sparse_challenge`, -`XofCursor::next_sign`). For production `(30, 12)`, `ω = ‖c‖_1 = 54` and the -energy `rho2 = ‖c‖_2^2 = 30 + 4·12 = 78` are fixed (every member meets -`rho2 <= ‖c‖_inf · ‖c‖_1 = 108`). - -Fix an output coordinate `r` of `z = sum_{(l,i)} c_{l,i} * s_{l,i}` (the fold of -`T_p` blocks). Expanding the negacyclic products, - -```text -z_r = sum_{(l,i)} sum_{a in supp(c_{l,i})} eps_{l,i,a} · m_{l,i,a} · (± s_{l,i, r⊖a}), -``` - -a signed sum of the independent signs `eps_{l,i,a}` with weights of magnitude -`m_{l,i,a} · |s| <= m_{l,i,a} · σ_inf` (`m = |c| in {1, 2}`). Conditioned on every -support and magnitude pattern, `z_r` is a zero-mean Rademacher sum with variance -proxy - -```text -V_r = sum_{(l,i)} sum_a m_{l,i,a}^2 · s_{l,i, r⊖a}^2 - <= σ_inf^2 · sum_{(l,i)} ‖c_{l,i}‖_2^2 - <= T_p · rho2 · σ_inf^2 =: V. -``` - -Hoeffding for Rademacher sums gives `Pr[|z_r| > t | support, magnitudes] <= -2·exp(−t^2 / 2V)` for every conditioning, hence unconditionally, and a union bound -over the `N = coeffs` coordinates yields the tail - -```text -Pr[‖z‖_inf > t] <= 2·N·exp(−t^2 / 2V). (T) -``` - -Let `p = Pr[gamma(c) <= Gamma]` be the operator-norm acceptance probability -(`p = 1` when the cap does not bind; the production `(30, 12)` ships with no -threshold, so `p = 1`). For challenges from the accepted distribution, Bayes -against (T) on the unconditioned event gives - -```text -Pr[‖z‖_inf > t | all T_p blocks accepted] <= Pr[‖z‖_inf > t] / p^{T_p} - <= (2N / p^{T_p}) · exp(−t^2 / 2V), -``` - -so taking - -```text -t >= t* = sqrt( 2V · ln(4N / p^{T_p}) ) - = sqrt( 2 · T_p · rho2 · σ_inf^2 · (ln 4N + T_p · ln(1/p)) ) -``` - -makes the conditional miss probability at most 1/2. Each accepted challenge then -yields `‖z‖_inf <= t*` with probability at least 1/2, so the grind re-folds at -most twice in expectation (poly time). At `p = 1` this is just -`t* = sqrt(2V · ln 4N)`; a binding cap adds the loose `T_p · ln(1/p)` term (the -price of the Bayes step), which keeps termination in `O(1)` expected re-folds for -any constant `p`. - -**Soundness is unchanged.** -The verifier never reads the accepting nonce as evidence that `‖z‖_inf <= t*`. It -reads the bound off the committed digits: the stage-1 range check already forces -`|z_r| <= balanced_digit_max(lb, K)`, and the level published `K` before the fold. -The CWSS extractor inspects only accepting transcripts and never how `c` was -sampled, so narrowing the challenge support by the two rejection layers changes -nothing it recovers; the grind's bias on the challenge distribution is absorbed -into the standard Fiat-Shamir knowledge error `(Q+1)·κ` for the `Q` random-oracle -queries an adversary makes, the only contract being that the accepted support -retains `λ + log2 Q` bits (Accepted-challenge entropy invariant). Lowering `K` -tightens the `‖z‖_inf` the verifier structurally enforces without touching -binding. - -**How much is gained (D=64), and the gap to honest folds.** -At `p = 1`, - -```text -t* / β_inf = sqrt(2 · rho2 · ln 4N) / (ω · sqrt(T_p)), -``` - -independent of `σ_inf` and growing only as `sqrt(ln N)`. For `(rho2, ω) = -(78, 54)` and `N ≈ 2^16`, this is `≈ 0.41, 0.29, 0.20, 0.14` at fold widths -`T_p = 4, 8, 16, 32`, so the rigorous threshold sits inside one base-`b` digit of -the worst case at the wider folds. It is loose against the measured folds in the -calibration tables above by roughly another order of magnitude, because `V` charges -every source coordinate at the worst case `σ_inf` while honest source blocks are -far smaller in mean square (`mu2_implied`). Production thresholds are calibrated -against the realized response (the `z_rms` / `mu2_implied` tables) and are -correspondingly tighter; (T) is only what guarantees termination. - -**Transcript and planner consequences (later slices).** -- The grind nonce is bound before the challenge is squeezed (wire-before-squeeze), - exactly like the op-norm rejection stream, so the verifier replays it - deterministically and re-derives the same challenge. -- The threshold policy `t(level, family)` feeds `β_inf` / `num_digits_fold`, must - be planner-visible (it changes the schedule DP where a lowered `K` crosses a - `2^lb` boundary), and is bound in the instance descriptor. -- `validate_decompose_fold` becomes the grind loop with a capped attempt count; - exceeding the cap is a prover-only error (not verifier-reachable). - -### SIS Tables And Planner - -The current SIS tables are keyed by a rounded coefficient `L∞` collision bucket. -The cutover needs generated L2 MSIS tables keyed by the Euclidean bound used in -the security model. - -Required changes: - -- Rename table fields away from `collision_inf`. -- Generate audited L2 bucket ladders and secure-rank floors. -- Update `AjtaiKeyParams` to carry the L2 bound name and descriptor bytes. -- Update `LevelParams`, schedule entries, generated-family tables, and runtime - DP fallback to use L2 bounds. -- Delete the committed-fold L∞ *rank* derivation after all call sites move. - Retain the folded-witness L∞ bound `fold_witness_beta` and the prover's - `beta_linf_fold_bound` / `validate_decompose_fold` abort: they no longer price - the A-role rank, but they still size the digit count of the next recursive - witness `z_hat` (`num_digits_fold` depends on `||z||_inf`). -- Keep the B-role and D-role opening-digit collisions at their natural - coefficient bound `2^lb - 1` (the difference of two balanced digits), and - convert each into the unified L2 table by `||v||_2 <= sqrt(d) · ||v||_inf`. - The generated tables and public docs must state this conversion explicitly so - a single L2 MSIS floor covers all three roles. - -### Public Security Model Documentation - -The public repo documentation must change together with the code. -At minimum: - -- Replace the current `MSIS_{q,d}(n,m,eta)` definition using - `||z||_inf <= eta` with the Euclidean norm used by the implementation. -- State the accepted challenge distribution and its min-entropy after rejection. -- Define `gamma(c)` as the negacyclic convolution operator norm. -- State that A-role sizing uses the existing Lemma 7 bound converted by - `||v||_2^2 <= d · ||v||_inf^2` (no alternate weak-binding derivation). -- State the grouped-carry folded-witness certificate, the per-exponent no-wrap - gate, and why each carry residual that is zero modulo `q` is an exact integer - zero (certificate tier). -- Explain the full cutover and remove superseded L∞ **estimator** language while - keeping the Lemma 7 collision formula. - -## Architecture - -### Data Flow - -```text -sample accepted c_i with gamma(c_i) <= Gamma - | - v -decompose_fold: centered_coeffs for z = sum_i c_i * s_i - | - +--> z_hat digit planes - | | - | +--> select realization + FoldNormGrouping from public params - | | - | +--> four-square slack ell -> ell_hat ; carries h -> carry_hat - | | - | +--> squeeze alpha ; squared-sum sumcheck sum_x Z_alpha(x)^2 = V - | | - | +--> carry claim V = sum_e alpha^e T_e + - | | - | v - | virtualization onto committed z_hat/ell_hat/carry_hat in w_next - | - +--> z_folded_rings (z_hat), w_hat, t_hat, r_hat, ell_hat, carry_hat - | - v -build_w_coeffs (w_next) -> commit next w -> stage 1 -> stage 2 (+ L2 sumchecks) -``` - -### Affected Files - -Likely primary files: - -- `crates/akita-challenges/src/config.rs` -- `crates/akita-challenges/src/sampler/` -- `crates/akita-types/src/sis/norm_bound.rs` -- `crates/akita-types/src/sis/ajtai_key.rs` -- `crates/akita-types/src/sis/generated_sis_table/` -- `crates/akita-types/src/sis/decomposition_digits.rs` -- `crates/akita-types/src/layout/params.rs` -- `crates/akita-types/src/proof/levels.rs` -- `crates/akita-types/src/proof/shapes.rs` -- `crates/akita-types/src/proof_size.rs` -- `crates/akita-planner/src/schedule_params.rs` -- `crates/akita-config/src/proof_optimized.rs` -- `crates/akita-prover/src/lib.rs` -- `crates/akita-prover/src/protocol/ring_relation.rs` -- `crates/akita-prover/src/protocol/ring_switch/coeffs.rs` (`emit_z_folded_block_inner` - is the `z_hat` digit-plane source for grouped limbs) -- `crates/akita-types/src/proof/ring_relation.rs` (`segment_layout`: z-first column - order exposes the committed `z_hat` offset for grouped virtualization) -- `crates/akita-prover/src/protocol/sumcheck/akita_stage2/` -- `crates/akita-verifier/src/protocol/slice_mle/setup_contribution.rs` - (`compute_setup_contribution` / `fold_gadget`: the structured-matrix evaluation - the `G'` virtualization reuses) -- `crates/akita-verifier/src/stages/stage2.rs` -- `crates/akita-verifier/src/protocol/levels.rs` -- `scripts/gen_sis_table.py` -- `specs/weak-binding-norm-fix.md` - -## Alternatives Considered - -### Keep L∞ SIS And Add L2 As An Optimization Hint - -Rejected. -If security still uses L∞, the L2 proof does not improve SIS ranks. -It only adds proof bytes. - -### Use Honest Average L2 Norms Without A Certificate - -Rejected. -The extractor needs a bound on accepted adversarial transcripts, not on an -honest simulation distribution. -Experiments are useful for selecting thresholds and estimating prover abort -rates, but they are not a security argument. - -### Use Only Operator-Norm Challenge Rejection - -Rejected as incomplete. -`gamma(c) <= Gamma` bounds multiplication as an operator, but the proof still -needs the folded response to be short under the new MSIS norm. -The verifier must either see or certify the relevant folded-witness L2 bound. - -### Keep Both L∞ And L2 Schedule Tables - -Rejected. -This repo makes no backward-compatibility guarantee, and dual schedule tables -would invite drift between the security model, planner, prover, and verifier. -The cutover should replace the old path. - -### Publish Grouped Partial Sums In The Clear (transparent-only) - -Rejected as the default. -Publishing the `P_{r,s}` partial sums avoids slack and carries, but it leaks the -full digit-group Gram matrix of the folded witness, so it cannot be the ZK path -and would force two certificate protocols. -The grouped-carry certificate sends no inner products, costs only `ell_hat` / -`carry_hat` plus one short linear claim more than the field-fitting case, and is a -single design for transparent and ZK builds, so it is preferred even though the -public-partial-sum variant is marginally simpler on large fields. - -## Execution - -The work decomposes into 13 slices across six tracks (challenge family, L2 SIS, -proof shape, prover, verifier, planner/transcript/tests). -Four slices are independent and can start immediately; the rest serialize behind -the L2 norm/table API (S4, S5) and the proof-shape change (S6). - -Status: S1 (`crates/akita-challenges/src/sampler/op_norm.rs`), S7 -(`crates/akita-types/src/sis/four_square.rs`), and the S4 L2 norm primitives -(`crates/akita-types/src/sis/norm_bound.rs`, squared-domain) are implemented as -pure, not-yet-wired building blocks on `main`. - -Implementation on branch `quang/s3-s5-sis-estimator-spec` (PR #155) and later slices: - -- **S5a** ([`sis-euclidean-estimator.md`](sis-euclidean-estimator.md)): upstream - lattice-estimator reliability fixes, vendored LE PR branch submodule, hardened - `scripts/gen_sis_table.py`, and Akita golden. *(Done in #155.)* -- **S5b** (same #155): L2 table regen + stitch (pow2 ladder + derived `d·B²` keys), - `collision_l2_sq` rename, wire A/B/D pricing through `collision_l2_sq_for_linf_envelope`. - *(Done in #155.)* -- **S3**: operator-norm threshold + transcript rejection. - **Production D=64 cutover landed** in [#207](https://github.com/LayerZero-Labs/akita/pull/207) - (`(31, 11), T = 18`, per-level gating, `2^12` sparse-draw cap, fused predicate, - `fp128_d64_*` regen). Vendored S2 ≥128-bit acceptance cert still open. -- **S6, S8–S13**: proof shape, certificate, planner schedules, e2e (unchanged). - -### Decisions To Lock (gating) - -These are the former Phase 0 items. -Each gates specific slices, noted in parentheses. - -- L2 MSIS definition and estimator input convention, including the B/D - `||v||_2 <= sqrt(d)·||v||_inf` conversion into the single L2 table. (S4, S5) -- D=64 signed-sparse operator-norm acceptance lower bound, and the fallback if it - lands below `0.225` (larger shell or higher `T`). (S2) -- Production D=64 shell and threshold: **`(31, 11), T = 18` shipped** in - [#207](https://github.com/LayerZero-Labs/akita/pull/207) (per-level `op_norm_rejection` - gating, witness-scoring cost, `2^12` sparse-draw cap). - Vendored S2 accepted-support lower bound ≥128 bits remains a follow-up artifact. -- Certificate `Z_SQUARED` ceiling from `β_inf` and `balanced_digit_max` per - level (not `‖s‖_2` surrogates). (S4, S8) -- Certificate placement: whether the limb / carry virtualization claims are - merged into the stage-2 point or kept adjacent at a separately derived point. (S9) -- The per-exponent no-wrap gate `D_e + H'_e + (B-1) + B·H'_{e+1} < q` for every - convolution exponent (`H'_e` from the committed carry cell run), the realization - selection (field-fitting vs grouped-carry), and the per-level fallback to the - deterministic bound when no group size satisfies the gate. (S8, S10) -- The canonical Euclidean MSIS estimator and table-generation command: see - [`sis-euclidean-estimator.md`](sis-euclidean-estimator.md) (S5a). (S5b consumes its output.) - -### Slice Dependency Graph - -```text -WAVE 0 (independent, start now, parallel) - S1 op-norm predicate gamma_D(c) <= T [akita-challenges, pure] DONE - S7 four-square slack helper (default path) [pure algorithm] DONE - S4 L2 norm primitives (Lemma 7 + l2_sq_from_linf) [akita-types::sis] DONE - S2 D=64 support lower bound >= 128 bits [research / certificate] - -WAVE 1 - S5a lattice-estimator pin + gen_sis_table (spec: sis-euclidean-estimator.md) DONE - S5b L2 SIS tables + collision_l2_sq rename (S4, S5a) #155 - S3 threshold + transcript rejection (S1) DONE (D64 prod) - S6 proof shape / serialization / size (parameterize B_l2 early) - -WAVE 2 - S8 prover certificate assembly (S4, S6, S7) - S11 planner + shipped tables + drift (S4, S5, S6) - S12 transcript instance-descriptor bind (S3, S5, S6) - -WAVE 3 - S9 squared-sum sumcheck + carry claim + virtualization (S6, S8) - S10 verifier replay + no-panic (S6, S9) - -WAVE 4 - S13 e2e tamper tests + ZK parity (all) -``` - -### Slices - -Each slice lists its crate/files, deliverable, and dependencies. -Per-slice test obligations are in the Testing Strategy section. - -**S1 — Exact operator-norm acceptance predicate.** *(independent, DONE)* -`crates/akita-challenges/src/sampler/op_norm.rs`. -Implements `gamma_D(c) <= T` as the integer DFT predicate: a certified `pi` -enclosure (Machin series in `i128`) feeds interval-Taylor cos/sin tables at scale -`2^q` carrying a sound `eps_root`; the predicate forms integer accumulators -`R_k, I_k` and accepts only when the conservative upper bound -`R_k^2 + I_k^2 + 2(|R_k|+|I_k|)r + 2r^2 <= T^2 2^{2q}` (with `r = ||c||_1 eps_root`) -holds for every reduced frequency, rejects when a lower bound already exceeds the -threshold, and reports the boundary band as indeterminate (treated as reject). -Dimension-generic for `D in {4, 32, 64, 128}`; worst-case `i128` accumulator and -square bounds validated at construction. No floating point on the decision path. - -**S2 — D=64 accepted-support lower bound.** *(independent, research)* -Establish a rigorous `>= 128`-bit accepted-support lower bound for shell -`(31, 11)` at `T = 18` (`Pr[strict_accept] >= 13/20` on Monte Carlo), as a checked certificate -artifact rather than full enumeration. -Decide the fallback (larger shell or higher `T`) if it lands short. -Gates the production policy in S3. - -**S4 — L2 norm primitives.** *(independent, DONE)* -`crates/akita-types/src/sis/norm_bound.rs`. -Adds `committed_fold_collision_l2_sq` / `rounded_up_collision_norm_s` (Lemma 7 on -fold response `z` via `β_inf = fold_witness_beta`, then `collision_l2_sq_for_linf_envelope`), -and the B/D `collision_l2_sq_for_linf_envelope` on `2^lb − 1` -(`||v||_2^2 <= d·||v||_inf^2`). Squared -domain keeps every value an exact `u128` integer (`sqrt(D)` is irrational for -`D ∈ {32, 128}`); the real square root is taken only at bucket/slack selection -(S8). `fold_witness_beta` prices both `num_digits_fold` and the A-role collision -through `β_inf`. Realized `Z_SQUARED` certificates are implemented in S8, not -here. - -**S7 — Four-square slack helper.** *(independent, DONE; on the default path)* -`crates/akita-types/src/sis/four_square.rs`. -Pure helper computing `ell_0..ell_3` with `sum ell_j^2 = B_l2 - Z_SQUARED`. A -Rabin–Shallit-style prime hunt is the fast path; a theorem-backed finite -two-squares-residual fallback makes the solver total. Integer-only decision path -(no floating point). -The four-square slack is committed as `ell_hat` on every realized level (not just -ZK), so the certificate proves an equality; small-field levels need a `u128` -target path because `B_l2 - Z_SQUARED` can exceed `2^64`. - -**S3 — Threshold + transcript-stable rejection sampling.** *(S1; production shell)* -`crates/akita-challenges/src/config.rs`, `sampler/exact_shell.rs`, `sampler/mod.rs`, -`sampler/op_norm_accumulate.rs` (transposed `i64` predicate, AVX2/NEON fusion), -`akita-types::sis::norm_bound` (Γ-vs-ω pricing, witness-scoring gate, `2^12` cap), -`akita-planner` (`choose_op_norm_rejection_for_a_role`, `expand` n_a audit), -`LevelParams.op_norm_rejection`. -Production D=64: `signed-sparse { count_mag1: 31, count_mag2: 11 }`, `T = 18`, -certified acceptance floor `13/20`, `fp128_d64_*` schedule regen. -**Landed** in [#207](https://github.com/LayerZero-Labs/akita/pull/207). Vendored S2 ≥128-bit acceptance cert remains open. - -**S5a — Euclidean SIS table regen (lattice-estimator).** *(done in #155)* -[`specs/sis-euclidean-estimator.md`](sis-euclidean-estimator.md). -Vendor the open lattice-estimator reliability PR branch as `third_party/lattice-estimator`, -harden `scripts/gen_sis_table.py`, and check in Akita-local golden CSV under -`scripts/sis_golden/`. Repoint to `malb/lattice-estimator` after upstream merge. No Rust -estimator crate. - -**S5b — L2 SIS tables + key rename.** *(S4, S5a; done in #155)* -`crates/akita-types/src/sis/{ajtai_key,generated_sis_table}.rs`. -Regenerate and stitch two key families: power-of-two buckets -(`2^MIN_LOG_BUCKET .. 2^MAX_LOG_BUCKET`) plus derived `K = d · B²` for -`COEFF_LINF_BUCKETS`; rename `collision_inf` to `collision_l2_sq` (`u128`) across -`AjtaiKeyParams`, `min_secure_rank`, `ceil_supported_collision`, and descriptor bytes; -route A/B/D norm-bound pricing through `collision_l2_sq_for_linf_envelope` (derived key -default, pow2 fallback). Remove the old committed-fold L∞ rank-pricing paths. Regen remains -Sage + `scripts/{gen_sis_table,stitch_generated_sis_table}.py` against the pinned submodule. - -**S6 — Proof shape, serialization, proof size.** *(parameterizable early)* -`crates/akita-types/src/proof/{levels,shapes}.rs`, `proof_size.rs`, -`proof/ring_relation.rs`. -Add the realization marker (field-fitting / grouped-carry / deterministic), the -`FoldNormGrouping` descriptor (`group_digits`, `group_count`, last-group width, -carry exponent count `E`, per-exponent carry cell counts `delta_carry`), the -`B_l2` scalar, trailing `ell_hat` / `carry_hat` offsets, the masked `V` claim, -shape validation, serialization tests, and the proof-size formula. No partial-sum -payload. -Parameterized on `B_l2`'s type, so it does not wait on S5's values. - -**S8 — Prover certificate assembly.** *(S4, S6, S7)* -`crates/akita-prover/src/protocol/ring_relation.rs`, `ring_switch/coeffs.rs`. -From `DecomposeFoldWitness.centered_coeffs`, compute `Z_SQUARED`, the four-square -slack `ell` (and `ell_hat`), select the realization and the largest group size -`g` satisfying the per-exponent no-wrap gate (evaluated with the realizable carry -budget `H'_e`), derive the carries `h` and decompose each into `delta_carry(e)` -balanced cells with base-2 recomposition weights (`carry_hat`), and fall back to -deterministic `L2_BOUND_SQUARED` when no `g` passes. Append `ell_hat` / -`carry_hat` to `w_next` and transcript-bind them and `B_l2` before squeezing -`alpha` (wire-before-squeeze). - -**S11 — Planner + generated tables + drift guards.** *(S4, S5, S6)* -`crates/akita-planner`, `crates/akita-config`. -Update the runtime DP, regenerate shipped schedules, update proof-size formulas, -run the generated-table drift guards, and retarget profile modes if the secure -family set changes. - -**S12 — Transcript instance-descriptor binding.** *(S3, S5, S6)* -`crates/akita-config` transcript binding. -Bind the active MSIS norm model, challenge family + operator-norm threshold, L2 -bound policy, certificate shape, the number and order of stage-2 claims, and the -schedule. -Pin the descriptor bytes with a test; a proof under L2 must not verify under old -L∞ parameters. - -**S9 — Squared-sum sumcheck + carry claim + virtualization.** *(S6, S8)* -`crates/akita-prover/src/protocol/sumcheck/akita_stage2/`, verifier -`slice_mle/setup_contribution.rs`. -Run the single degree-2 sumcheck `sum_x Z_alpha(x)^2 = V`, the folded carry claim -`V = sum_e alpha^e T_e + ` (a short linear sumcheck), then -discharge `Z_alpha(rho)` and `carry_hat(rho_c)` through linear virtualization onto -the committed `w_next` opening. Reuse `fold_gadget` / `compute_setup_contribution` -structured evaluation for the `z_hat` / `ell_hat` / `carry_hat` segments. -Certifying levels bind the active claim vector and whether the claims are merged -into stage 2 or carried adjacent. - -**S10 — Verifier replay + no-panic.** *(S6, S9)* -`crates/akita-verifier/src/stages/stage2.rs`, `protocol/levels.rs`. -Recompute the realization and no-wrap gate from public params, replay the -squared-sum sumcheck and carry claim, check `h_0 = h_E = 0`, validate `B_l2`, -`ell_hat`, and `carry_hat` lengths / digit bounds / offsets, confirm every -evaluation is anchored to the committed `w_next`, and reject every malformed -challenge / certificate / shape with `AkitaError` / `SerializationError`. - -**S13 — End-to-end + ZK parity.** *(all)* -End-to-end prover/verifier tests that fail under independent tampering of the -committed folded witness, `ell_hat`, `carry_hat`, `B_l2`, the next-witness -commitment, and the ring-relation rows. Because the certificate is one design for -both builds, the ZK path runs the same claims with masking on; a test asserts no -inner-product payload is serialized under `feature = "zk"`. - -## Open Questions - -1. Resolved: [`specs/sis-euclidean-estimator.md`](sis-euclidean-estimator.md) defines the - canonical offline regen path: general fixes in `malb/lattice-estimator`, pinned submodule, - `scripts/gen_sis_table.py`, and Akita-local golden checks (no in-repo Rust estimator). -2. Should the certified bucket `B_l2` be a fixed worst-case-per-level value, or - may the prover abort against a tighter `B_l2` with a separately proved - acceptance probability? -3. Resolved: the default realized certificate is the grouped-carry design. - It commits `ell_hat` (four-square slack) and `carry_hat` (carry limbs) in - `w_next`, proves one squared-sum sumcheck `sum_x Z_alpha(x)^2 = V`, and folds - the carry chain into one linear claim. It sends no inner products, so it is the - single design for transparent and ZK builds. -4. Resolved (virtualization worked out in "Sumcheck And Virtualization"): the - squared-sum sumcheck reduces to `Z_alpha(rho)` and the carry claim to - `carry_hat(rho_c)`, both discharged onto the committed `w_next` via the - existing `z_hat` / `ell_hat` / `carry_hat` digit layout and `fold_gadget` - weights. - The residual implementation choice is whether those linear claims are merged - into the existing stage-2 point or kept adjacent at a separately derived point. -5. Resolved: the B/D roles keep their coefficient `L∞` digit-collision bound - `2^lb - 1` and convert into the unified L2 table via - `||v||_2 <= sqrt(d)·||v||_inf` (see Invariants and SIS Tables And Planner). -7. Resolved: small-field (31/32-bit) realized L2 certificates use the - grouped-carry realization with the per-exponent no-wrap gate - `D_e + H'_e + (B-1) + B·H'_{e+1} < q` (`H'_e` the committed carry cell run's - realizable budget, base-2 weights), certifying rather than falling back on - typical fp31 / fp32 dense recursive levels. - -## References - -- `specs/sis-euclidean-estimator.md` (S5a: offline estimator + table regen) -- `specs/weak-binding-norm-fix.md` -- `crates/akita-types/src/sis/norm_bound.rs` -- `crates/akita-prover/src/protocol/ring_relation.rs` -- `crates/akita-prover/src/protocol/ring_switch/coeffs.rs` (`build_w_coeffs`) -- `crates/akita-prover/src/protocol/sumcheck/akita_stage2/mod.rs` -- `crates/akita-verifier/src/protocol/slice_mle/setup_contribution.rs` diff --git a/specs/archive/2026-Q2/sis-euclidean-estimator.md b/specs/archive/2026-Q2/sis-euclidean-estimator.md index 77a95f1ef..cd243379c 100644 --- a/specs/archive/2026-Q2/sis-euclidean-estimator.md +++ b/specs/archive/2026-Q2/sis-euclidean-estimator.md @@ -11,12 +11,12 @@ ## Summary -Akita's L2 MSIS table regen (archived parent: -[`specs/archive/2026-Q2/l2-msis-opnorm-folded-witness.md`](archive/2026-Q2/l2-msis-opnorm-folded-witness.md); -the folded-witness L2 certificate was cancelled and removed in #247 on main) -needs regenerated `generated_sis_table/` rows: for each representative modulus family, -ring dimension, squared-Euclidean collision bucket, and module rank, the maximum commitment -width that still yields at least 128-bit security under a fixed lattice-reduction cost model. +This archived work regenerated Akita's former L2 MSIS table. The folded-witness +L2 certificate was cancelled and removed in #247 on main. The work produced +`generated_sis_table/` rows for representative modulus families, ring +dimensions, squared-Euclidean collision buckets, and module ranks. Each row +records the maximum commitment width that still yields at least 128-bit +security under a fixed lattice-reduction cost model. Today that table is produced offline by `scripts/gen_sis_table.py`, which calls [lattice-estimator](https://github.com/malb/lattice-estimator) through SageMath from an @@ -368,7 +368,6 @@ Historical baseline before reliability work: `2bfb768`. ## References -- Parent (archived): [`specs/archive/2026-Q2/l2-msis-opnorm-folded-witness.md`](archive/2026-Q2/l2-msis-opnorm-folded-witness.md) - [`scripts/gen_sis_table.py`](../scripts/gen_sis_table.py) - [`crates/akita-types/src/sis/ajtai_key.rs`](../crates/akita-types/src/sis/ajtai_key.rs) - lattice-estimator: `malb/lattice-estimator` — `estimator/sis_lattice.py` diff --git a/specs/archive/2026-Q3/profile-bench-coverage-matrix.md b/specs/archive/2026-Q3/profile-bench-coverage-matrix.md index 70301bfc4..8359cf395 100644 --- a/specs/archive/2026-Q3/profile-bench-coverage-matrix.md +++ b/specs/archive/2026-Q3/profile-bench-coverage-matrix.md @@ -15,7 +15,7 @@ > for the current contract and exact cases. > **Status note (2026-06-03, PR #146).** The committed-fold A-role reprice in -> [`specs/weak-binding-norm-fix.md`](../../weak-binding-norm-fix.md) made the small-D +> [`weak-binding-norm-fix.md`](weak-binding-norm-fix.md) made the small-D > families non-securable (fp16 entirely; fp32/fp64 at D32/D64), so the **active** > benchmark matrix was re-pointed at securable D128 profiles for the small prime > fields. A later follow-up re-pointed the **fp128** cells to D64 after measuring diff --git a/specs/weak-binding-norm-fix.md b/specs/archive/2026-Q3/weak-binding-norm-fix.md similarity index 98% rename from specs/weak-binding-norm-fix.md rename to specs/archive/2026-Q3/weak-binding-norm-fix.md index 3c1c4e651..5467824eb 100644 --- a/specs/weak-binding-norm-fix.md +++ b/specs/archive/2026-Q3/weak-binding-norm-fix.md @@ -4,8 +4,10 @@ |-----------|--------------------------------| | Author(s) | Omid Bodaghi, Quang Dao, Cursor agent draft | | Created | 2026-06-01 | -| Status | implemented (the original anchored A-role bound is superseded by the committed-fold reprice below) | +| Status | superseded | | PR | https://github.com/LayerZero-Labs/akita/pull/146 | +| Superseded-by | [`selective-l2-fold-security-sizing.md`](../../selective-l2-fold-security-sizing.md) | +| Book-chapter | book/src/how/security.md | > **Status note (2026-06-03).** The A-role weak-binding price that first > shipped on this branch (`collision_A = 2·ω̄·β̄·ν` with a single-block `β̄`, @@ -16,6 +18,14 @@ > in the two sections immediately below. Everything from "Implementation > outcome (2026-06-02)" onward is retained as historical / superseded context. +> **Active correction (2026-08-06).** +> [`selective-l2-fold-security-sizing.md`](../../selective-l2-fold-security-sizing.md) +> removes `ring_subfield_norm_bound` from physical A role collision sizing. +> The challenge and accepted folded response are already physical ring +> coefficient vectors at this point, so applying the Hachi logical to ring +> conversion here counts it twice. The active spec owns this correction and +> the optional L2 route. + ## Correction (2026-06-03): committed-fold A-role reprice ### What was still wrong @@ -66,7 +76,8 @@ envelope** the stage-1 range check actually certifies: z_verifier = balanced_digit_abs_max(log_basis, δ_fold) collision_A_inf = 8 · ω · z_verifier · ν -collision_A = ceil_bucket(d · collision_A_inf²) (L2 MSIS table) +collision_A = ceil_supported_linf_bound(collision_A_inf) + (ADPS16 coefficient-L∞ SIS table) ``` `fold_witness_beta` still names the fold-response kernel bound; MSIS pricing uses diff --git a/specs/archive/README.md b/specs/archive/README.md index 5c1dedf6b..8582fd3d9 100644 --- a/specs/archive/README.md +++ b/specs/archive/README.md @@ -13,6 +13,7 @@ to track current behavior; update the owning book chapter instead. | Spec | Final status | Book chapter | Archived | |------|--------------|--------------|----------| | `2026-Q3/pr375-prover-streaming-and-onehot-unification.md` | archived | `book/src/how/optimizations.md` | 2026-Q3 | +| `2026-Q3/weak-binding-norm-fix.md` | superseded | `book/src/how/security.md` | 2026-Q3 | | `2026-Q3/profile-bench-coverage-matrix.md` | archived | `book/src/usage/profiling.md` | 2026-Q3 | | `2026-Q3/multi-group-batching-legacy.md` | historical | _(superseded API record)_ | 2026-Q3 | | `2026-Q3/group-local-opening-points.md` | archived | `book/src/how/architecture.md` | 2026-Q3 | @@ -25,7 +26,6 @@ to track current behavior; update the owning book chapter instead. | `2026-Q2/akita-zk-commitment-hiding.md` | archived | `book/src/roadmap/zero-knowledge.md` | 2026-Q2 | | `2026-Q2/akita-zk-sumcheck-hiding-plain.md` | archived | `book/src/roadmap/zero-knowledge.md` | 2026-Q2 | | `2026-Q2/akita-zk-v-hiding.md` | archived | `book/src/roadmap/zero-knowledge.md` | 2026-Q2 | -| `2026-Q2/l2-msis-opnorm-folded-witness.md` | historical | _(cancelled; no book fold)_ | 2026-Q2 | | `2026-Q2/akita-sis-consolidation.md` | superseded | `book/src/how/security.md` | 2026-Q2 | | `2026-Q2/sis-euclidean-estimator.md` | superseded | `book/src/how/security.md` | 2026-Q2 | | `2026-Q2/sis-infinity-estimator-implementation-plan.md` | superseded | _(slice plan superseded by cutover spec)_ | 2026-Q2 | diff --git a/specs/fold-linf-rejection.md b/specs/fold-linf-rejection.md index 4574ff9f3..f5adc3cfb 100644 --- a/specs/fold-linf-rejection.md +++ b/specs/fold-linf-rejection.md @@ -38,6 +38,12 @@ treat the nonce itself as evidence of the norm bound. There is one sizing and grinding flow for every valid sparse configuration. +This honest coefficient-`L∞` sizing flow is separate from the A-role security +route. The ordinary A route prices the verifier-enforced balanced-digit +envelope in the coefficient-`L∞` SIS table. Eligible calibrated later folds may +instead carry the exact physical norm proof and Euclidean SIS route defined by +[`selective-l2-fold-security-sizing.md`](selective-l2-fold-security-sizing.md). + ## Bounds Let: @@ -156,4 +162,5 @@ for the current group and terminal ownership model. - operator-norm rejection or calibrated empirical thresholds; - using the honest tail cap directly for A-role MSIS collision pricing. -A-role pricing continues to use the verifier-enforced balanced-digit envelope. +The ordinary coefficient-`L∞` A-role route continues to use the +verifier-enforced balanced-digit envelope. diff --git a/specs/remove-fp16.md b/specs/remove-fp16.md index 7e3bb068f..8ba33a2b4 100644 --- a/specs/remove-fp16.md +++ b/specs/remove-fp16.md @@ -186,5 +186,5 @@ Risks to watch: ## References - PR 146 (security correction and A-role reprice): `https://github.com/LayerZero-Labs/akita/pull/146` -- `specs/weak-binding-norm-fix.md` (context and derivation history) +- `specs/archive/2026-Q3/weak-binding-norm-fix.md` (context and derivation history) - `crates/akita-types/src/sis/norm_bound.rs` (committed-fold collision pricing implementation) diff --git a/specs/schedule-catalog-ownership.md b/specs/schedule-catalog-ownership.md index 154f52814..cf5857fb4 100644 --- a/specs/schedule-catalog-ownership.md +++ b/specs/schedule-catalog-ownership.md @@ -514,7 +514,6 @@ pub struct GeneratedScheduleCatalogIdentity { pub sis_modulus_profile: SisModulusProfileId, pub ring_dimension: usize, pub decomposition: DecompositionParams, - pub ring_subfield_norm_bound: u32, pub claim_ext_degree: usize, pub chal_ext_degree: usize, pub inner_basis_range: (u32, u32), diff --git a/specs/selective-l2-fold-security-sizing.md b/specs/selective-l2-fold-security-sizing.md new file mode 100644 index 000000000..87e6fea1b --- /dev/null +++ b/specs/selective-l2-fold-security-sizing.md @@ -0,0 +1,755 @@ +# Spec: Selective L2 Fold Security Sizing + +| Field | Value | +|---------------|-------| +| Author(s) | Quang Dao | +| Created | 2026-08-06 | +| Status | active | +| PR | [#369](https://github.com/LayerZero-Labs/akita/pull/369) | +| Supersedes | The physical A role embedding factor in `archive/2026-Q3/weak-binding-norm-fix.md` | +| Superseded-by | | +| Book-chapter | book/src/how/security.md | + +## Summary + +Akita currently sizes every committed A matrix from a coefficient L infinity +bound on the folded response. This remains the default. This change adds a +second candidate for selected later folds. That candidate proves a bound on the +squared L2 norm of the physical folded response and sizes only that level's A +matrix with the quantum ADPS16 Euclidean SIS table. A level that has no L2 proof +continues to use the current L infinity table. + +This change also removes an unrelated factor of two from physical A role +security sizing in the small field profiles. The folding challenge and folded +response are already expressed as physical ring coefficients when the weak +binding argument uses them. Applying the Hachi logical to ring conversion at +that point converts neither value. It counts a conversion that has already +happened. + +The purpose of the selective L2 route is to reduce the A rank at later folds +when the folded response has low total energy. Lowering A rank also shrinks the +T witness that the next fold must carry. The planner must therefore compare +complete suffixes, including any change in the number of folds, rather than +compare one level in isolation. + +## Intent + +### Goal + +Add a sound optional L2 security route for selected nonterminal folds while +keeping the current L infinity route available at every fold. + +### Per level rule + +The planner constructs distinct candidates. It does not attach an L2 claim to +every level and it does not choose a norm after the proof has been produced. + +| Candidate | Proof obligation | A role security table | +|-----------|------------------|-----------------------| +| L infinity | Existing digit range proof | Quantum ADPS16 coefficient L infinity table | +| L2 | Existing digit range proof and the new physical norm proof | Quantum ADPS16 Euclidean table | + +Every planner state has an L infinity candidate. An L2 candidate exists only +when the planner policy supplies a public squared norm cap for that candidate. +If the planner selects the L infinity candidate, the proof contains no L2 +claim and pays no L2 proof cost. + +The terminal response has no Stage 1 proof. This change does not add an L2 +route to the terminal response. A direct check on the clear terminal witness is +a separate change. + +### Coordinate system + +Let + +```text +R = Z[X] / (X^D + 1) +``` + +with centered integer coefficients. All security bounds in this spec use the +physical coefficient vector obtained by flattening every ring row, chunk, and +coefficient position in the A role response. + +For one raw fold challenge and response, define + +```text +kappa_1 = maximum physical coefficient L1 norm of c +Z_inf = accepted physical coefficient L infinity bound on z +S = accepted complete physical squared L2 norm of z +``` + +The complete norm is + +```text +S = sum over every physical A response coefficient of z_i^2. +``` + +It is not a per row norm and it is not a per matrix column norm. + +The sparse challenge type already represents a polynomial in the physical +base field ring. Its `l1_norm()` already counts physical ring coefficients. +The folded response is centered and decomposed into the physical Z digit +planes before Stage 1 checks those planes. + +### Security invariants + +1. A level without an L2 proof must use L infinity A role sizing. +2. An L2 candidate must bind its public norm cap into the schedule and proof + shape. +3. The verifier must prove the norm of the same physical Z coefficients that + the A role Module SIS reduction uses. +4. The planner, prover, verifier, schedule audit, and proof size code must use + one shared definition of the physical response domain. +5. The physical A role collision formula must not apply a Hachi embedding + factor. +6. The Euclidean SIS estimator must receive the norm of the complete scalar + collision vector exactly once. +7. The existing digit range proof remains present on an L2 candidate. +8. A proof must not move between L infinity and L2 schedules through a shape or + transcript ambiguity. +9. Verifier reachable code must reject malformed norm claims and shapes with + `AkitaError` or `SerializationError`. It must not panic. + +### Non goals + +This change does not add the following features. + +* It does not replace L infinity sizing at every fold. +* It does not add an L2 check to the root or early folds. +* It does not use a Gaussian assumption as part of security. +* It does not use an uncertified operator norm cap of 17. +* It does not add operator norm rejection above D128 without a separate + accepted support certificate. +* It does not force terminal rank three. +* It does not remove the digit range proof. +* It does not add zero knowledge machinery, four square slack, carry witnesses, + or an inequality proof inside the field. + +## Security argument + +### The extracted A collision + +The weak binding extractor compares two accepted openings. A raw challenge in +either opening has physical L1 norm at most `kappa_1`. Their difference has L1 +norm at most `2 * kappa_1`. + +Likewise, if each raw response has physical L infinity norm at most `Z_inf`, a +response difference has L infinity norm at most `2 * Z_inf`. If each raw +response has squared L2 norm at most `S`, a response difference has L2 norm at +most `2 * sqrt(S)`. + +Clearing the two weak opening denominators produces two negacyclic products. +For physical ring coefficient vectors, Young's convolution inequalities give + +```text +||a * b||_inf <= ||a||_1 * ||b||_inf +||a * b||_2 <= ||a||_1 * ||b||_2. +``` + +Each product has one challenge difference and one response difference. The +sum has two products. This gives the complete raw radius bounds + +```text +C_inf = 8 * kappa_1 * Z_inf +C_2_sq = 64 * kappa_1^2 * S. +``` + +The three factors of two have separate sources. One comes from the challenge +difference. One comes from the response difference. One comes from adding the +two products that clear the two weak opening denominators. + +The L infinity candidate rounds `C_inf` upward in the quantum ADPS16 +coefficient L infinity table. The L2 candidate rounds `C_2_sq` upward in the +quantum ADPS16 Euclidean table. + +Both formulas describe the same extracted A kernel vector. A selected schedule +needs one sound route. The planner may compare the ranks returned by the two +routes, but the selected route determines the proof obligation and table used +by the verifier's schedule audit. + +### Why the Hachi factor is double counted today + +The Hachi map `psi` packs logical extension field coordinates into a physical +base field ring. A norm conversion factor is needed only for an argument that +starts with a bound on the logical coordinates and then derives a bound on the +packed ring coefficients. + +The current committed fold security path starts from physical values. + +First, the fold challenge `c` is sampled as a `SparseChallenge`. It is already +a physical polynomial in the base field ring. Its L1 norm counts the nonzero +physical coefficients and their magnitudes. There is no extension field +challenge left to pack. + +Second, the folded response `z` is stored as centered physical ring +coefficients in `z_folded_centered_per_chunk`. The prover decomposes those same +coefficients into the Z digit planes. Stage 1 checks the digit alphabet, and +the verifier's accepted `Z_inf` is the integer envelope obtained by +recomposing those physical digits. + +Third, the A role Module SIS kernel vector uses the same physical ring +coordinates. The weak binding product inequalities act directly on the +physical challenge and physical response. + +The current `ring_subfield_norm_bound` multiplication inside A role collision +sizing therefore has no input to convert. For fp32 and fp64 it changes + +```text +8 * kappa_1 * Z_inf +``` + +into + +```text +8 * kappa_1 * 2 * Z_inf. +``` + +That second expression treats `Z_inf` as if it were still a logical norm before +`psi`. It is not. Stage 1 already bounds the packed coefficients. The factor of +two is therefore counted after the conversion it was meant to cover. + +This conclusion does not say that `psi` has no norm cost. A completeness or +honest sizing argument may begin with a logical extension field source. Such an +argument must apply the relevant logical to physical conversion once before it +chooses a physical digit depth or physical response cap. Once the argument has +reached `z_folded_centered_per_chunk` or the reconstructed Z digit planes, it +must not apply that conversion again. + +The Hachi trace identity used for extension opening checks does not change this +conclusion. That identity connects a logical opening claim to a ring trace. It +does not rescale the physical A kernel vector produced by weak binding. + +### The separate Euclidean width double count + +The Euclidean estimator uses the scalar SIS dimensions + +```text +n = rank * D +m = width * D. +``` + +For the L2 route, `C_2_sq` bounds the complete scalar collision vector across +all `width` input ring rows. The estimator must therefore use + +```text +length_bound = sqrt(C_2_sq). +``` + +Using + +```text +length_bound = sqrt(width * C_2_sq) +``` + +counts the rows twice. Their coefficients already appear in the sum that +defines `S` and hence in `C_2_sq`. The scalar column count `m` records the width +again for the lattice dimension, which is correct. It must not also enlarge the +norm. + +### Security versus honest acceptance + +The scheduled cap is a public acceptance condition. Security does not require +the honest folded witness to follow a Gaussian distribution. If the verifier +accepts only responses with `S <= S_max`, then the L2 collision formula holds +for every accepted proof. + +The response distribution affects completeness and prover cost. It determines +how often the prover can find an allowed Fiat Shamir nonce whose response lies +below `S_max`. The planner uses typed source moments and a separate model error +envelope. Held out end to end measurements test that envelope and the final cap +slack. Neither the model nor those measurements are assumptions in the binding +proof. + +## Protocol design + +### Schedule representation + +The schedule needs one explicit A role security route for each committed +level. The canonical type should have the following meaning. + +```text +InnerCommitSecurityRoute::Linf +InnerCommitSecurityRoute::L2 { + response_l2_sq_cap, + norm_subclaim_shape, +} +``` + +The exact Rust field names may change during implementation, but there must be +one canonical route value. A collection of independent booleans is not +acceptable because it permits impossible states. + +The route and all L2 shape data are part of schedule identity, descriptor +bytes, proof shape derivation, serialization context, and schedule audit. The +proof stream remains headerless. The schedule tells the decoder whether norm +claims are present and how many values to read. + +### Candidate eligibility + +The planner always emits an L infinity candidate. It may emit an L2 candidate +only when a production profile enables the typed response model and the +canonical derivation supplies `S_max` and the norm proof shape for that physical +response domain. + +There is no global L2 cap and no hard coded rule that every level after a fixed +index must use L2. Different field profiles and witness geometries reach useful +energy ranges at different levels. Generated schedules record the exact levels +and concrete caps that select L2. + +The model starts at level 3. The planner discards a candidate if it does not +lower the A rank or if its complete suffix is not smaller than an L infinity +suffix. The existing bounded nonce limit remains unchanged. + +### Prover acceptance + +An L infinity candidate uses the existing fold nonce rule. + +An L2 candidate uses the same bounded nonce space. For each nonce, the prover +derives the fold challenge, computes the physical folded response, checks the +existing digit admission condition, and checks `S <= S_max`. The prover accepts +the first nonce that satisfies both conditions. + +The verifier checks that the nonce lies within the scheduled attempt bound. It +does not trust the prover's search. It derives the selected challenge from the +nonce, verifies the physical norm proof, and checks the reconstructed integer +norm against `S_max`. + +### Stage 1 norm claim + +For an L2 candidate, Stage 1 receives the integer claim + +```text +S = sum_x z(x)^2 +``` + +over the canonical physical A response domain. The domain contains every live Z +coefficient exactly once and gives every padding address value zero. + +The prover adds a degree two sumcheck term to the final Stage 1 substage. A +fresh transcript challenge batches it with the existing digit range term. The +range term remains equality factored. The norm term is an unweighted sum over +the physical response domain. The combined round message therefore uses the +general degree bound required by both terms. + +At the final Stage 1 point, the norm term reduces to the square of one virtual +evaluation of physical `z`. Stage 2 proves that this virtual value is the +balanced basis recomposition of the committed Z digit plane evaluations at the +same physical point. The selector and basis powers come from `WitnessLayout` +and the selected level parameters. The prover cannot substitute a logical +prepacking response or omit a physical segment. + +For the direct large field case, the expected wire change is one additional +extension field coefficient in each round of the final Stage 1 substage, plus +the integer norm claim and any final virtual evaluation needed by Stage 2. The +proof shape and proof size code must compute the exact count. No comment or +planner estimate may substitute for the serialized shape. + +### Integer soundness in small fields + +A field equation proves only a congruence. It proves an integer square sum only +when the public bounds rule out wraparound. + +If the schedule derived worst case physical square sum is below the base field +modulus, the verifier may use one direct norm claim. A prover supplied claim +below the modulus is not enough by itself. The worst case value allowed by the +digit ranges must also be below the modulus. + +Otherwise, write each physical response coefficient as + +```text +z(x) = sum_j B^j * z_hat_j(x). +``` + +Then + +```text +S = sum_j B^(2j) * I_jj + + 2 * sum_{j < k} B^(j+k) * I_jk, + +I_jk = sum_x z_hat_j(x) * z_hat_k(x). +``` + +The protocol partitions the physical address domain into public blocks. Each +block is short enough that the digit alphabet gives an absolute bound below +half the base field modulus for every `I_jk` subclaim. The verifier takes the +unique centered integer lift of each field value and reconstructs `S` with +checked integer arithmetic. + +The block partition and limb pair list are schedule derived proof shape data. +The prover does not choose them. The verifier rejects an overflow, a missing +subclaim, a duplicate pair, an invalid block, or a reconstructed negative +square sum. + +This construction certifies equality to the physical square sum. It does not +prove a field inequality and it does not use four square slack. The verifier +performs the final integer comparison `S <= S_max` after reconstruction. + +### Stage 2 virtualization + +Stage 2 already binds the final Stage 1 range image to the committed digit +witness. The L2 route adds one more virtual relation for the Z segments. It +uses the same physical address authority and digit source. + +For each required virtual value, Stage 2 checks the linear recomposition + +```text +z(r) = sum_j B^j * z_hat_j(r) +``` + +with the correct group, chunk, row, and coefficient selectors. The final norm +claim uses `z(r)^2`. Small field limb subclaims use the corresponding pairs of +digit plane evaluations. + +The Stage 2 batching challenge is sampled after all Stage 1 claims have been +absorbed. This prevents a prover from choosing one false relation to cancel +another. + +### Proof and transcript shape + +The L2 route changes all of the following surfaces. + +* `AkitaStage1Proof` and its shape need the norm claim and any small field + subclaims selected by the schedule. +* The final Stage 1 round shape needs the additional coefficient count. +* Transcript labels must separate norm claims from range image claims. +* `FoldLevelProof` serialization remains schedule driven and headerless. +* `Valid` and deserialization checks must bound every allocation before use. +* `level_proof_bytes` and the profile reporter must count the exact serialized + values. +* Logging transcript tests must show the same event order for prover and + verifier. + +## Planner and SIS estimator + +### Quantum ADPS16 Euclidean table + +The production L2 route uses the 128 bit quantum ADPS16 reduction cost model. +It does not use the older BDGL16 Euclidean profile. + +The estimator work includes the following changes. + +* Enable the ADPS16 quantum cost in the Euclidean path. +* Reject BDGL16 for production Euclidean table generation. +* Use `sqrt(C_2_sq)` as the scalar length bound. +* Generate a separate L2 table and digest. Do not overwrite the coefficient L + infinity table. +* Store accepted cells and rejected successor evidence at the 128 bit boundary. +* Add golden tests for each field family and supported ring dimension. + +The verifier never runs the estimator. It uses checked schedule parameters and +the generated table only. + +The table generator emits a full audit CSV and hashes it into the generated +Rust table. The CSV is reproducible and is not checked in. Run the following +command to rebuild the Rust rows and the local audit file. + +```sh +cargo run -p akita-sis-estimator --release --example euclidean_width_table -- --format rust-split +``` + +### Calibrated response model admission + +The planner keeps its ordinary L infinity search at every state. Every +production family enables `TypedProtocolMomentsV1`. At level 3 and later, the +planner evaluates the ordinary best block +split under both security routes for response bases 16 and above. It keeps the +L2 alternative only when it lowers the A rank. Response basis 8 is excluded +because it caused deterministic stage 2 folded oracle consistency failures in +two D64 production profiles. The protocol cause has not been fixed. + +The typed model carries the expected squared norm of the recursive witness +through the protocol. Dense roots use centered field digit moments. One-hot +roots use the exact number of unit entries. Later Z segments use rounded normal +residue moments. Their variance is the previous source energy times the +challenge energy, divided by the physical response length. E, T, and R use +centered field digit moments for the exact live scalar counts. The last field +digit plane uses its actual residual width. Negative binary compression uses a +second moment of one half per coefficient. Extension tensor packing multiplies +logical energy by `(2K - 1) / K`. + +The challenge multiplication identity is exact under scalar challenge +covariance. The accepted fixed point operator norm sampler is not assumed to be +perfectly orbit invariant. Measurements cover five million random orbit pairs +and 32 complete orbits at each of D64 and D128. They found no acceptance +mismatches or mixed orbits. Raw and explicitly randomized covariance defects +were both about 0.07 percent, so this change does not add transcript +symmetrization. + +The suffix state retains seven leading bits of source energy and rounds upward. +This loses less than `1/64` relative precision and prevents the dynamic program +from creating a separate state for every integer energy. The planner computes + +```text +cap = ceil(bucketed_source_energy * challenge_l2_sq * 1.03 * 1.06). +``` + +The 1.03 factor covers source model error. The 1.06 factor is the per attempt +response allowance. If the first factor bounds the true conditional mean, +Markov's inequality gives + +```text +Pr[response_l2_sq <= 1.06 * conditional_mean] >= 3 / 53. +``` + +The protocol permits 4096 independent attempts. The resulting worst case +exhaustion probability is negligible. The Markov statement does not assume a +Gaussian response tail. The rounded normal hypothesis is only used to predict +the Z digits of the next source witness. + +Held out end to end samples cover 14 fp32, fp64, and fp128 profile modes. They +include dense, one-hot, direct, recursive, multi-group, and multi-chunk paths. +All proofs passed both verifier modes. Across 52 selected L2 responses, cap +slack was 6.90 to 18.18 percent. One response needed one retry. Aggregate source +model error was negative 0.20 to positive 8.95 percent. The largest unfavorable +component error was 2.24 percent. A recursive multi-group W8 setup state retained +enough correlation that its E and T energies were about 25 percent below the +uniform model. This made the model conservative and produced the 18.18 percent +maximum cap slack. + +This is a completeness model, not a soundness assumption. The selected cap is +frozen into the generated schedule and remains the verifier enforced SIS input. +If model construction fails, the geometry is unsupported, the Euclidean table +has no row, or the L2 rank does not improve, the planner keeps the L infinity +candidate. + +The existing suffix search prices the ordinary L infinity candidate and the +modeled L2 candidate. This comparison includes the different A rank, T width, +next witness length, later folds, and terminal response. The planner does not +keep extra predecessor splits merely to expose more modeled alternatives. + +The final planner comparison includes the norm proof bytes, changed A payload, +changed T decomposition, changed next witness, all later folds, and the +terminal response. + +### Reporting + +For every shipped fp128, fp64, and fp32 profile affected by the change, the PR +must report the following values before and after the change. + +* Total proof bytes. +* Number of recursive folds. +* The selected security route at every fold. +* A, B, and D ranks. +* Ring dimensions. +* Log bases and digit counts. +* The public L2 cap and observed physical norm on every L2 level. +* The norm proof bytes. +* The next witness length after every fold. +* Terminal response bytes. +* Nonce attempts and the observed failure rate for each L2 cap. + +The report must separate three effects. It must show the old main result, the +result after removing only the physical Hachi double count, and the result after +adding selective L2 candidates. This prevents the PR from attributing an L +infinity correction to the new norm proof. + +## Evaluation + +### Acceptance criteria + +* [x] A level with `InnerCommitSecurityRoute::Linf` serializes no L2 claim and + uses only coefficient L infinity A role sizing. +* [x] A level with `InnerCommitSecurityRoute::L2` verifies the complete physical + square sum and rejects `S > S_max`. +* [x] The prover and verifier derive the physical Z domain from one shared + `WitnessLayout` authority. +* [x] Removing the Hachi factor changes physical A role collision sizing from + `8 * kappa_1 * 2 * Z_inf` to `8 * kappa_1 * Z_inf` for fp32 and fp64. +* [x] Equal physical challenges and responses produce equal A role collision + bounds across field profiles, independent of extension degree. +* [x] A separate test shows that a bound stated before `psi` still applies its + logical to physical conversion once in honest sizing. +* [x] The Euclidean scalar mapping uses `sqrt(C_2_sq)` and never + `sqrt(width * C_2_sq)` for a complete collision norm. +* [x] Production L2 table rows use quantum ADPS16 at 128 bits. +* [x] At each calibrated suffix state, the planner prices the ordinary L + infinity candidate and at most one L2 alternative for its canonical + split. +* [x] Root and early levels carry no L2 proof; a terminal level carries one + only when the complete suffix comparison selects it. +* [x] Tampering with the norm, cap, route, subclaim, virtual evaluation, nonce, + or proof shape causes verification to fail. +* [x] Small field tests cover positive and negative limb inner products, + centered lifting boundaries, block boundaries, and integer overflow. +* [x] Headerless deserialization rejects oversized shapes before allocation. +* [x] Proof size accounting equals actual serialization for every supported + field family. +* [x] Generated schedules pass audit and the report contains all required + before and after values. +* [x] All repository CI gates and verifier no panic checks pass. + +### Testing strategy + +Unit tests cover the collision formulas, physical coordinate conversion, L2 +table mapping, integer reconstruction, and proof shape arithmetic. + +Protocol tests produce valid L infinity and L2 proofs from the same witness. +They then mutate each new transcript value and each schedule field. The +verifier must reject every mutation without panic. + +Planner tests pin one case where the locally smaller A rank is not the cheapest +suffix. They also pin one case where the L2 candidate removes a fold and one +case where its proof cost makes the L infinity candidate win. + +End to end tests cover fp128, fp64, and fp32. Small field tests must exercise a +configuration that uses more than one limb inner product block. + +The final verification commands come from `AGENTS.md` and the current CI +workflow. Documentation changes also run `scripts/check-doc-guardrails.sh`. + +### Performance + +An L infinity selected schedule must have no prover, verifier, or proof size +cost from the L2 machinery. + +An L2 selected large field level should add one field coefficient per final +Stage 1 round, plus its fixed claims. The implementation must report the actual +serialized count instead of assuming this estimate. + +The prover may perform an extra physical square sum while testing a nonce. It +should compute that sum in the same pass that already materializes centered Z +coefficients. A second full ring switch per nonce is not acceptable. + +Small field limb proofs may cost more. The planner must include those bytes and +must be free to reject every small field L2 candidate if none improves the +complete suffix. + +## Design + +### Architecture + +The change crosses the following canonical owners. + +* `akita-challenges` owns physical sparse challenge norms. +* `akita-types::sis` owns the L infinity and L2 collision formulas and generated + table lookup. +* `akita-types::layout` owns the physical Z address domain and norm subclaim + shape. +* `akita-types::proof` owns route derived proof shapes and wire values. +* `akita-prover` computes the physical norm, applies joint nonce admission, + proves Stage 1, and supplies Stage 2 virtual relations. +* `akita-verifier` replays the same relations and performs the final integer cap + check. +* `akita-planner` constructs separate L infinity and L2 candidates and prices + complete suffixes. +* `akita-sis-estimator` generates the quantum ADPS16 Euclidean table. +* `akita-schedules` stores and audits the selected route and cap. +* The profile report accounts for proof bytes, ranks, fold count, norms, and + nonce attempts. + +The intended flow is + +```text +physical centered z + | + +--> existing digit range proof --> L infinity candidate + | + +--> exact square sum proof ------> L2 candidate + | + +--> Stage 2 binds z to physical Z digit planes + +selected candidate --> A rank --> T width --> next witness --> suffix planner +``` + +### Alternatives considered + +#### Global L2 replacement + +A global replacement charges norm proof bytes at levels where the tighter +security route gives no suffix benefit. It also removes the proven L infinity +fallback. This design keeps the routes as separate planner candidates. + +#### Prover reported norm without a proof + +The old diagnostic bound a reported norm into the transcript but did not prove +it. That was useful only for estimating planner changes. It cannot size a +production A matrix. + +#### One global cap + +Witness geometry and fold history differ by level and field profile. One cap +either fails honest proving or loses the expected rank reduction. Caps are +schedule values attached only to checked candidates. + +#### Certified operator norm rejection + +A smaller challenge multiplication operator norm improves the L2 formula. +The D64 continuation uses the `(31, 11)` shell with a certified true threshold +of 18 and a strict integer threshold of 19. The D128 continuation reuses the +production `(31, 0)` shell with a certified true threshold of 13 and a strict +threshold of 14. The transcript binds the family and both thresholds. The +prover and verifier replay the same rejection sequence. Each route has an exact +accepted support certificate that retains at least 128 bits. Other dimensions +continue to use the deterministic challenge L1 norm. + +#### Direct terminal L2 check + +The terminal response is already clear. The verifier decodes every centered +coefficient, computes its exact integer squared norm, and rejects a value above +the scheduled cap. This route needs no recursive norm proof. It uses certified +operator norm rejection and the same A role collision formula. + +#### Four square inequality proof + +The verifier only needs equality to the physical integer norm, followed by a +public integer comparison. Exact square sums or bounded limb inner products do +that directly. Four square slack and carry witnesses add proof state that this +change does not need. + +#### Apply the Hachi factor conservatively + +Conservative factors are sound only when they bound a real conversion or +operation. Here both values are already physical. Keeping the factor changes +security parameters according to extension degree even when the physical SIS +instance is identical. That is not a property of the extracted collision. + +## Documentation + +The implementation PR must update the following pages when the behavior lands. + +* `book/src/how/security.md` must explain the two per level security routes and + the physical coordinate rule. +* `book/src/how/proving/sumcheck-stages.md` must explain the optional Stage 1 + norm term and Stage 2 virtualization. +* `book/src/how/configuration.md` must explain how the planner selects a route + and cap. +* `specs/archive/2026-Q3/weak-binding-norm-fix.md` must point to this correction + for physical A role sizing. +* Generated schedule tables and their book presentation must be refreshed. + +The implementation PR keeps this spec active. Mark it implemented when the PR +merges. It can then be archived because its durable security and protocol text +has been folded into the book. + +## Execution + +1. Land this spec and remove the stale global cutover design. +2. Remove the Hachi factor from physical A role L infinity sizing and add + boundary tests. +3. Add the quantum ADPS16 Euclidean table and fix the complete norm mapping. +4. Add the schedule route, cap, descriptor binding, and exact proof size model. +5. Add prover norm measurement and joint nonce admission. +6. Add the large field Stage 1 norm term and Stage 2 virtual relation. +7. Add small field limb inner products only where the no wrap test requires + them. +8. Add verifier replay and malformed proof tests. +9. Add the modeled L2 candidate to the existing suffix comparison. +10. Regenerate schedules and produce the required three way report. +11. Run the full repository gates and update the owning book pages. + +## References + +* Akita paper, `sections/akita/9_core_security.tex`, especially the core weak + binding lemma and radius to collision corollary. +* Akita paper, `sections/akita/3_preliminaries.tex`, for physical ring norm + inequalities and the logical to ring conversion boundary. +* Hachi, Lemma 7, for weak binding after denominator clearing. +* `crates/akita-types/src/sis/norm_bound.rs`. +* `crates/akita-prover/src/protocol/ring_switch/coeffs.rs`. +* `crates/akita-types/src/proof/stage1.rs`. +* `crates/akita-prover/src/protocol/sumcheck/digit_range/`. +* `crates/akita-prover/src/protocol/sumcheck/relation_range_image/`. +* `crates/akita-sis-estimator/src/euclidean.rs`. +* `specs/fold-linf-rejection.md` for the separate digit depth policy. +* `specs/sis-quantum128-scalar-n-table.md` for the production quantum security + policy. diff --git a/specs/tail-wire-encoding.md b/specs/tail-wire-encoding.md index d95acd892..828a83266 100644 --- a/specs/tail-wire-encoding.md +++ b/specs/tail-wire-encoding.md @@ -377,7 +377,7 @@ Remaining audit/measurement items: - PR #311 / [`terminal-direct-ring-relations-cutover.md`](terminal-direct-ring-relations-cutover.md): terminal r-drop and direct ring relations. - PR #174 / `specs/fold-linf-rejection.md` (closed spec PR; implementation #189): the `t*` threshold and fold `‖z‖_inf` cap; Golomb `z` sizing uses the same cap as `num_digits_fold`, not the level variance envelope. - `specs/terminal-fold-cutover.md` (PR #88): the D-role drop whose transcript-binding discipline the terminal `t`-state cutover reuses. -- `specs/weak-binding-norm-fix.md`: the weak-binding object the tail extraction recovers. +- `specs/archive/2026-Q3/weak-binding-norm-fix.md`: the historical weak-binding object the tail extraction recovers. - `crates/akita-types/src/proof/direct_witness.rs` (`TerminalResponse`), `crates/akita-types/src/proof/tail_segments.rs` (segment layout and transcript slicing), and `crates/akita-types/src/proof/levels.rs` (`TerminalLevelProof`).