diff --git a/.github/workflows/pr_main.yaml b/.github/workflows/pr_main.yaml index a4554fda2..0161d9ac0 100644 --- a/.github/workflows/pr_main.yaml +++ b/.github/workflows/pr_main.yaml @@ -76,7 +76,7 @@ jobs: path: | executor/program_artifacts/rust executor/shared_target - key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'Makefile') }} + key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'crypto/ethrex-crypto/**', 'Makefile') }} restore-keys: | rust-elf-artifacts- @@ -213,7 +213,7 @@ jobs: path: | executor/program_artifacts/rust executor/shared_target - key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'Makefile') }} + key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'crypto/ethrex-crypto/**', 'Makefile') }} restore-keys: | rust-elf-artifacts- @@ -329,7 +329,7 @@ jobs: path: | executor/program_artifacts/rust executor/shared_target - key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'Makefile') }} + key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'crypto/ethrex-crypto/**', 'Makefile') }} restore-keys: | rust-elf-artifacts- @@ -409,7 +409,7 @@ jobs: path: | executor/program_artifacts/rust executor/shared_target - key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'Makefile') }} + key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'crypto/ethrex-crypto/**', 'Makefile') }} restore-keys: | rust-elf-artifacts- @@ -493,7 +493,7 @@ jobs: path: | executor/program_artifacts/rust executor/shared_target - key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'Makefile') }} + key: rust-elf-artifacts-${{ hashFiles('executor/programs/rust/**', 'executor/programs/riscv64im-lambda-vm-elf.json', 'syscalls/**', 'crypto/ethrex-crypto/**', 'Makefile') }} restore-keys: | rust-elf-artifacts- diff --git a/Cargo.lock b/Cargo.lock index 74986dcc9..ac417b1c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -503,6 +503,7 @@ dependencies = [ "k256", "num-bigint", "num-traits", + "sha2", ] [[package]] @@ -584,6 +585,8 @@ name = "executor" version = "0.1.0" dependencies = [ "ecsm", + "k256", + "num-bigint", "rustc-demangle", "serde", "serde_json", @@ -833,6 +836,7 @@ dependencies = [ "log", "math", "math-cuda", + "num-bigint", "rayon", "rkyv", "stark", diff --git a/bin/cli/src/main.rs b/bin/cli/src/main.rs index 1de36220b..37c213aa1 100644 --- a/bin/cli/src/main.rs +++ b/bin/cli/src/main.rs @@ -412,7 +412,7 @@ fn cmd_execute( // below (the flamegraph path drives execution inside the executor and does // not expose per-log data). `None` means "not counted", so the accel lines // are omitted rather than printed as misleading zeros. - let mut accel_counts: Option<(u64, u64)> = None; + let mut accel_counts: Option<(u64, u64, u64)> = None; let cycle_count = if let Some(ref output_path) = flamegraph.path { // Shared execute+flamegraph path (executor::flamegraph) instead of @@ -480,6 +480,7 @@ fn cmd_execute( let mut cycle_count: u64 = 0; let mut keccak_calls: u64 = 0; let mut ecsm_calls: u64 = 0; + let mut ecsm_lincomb2_calls: u64 = 0; // Reused per chunk: `(current_pc, a7)` for logs whose a7 matches an // accelerator syscall number. This is a cheap superset — a non-ECALL // instruction can hold the same value in src1 — that `accelerator_of` @@ -512,6 +513,7 @@ fn cmd_execute( match accelerator_of(executor.instructions.get(pc), a7) { Some(Accelerator::Keccak) => keccak_calls += 1, Some(Accelerator::Ecsm) => ecsm_calls += 1, + Some(Accelerator::EcsmLincomb2) => ecsm_lincomb2_calls += 1, None => {} } } @@ -526,16 +528,17 @@ fn cmd_execute( } if cycles { - accel_counts = Some((keccak_calls, ecsm_calls)); + accel_counts = Some((keccak_calls, ecsm_calls, ecsm_lincomb2_calls)); } cycle_count }; if cycles { println!("Cycles: {}", cycle_count); - if let Some((keccak_calls, ecsm_calls)) = accel_counts { + if let Some((keccak_calls, ecsm_calls, ecsm_lincomb2_calls)) = accel_counts { println!("Keccak calls: {}", keccak_calls); println!("Ecsm calls: {}", ecsm_calls); + println!("Ecsm lincomb2 calls: {}", ecsm_lincomb2_calls); } } @@ -1097,7 +1100,9 @@ mod tests { // non-ECALL whose src1 collides with an accelerator number, and a cache miss. #[test] fn accelerator_of_mirrors_prover_classification() { - use executor::vm::instruction::execution::{ECSM_SYSCALL_NUMBER, KECCAK_SYSCALL_NUMBER}; + use executor::vm::instruction::execution::{ + ECSM_LINCOMB2_SYSCALL_NUMBER, ECSM_SYSCALL_NUMBER, KECCAK_SYSCALL_NUMBER, + }; let ecall = Instruction::EcallEbreak; @@ -1109,6 +1114,10 @@ mod tests { accelerator_of(Some(&ecall), ECSM_SYSCALL_NUMBER), Some(Accelerator::Ecsm) ); + assert_eq!( + accelerator_of(Some(&ecall), ECSM_LINCOMB2_SYSCALL_NUMBER), + Some(Accelerator::EcsmLincomb2) + ); // Non-accelerator syscalls (Commit=64, Halt=93) count as neither. assert_eq!( diff --git a/crypto/ecsm/Cargo.toml b/crypto/ecsm/Cargo.toml index 4d2800b2c..aebd760b7 100644 --- a/crypto/ecsm/Cargo.toml +++ b/crypto/ecsm/Cargo.toml @@ -12,3 +12,8 @@ num-traits = "0.2.19" # constraint system). Used for executor scalar multiplication and for the projective # double-and-add replay + batch inversion that builds ECDAS step witnesses efficiently. k256 = { version = "0.13", default-features = false, features = ["arithmetic", "expose-field"] } + +[dev-dependencies] +# Test-only: re-derives the NUMS blinding point T₀ (SHA-256 try-and-increment) +# to prove the pinned constant in `witness.rs` is reproducible from its tag. +sha2 = { version = "0.10", default-features = false } diff --git a/crypto/ecsm/src/curve.rs b/crypto/ecsm/src/curve.rs index 2f2acb0e1..9aa069c85 100644 --- a/crypto/ecsm/src/curve.rs +++ b/crypto/ecsm/src/curve.rs @@ -90,12 +90,12 @@ fn biguint_from_fe(f: &FieldElement) -> BigUint { BigUint::from_bytes_be(&f.to_bytes()) } -fn to_k256_affine(a: &AffinePoint) -> K256Affine { +pub(crate) fn to_k256_affine(a: &AffinePoint) -> K256Affine { let ep = EncodedPoint::from_affine_coordinates(&be32(&a.x).into(), &be32(&a.y).into(), false); Option::from(K256Affine::from_encoded_point(&ep)).expect("ECSM: point must be on the curve") } -fn from_k256_affine(p: &K256Affine) -> AffinePoint { +pub(crate) fn from_k256_affine(p: &K256Affine) -> AffinePoint { let ep = p.to_encoded_point(false); AffinePoint { x: BigUint::from_bytes_be(ep.x().expect("ECSM: affine point has x")), diff --git a/crypto/ecsm/src/lib.rs b/crypto/ecsm/src/lib.rs index e3a5e3a33..221ccbc76 100644 --- a/crypto/ecsm/src/lib.rs +++ b/crypto/ecsm/src/lib.rs @@ -16,6 +16,7 @@ //! Curve: secp256k1, `y^2 = x^3 + 7 mod p`, `p = 2^256 - 2^32 - 977`, order `N`. pub mod curve; +pub mod lincomb2_table; pub mod witness; #[cfg(test)] diff --git a/crypto/ecsm/src/lincomb2_table.rs b/crypto/ecsm/src/lincomb2_table.rs new file mode 100644 index 000000000..f2d58fdb5 --- /dev/null +++ b/crypto/ecsm/src/lincomb2_table.rs @@ -0,0 +1,76 @@ +//! The lincomb2 NUMS correction constants: `−2^i·T₀` for `i ∈ [0, 256]`. +//! +//! The lincomb2 joint chain seeds its accumulator with the nothing-up-my-sleeve +//! point `T₀` (see [`crate::witness::t0`] and +//! `thoughts/ec-recover-opt/lincomb2/T0.md`), so after `len` doublings the +//! accumulator carries a blind of `2^len·T₀`. The chain's final row — +//! [`crate::witness::JointSel::Correction`] — strips it by *adding* +//! `−2^len·T₀`. +//! +//! # Sign convention: these are the NEGATED points +//! +//! Entry `i` is `−2^i·T₀`, i.e. `(x(2^i·T₀), p − y(2^i·T₀))`, **not** `2^i·T₀`. +//! That is exactly the addend `lincomb2_witness` writes into the correction +//! row's `(x_g, y_g)` columns (`witness.rs`: `neg_tpow` is built by negating +//! `tpow`'s `y`, and is passed as `joint_row`'s `addend`), so a chip that wires +//! a lookup of this table straight into its addend columns needs no modular +//! negation at all. `crate::tests::lincomb2_table_tests` asserts the match +//! against a real witness rather than restating it. +//! +//! Note that only `y` differs between the two conventions — `x(−P) = x(P)` — +//! so the `x` half of an entry serves either reading. +//! +//! # Why 257 entries +//! +//! `len = max(bits(u1), bits(u2))` for scalars in `[1, N)`, so the reachable +//! range is `[1, 256]`. Entry `0` (`−T₀` itself) is defined anyway: it is the +//! anchor of the doubling recurrence and costs nothing. + +use num_bigint::BigUint; + +use k256::elliptic_curve::group::Curve as _; +use k256::{AffinePoint as K256Affine, ProjectivePoint}; + +use crate::curve::{AffinePoint, from_k256_affine, to_k256_affine}; +use crate::p; +use crate::witness::t0; + +/// Number of defined entries: `i ∈ [0, 256]`. +pub const NEG_T0_POW2_ROWS: usize = 257; + +/// `−2^i·T₀` for every `i ∈ [0, 256]`, indexed by `i`. +/// +/// Derived from [`crate::witness::t0`] by repeated doubling in `k256` +/// projective coordinates (one `batch_normalize` for the whole chain), then +/// negating each `y`. Deterministic and reproducible: the only input is the +/// pinned `T₀`. +/// +/// See the module header for the sign convention — these are the *negated* +/// points, matching the correction row's addend. +pub fn neg_t0_pow2_points() -> Vec { + let mut proj = ProjectivePoint::from(to_k256_affine(&t0())); + let mut chain = Vec::with_capacity(NEG_T0_POW2_ROWS); + for _ in 0..NEG_T0_POW2_ROWS { + chain.push(proj); + proj = proj.double(); + } + + let mut affine = vec![K256Affine::IDENTITY; NEG_T0_POW2_ROWS]; + ProjectivePoint::batch_normalize(&chain, &mut affine); + + let modulus = p(); + affine + .iter() + .map(|a| { + let pt = from_k256_affine(a); + // `T₀` generates the prime-order group, so no multiple of it is the + // identity or a 2-torsion point: `y` is never 0 and `p - y` is a + // canonical nonzero field element. + debug_assert!(pt.y != BigUint::from(0u8), "2^i·T0 has y = 0"); + AffinePoint { + x: pt.x, + y: &modulus - &pt.y, + } + }) + .collect() +} diff --git a/crypto/ecsm/src/tests/lincomb2_table_tests.rs b/crypto/ecsm/src/tests/lincomb2_table_tests.rs new file mode 100644 index 000000000..59a59c194 --- /dev/null +++ b/crypto/ecsm/src/tests/lincomb2_table_tests.rs @@ -0,0 +1,163 @@ +//! Validation for the `−2^i·T₀` correction constants. +//! +//! The constants are produced by `k256` projective doubling + `batch_normalize`; +//! every check below uses a *different* implementation (the `Fp` BigUint +//! reference, or `lincomb2_witness`'s own BigInt group law) so a bug in one +//! cannot hide behind the other. + +use num_bigint::BigUint; + +use crate::curve::AffinePoint; +use crate::lincomb2_table::{NEG_T0_POW2_ROWS, neg_t0_pow2_points}; +use crate::tests::reference::point_double; +use crate::witness::{JointSel, lincomb2_witness, t0}; +use crate::{B, n, p}; + +fn le32(v: &BigUint) -> [u8; 32] { + crate::to_le_32(v) +} + +/// `−pt`, computed here rather than read from the table under test. +fn negate(pt: &AffinePoint) -> AffinePoint { + AffinePoint { + x: pt.x.clone(), + y: &p() - &pt.y, + } +} + +/// Every entry is a canonical on-curve point (`y² ≡ x³ + b mod p`, both +/// coordinates `< p`). Independent of how the table was built. +#[test] +fn neg_t0_pow2_entries_are_on_curve_and_canonical() { + let table = neg_t0_pow2_points(); + assert_eq!(table.len(), NEG_T0_POW2_ROWS); + let modulus = p(); + for (i, pt) in table.iter().enumerate() { + assert!(pt.x < modulus, "entry {i}: x >= p"); + assert!(pt.y < modulus, "entry {i}: y >= p"); + assert!(pt.y > BigUint::ZERO, "entry {i}: y = 0 (2-torsion)"); + let lhs = (&pt.y * &pt.y) % &modulus; + let rhs = (&pt.x * &pt.x % &modulus * &pt.x + B) % &modulus; + assert_eq!(lhs, rhs, "entry {i} is not on the curve"); + } +} + +/// The table is exactly the doubling chain of `T₀`, negated: entry `0` is +/// `−T₀` and entry `i+1` is `−2·(−entry i)`. Recomputed with the `Fp` +/// reference doubling, not the `k256` path the table itself uses. +#[test] +fn neg_t0_pow2_matches_reference_doubling_chain() { + let table = neg_t0_pow2_points(); + let mut expected = t0(); + for (i, entry) in table.iter().enumerate() { + assert_eq!( + *entry, + negate(&expected), + "entry {i} != -(2^{i}·T0) under the Fp reference doubling", + ); + expected = point_double(&expected); + } +} + +/// The stored `y` is the negation of the positive multiple's `y`, and the +/// stored `x` is unchanged: `x(−P) = x(P)`, `y(−P) + y(P) ≡ 0 mod p`. This is +/// the convention assertion — if the table ever flips to storing `+2^i·T₀`, +/// this test is what fails. +#[test] +fn neg_t0_pow2_stores_the_negation_not_the_positive_multiple() { + let table = neg_t0_pow2_points(); + let modulus = p(); + let mut positive = t0(); + for (i, entry) in table.iter().enumerate() { + assert_eq!(entry.x, positive.x, "entry {i}: x must equal x(2^i·T0)"); + assert_eq!( + (&entry.y + &positive.y) % &modulus, + BigUint::ZERO, + "entry {i}: y must be the additive inverse of y(2^i·T0)", + ); + assert_ne!( + entry.y, positive.y, + "entry {i}: negation must be a real change (y != p - y for y != 0)", + ); + positive = point_double(&positive); + } +} + +/// The load-bearing test: `lincomb2_witness`'s correction row consumes its +/// addend from `(x_g, y_g)`, and that addend must be table entry `len` +/// verbatim. Covers the whole sign convention end to end, on real witnesses +/// spanning several `len` values (including the `len = 256` top row). +#[test] +fn correction_row_addend_equals_table_entry_at_len() { + let table = neg_t0_pow2_points(); + let g = { + // The generator, via the crate's own recovery path. + let gx = BigUint::parse_bytes( + b"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + 16, + ) + .unwrap(); + let gy = crate::curve::recover_y_canonical(&gx).unwrap(); + AffinePoint { x: gx, y: gy } + }; + // 2·G — a second base with an x distinct from G's, so the `P1 + P2` + // precompute is a genuine chord. + let p2 = point_double(&g); + + // Scalars chosen to exercise a spread of `len` values, including the max. + let cases = [ + BigUint::from(1u8), + BigUint::from(3u8), + BigUint::from(0xFFFFu32), + BigUint::from(1u8) << 200, + n() - 1u32, // len = 256 + ]; + + let mut seen_lens = Vec::new(); + for u1 in &cases { + for u2 in &cases { + let w = lincomb2_witness(&le32(u1), &le32(u2), &g, &p2).expect("witness"); + let len = w.len as usize; + assert!( + (1..=256).contains(&len), + "len {len} outside the reachable range", + ); + seen_lens.push(len); + + let corr = w + .steps + .iter() + .find(|s| matches!(s.sel, JointSel::Correction)) + .expect("correction row"); + let entry = &table[len]; + assert_eq!( + corr.step.x_g, + le32(&entry.x), + "len {len}: correction addend x != table entry x", + ); + assert_eq!( + corr.step.y_g, + le32(&entry.y), + "len {len}: correction addend y != table entry y \ + (sign convention broken: the table must store -2^len·T0)", + ); + + // The witness also records the *positive* blind separately; the + // table's x half serves it directly, its y half only after negation. + assert_eq!( + w.x_t0_pow, + le32(&entry.x), + "len {len}: x_t0_pow != table entry x", + ); + assert_eq!( + BigUint::from_bytes_le(&w.y_t0_pow) + &entry.y, + p(), + "len {len}: y_t0_pow is not the negation of the table entry y", + ); + } + } + assert!( + seen_lens.contains(&256), + "the len = 256 top row was never exercised", + ); +} diff --git a/crypto/ecsm/src/tests/lincomb2_tests.rs b/crypto/ecsm/src/tests/lincomb2_tests.rs new file mode 100644 index 000000000..27e5a7508 --- /dev/null +++ b/crypto/ecsm/src/tests/lincomb2_tests.rs @@ -0,0 +1,495 @@ +//! Host validation for `lincomb2_witness` (phase A). +//! +//! Three independent cross-checks per case: +//! 1. `Q` matches an `Fp`-reference lincomb (`tests::reference`, a different +//! implementation from the witness's own BigInt group law) AND k256. +//! 2. every emitted joint-chain row re-satisfies its double/add relation and +//! slope (on top of the `limb_carries` asserts that already fire at build +//! time if any quotient/carry is wrong). +//! 3. the NUMS blind cancels: the pre-correction accumulator equals +//! `Q + 2^len·T₀`, and the correction row lands on `Q`. +//! 4. the joint schedule is self-consistent: `nb` really is the "an add +//! follows" bit, and the round recurrence `round − 1 + nb` walks the chain +//! from `len − 1` down to the drain sentinel `−1` (`check_nb_schedule`). + +use num_bigint::BigUint; + +use crate::curve::AffinePoint; +use crate::tests::reference::{point_add, point_double, step_lambda}; +use crate::witness::{JointSel, Lincomb2Error, Lincomb2Witness, lincomb2_witness, t0}; +use crate::{n, p}; + +use k256::elliptic_curve::ff::PrimeField as _; +use k256::elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint}; +use k256::{AffinePoint as K256Affine, EncodedPoint, ProjectivePoint, Scalar}; + +// ---- helpers ---- + +fn be32(v: &BigUint) -> [u8; 32] { + let b = v.to_bytes_be(); + let mut out = [0u8; 32]; + out[32 - b.len()..].copy_from_slice(&b); + out +} + +fn to_k256(a: &AffinePoint) -> ProjectivePoint { + let ep = EncodedPoint::from_affine_coordinates(&be32(&a.x).into(), &be32(&a.y).into(), false); + ProjectivePoint::from(K256Affine::from_encoded_point(&ep).unwrap()) +} + +fn from_k256(p: &ProjectivePoint) -> AffinePoint { + let a = p.to_affine(); + let ep = a.to_encoded_point(false); + AffinePoint { + x: BigUint::from_bytes_be(ep.x().unwrap()), + y: BigUint::from_bytes_be(ep.y().unwrap()), + } +} + +fn generator() -> AffinePoint { + from_k256(&ProjectivePoint::GENERATOR) +} + +/// Independent point-scalar-mul via the `Fp` reference (MSB-first). +fn ref_scalar_mul(k: &BigUint, pt: &AffinePoint) -> AffinePoint { + let bits = k.bits(); + let mut acc = pt.clone(); + for i in (0..bits - 1).rev() { + acc = point_double(&acc); + if k.bit(i) { + acc = point_add(&acc, pt); + } + } + acc +} + +/// Independent lincomb2 via the `Fp` reference. +fn ref_lincomb2(u1: &BigUint, p1: &AffinePoint, u2: &BigUint, p2: &AffinePoint) -> AffinePoint { + let a = ref_scalar_mul(u1, p1); + let b = ref_scalar_mul(u2, p2); + if a.x == b.x { + assert_eq!(a.y, b.y, "reference lincomb2 hit infinity"); + point_double(&a) + } else { + point_add(&a, &b) + } +} + +fn k256_lincomb2(u1: &BigUint, p1: &AffinePoint, u2: &BigUint, p2: &AffinePoint) -> AffinePoint { + let s1 = Scalar::from_repr(be32(u1).into()).unwrap(); + let s2 = Scalar::from_repr(be32(u2).into()).unwrap(); + from_k256(&(to_k256(p1) * s1 + to_k256(p2) * s2)) +} + +fn pt(x: &[u8; 32], y: &[u8; 32]) -> AffinePoint { + AffinePoint { + x: BigUint::from_bytes_le(x), + y: BigUint::from_bytes_le(y), + } +} + +/// Deterministic pseudo-random scalar in `[1, N)` from a seed. +fn scalar(seed: u64) -> BigUint { + // splitmix64-ish expansion to 256 bits, then reduce into [1, N). + let mut s = seed.wrapping_mul(0x9E3779B97F4A7C15).wrapping_add(1); + let mut bytes = [0u8; 32]; + for chunk in bytes.chunks_mut(8) { + s ^= s >> 30; + s = s.wrapping_mul(0xBF58476D1CE4E5B9); + s ^= s >> 27; + s = s.wrapping_mul(0x94D049BB133111EB); + s ^= s >> 31; + chunk.copy_from_slice(&s.to_le_bytes()); + } + BigUint::from_bytes_le(&bytes) % (n() - 1u32) + 1u32 +} + +fn le32(v: &BigUint) -> [u8; 32] { + crate::to_le_32(v) +} + +/// The joint-schedule invariants the ECDAS′ chip will constrain, checked at the +/// source. +/// +/// `nb` is the only thing pinning a double row's successor round — the doubling +/// and its optional add share a round, so `round − 1 + nb` is not derivable from +/// the other columns. A prover who could stall `round` would insert or drop +/// doublings while every per-row relation still held, so a failure here is a +/// soundness hole in whatever chip consumes this witness, not a cosmetic bug. +fn check_nb_schedule(w: &Lincomb2Witness, u1: &BigUint, u2: &BigUint) { + let steps = &w.steps; + assert!( + steps.len() >= 3, + "chain must be precompute + at least one round + correction" + ); + + // Row-local facts that hold everywhere, boundary rows included. These are + // exactly the two constraints the chip needs to define `nb`: + // OP · NB = 0 (degree 2) + // (1 − OP) · (NB − D1 − D2 + D1·D2) = 0 (degree 3) + // Note the second is op-gated: an ADD row carries its round's digits (it + // needs them to select the addend) but `nb = 0`, because the row after an + // add is always the next round's double. + for (i, js) in steps.iter().enumerate() { + assert!(js.d1 <= 1 && js.d2 <= 1, "row {i}: digits are not bits"); + assert!(js.nb <= 1, "row {i}: nb is not a bit"); + assert!(js.step.op <= 1, "row {i}: op is not a bit"); + // `nb` is mirrored into the EcdasStep slot so a chip may read either. + assert_eq!(js.nb, js.step.next_op, "row {i}: nb != step.next_op"); + // an add is never followed by an add (today's ECDAS `OP · NEXT_OP = 0`) + assert_eq!(js.step.op * js.nb, 0, "row {i}: op*nb != 0"); + // on a double, `nb` is the OR of the digits, in the degree-2 form + if js.step.op == 0 { + assert_eq!( + js.nb, + js.d1 + js.d2 - js.d1 * js.d2, + "row {i}: double's nb != d1 + d2 - d1*d2" + ); + } + } + + // The two rows that sit off the accumulator line carry no digit. + let first = &steps[0]; + assert_eq!( + first.sel, + JointSel::Precompute, + "row 0 must be the precompute" + ); + assert_eq!( + (first.d1, first.d2, first.nb), + (0, 0, 0), + "precompute row must be digit-free" + ); + let last = steps.last().expect("non-empty"); + assert_eq!( + last.sel, + JointSel::Correction, + "last row must be the correction" + ); + assert_eq!( + (last.d1, last.d2, last.nb), + (0, 0, 0), + "correction row must be digit-free" + ); + + // Walk the main chain: round starts at len-1 and each row steps it by + // `-1 + nb`, draining at the sentinel -1. + let main = &steps[1..steps.len() - 1]; + let mut expected_round = w.len as i32 - 1; + for (i, js) in main.iter().enumerate() { + assert_eq!( + js.step.round as i32, expected_round, + "main row {i}: round drifted from the recurrence" + ); + let round = expected_round as u64; + + // Both row kinds carry this round's true digits (the double needs them + // for `nb` and its per-stream Bit sends, the add to pick the addend). + assert_eq!( + js.d1, + u1.bit(round) as u8, + "row {i} (round {round}): d1 != u1 bit" + ); + assert_eq!( + js.d2, + u2.bit(round) as u8, + "row {i} (round {round}): d2 != u2 bit" + ); + + match js.sel { + JointSel::Double => assert_eq!(js.step.op, 0), + JointSel::AddP1 | JointSel::AddP2 | JointSel::AddP12 => { + assert_eq!(js.step.op, 1); + // the addend is a function of the digits + let want = match (js.d1, js.d2) { + (1, 0) => JointSel::AddP1, + (0, 1) => JointSel::AddP2, + (1, 1) => JointSel::AddP12, + _ => panic!("add row at round {round} with a zero joint digit"), + }; + assert_eq!(js.sel, want, "row {i} (round {round}): sel != f(d1, d2)"); + assert_eq!(js.nb, 0, "an add row must not claim a pending add"); + } + other => panic!("main row {i} carries boundary selector {other:?}"), + } + + // `nb == 1` exactly when the next emitted row is this round's add. + match main.get(i + 1) { + Some(next) if js.nb == 1 => { + assert_eq!( + next.step.op, 1, + "row {i}: nb=1 but the next row is not an add" + ); + assert_eq!( + next.step.round, js.step.round, + "row {i}: the add must share the double's round" + ); + } + Some(next) => { + assert_eq!(next.step.op, 0, "row {i}: nb=0 but the next row is an add"); + assert_eq!( + next.step.round as i32, + js.step.round as i32 - 1, + "row {i}: nb=0 must step the round down by one" + ); + } + None => assert_eq!(js.nb, 0, "the last main row cannot have a pending add"), + } + + expected_round = expected_round - 1 + js.nb as i32; + } + assert_eq!( + expected_round, -1, + "main chain must drain at the sentinel round -1" + ); +} + +/// The full validation battery for one input tuple. Returns the row count. +fn validate(u1: &BigUint, p1: &AffinePoint, u2: &BigUint, p2: &AffinePoint) -> usize { + let w = lincomb2_witness(&le32(u1), &le32(u2), p1, p2).expect("witness"); + + // 1. Q correctness — two independent references. + let q = pt(&w.x_q, &w.y_q); + let q_ref = ref_lincomb2(u1, p1, u2, p2); + assert_eq!(q, q_ref, "Q != Fp-reference lincomb2"); + assert_eq!(q, k256_lincomb2(u1, p1, u2, p2), "Q != k256 lincomb2"); + + // canonicalization witnesses must correspond to values < p / < N. + assert!(q.x < p() && q.y < p(), "Q not canonical"); + assert!(pt(&w.x_p2, &w.y_p2).y < p(), "yP2 not canonical"); + + // 2. every row re-satisfies its relation and slope. + let mut n_dbl = 0usize; + let mut n_add = 0usize; + for js in &w.steps { + let s = &js.step; + let a = pt(&s.x_a, &s.y_a); + let r = pt(&s.x_r, &s.y_r); + let lambda = BigUint::from_bytes_le(&s.lambda); + match js.sel { + JointSel::Double => { + assert_eq!(s.op, 0); + assert_eq!(point_double(&a), r, "double row wrong result"); + assert_eq!(step_lambda(&a, &a, 0), lambda, "double row wrong slope"); + n_dbl += 1; + } + _ => { + assert_eq!(s.op, 1); + let addend = pt(&s.x_g, &s.y_g); + assert_eq!(point_add(&a, &addend), r, "add row wrong result"); + assert_eq!(step_lambda(&a, &addend, 1), lambda, "add row wrong slope"); + if matches!(js.sel, JointSel::AddP1 | JointSel::AddP2 | JointSel::AddP12) { + n_add += 1; + } + } + } + } + + // 3. blind cancels: 2^len·T₀ recorded, and pre-correction acc = Q + 2^len·T₀. + let tpow = pt(&w.x_t0_pow, &w.y_t0_pow); + // recompute 2^len·T₀ independently from T₀. + let mut t = t0(); + for _ in 0..w.len { + t = point_double(&t); + } + assert_eq!(t, tpow, "recorded 2^len·T0 wrong"); + // the correction row's incoming accumulator must equal Q + 2^len·T₀. + let corr = w + .steps + .iter() + .find(|j| matches!(j.sel, JointSel::Correction)) + .unwrap(); + let acc_before = pt(&corr.step.x_a, &corr.step.y_a); + assert_eq!(acc_before, point_add(&q, &t), "acc_before != Q + 2^len·T0"); + + // 4. the joint schedule is self-consistent. + check_nb_schedule(&w, u1, u2); + + // rows = P12-precompute + doublings + adds + correction. + assert_eq!(n_dbl, w.len as usize, "doubling count != len"); + 2 + n_dbl + n_add +} + +// ---- tests ---- + +#[test] +fn t0_is_on_curve_and_pinned() { + let t = t0(); + assert!(t.x < p() && t.y < p()); + let lhs = (&t.y * &t.y) % p(); + let rhs = (&t.x * &t.x % p() * &t.x + 7u32) % p(); + assert_eq!(lhs, rhs, "T0 not on curve"); + assert!(&t.y % 2u32 == BigUint::from(0u32), "T0.y not even"); +} + +#[test] +fn lincomb2_random_matches_references() { + let g = generator(); + let mut rows_sum = 0usize; + let mut rows_max = 0usize; + const CASES: usize = 512; + for i in 0..CASES { + let u1 = scalar(2 * i as u64 + 1); + let u2 = scalar(2 * i as u64 + 2); + let p1 = if i % 3 == 0 { + g.clone() + } else { + ref_scalar_mul(&scalar(1000 + i as u64), &g) + }; + let p2 = ref_scalar_mul(&scalar(5000 + i as u64), &g); + let rows = validate(&u1, &p1, &u2, &p2); + rows_sum += rows; + rows_max = rows_max.max(rows); + } + println!( + "lincomb2 rows/ecrecover: mean {:.1}, max {} over {} cases", + rows_sum as f64 / CASES as f64, + rows_max, + CASES + ); +} + +/// The whole emitted schedule for a hand-checkable digit pattern, spelled out +/// row by row. `check_nb_schedule` proves the recurrence is *self*-consistent +/// over the random corpus; this pins what the recurrence actually produces, so +/// a change of convention (say, moving the digits onto the add row only, or +/// decrementing the round on the double) fails here loudly instead of silently +/// re-balancing. +/// +/// `u1 = 0b1010`, `u2 = 0b0011`, so `len = 4` and the four rounds carry joint +/// digits `(1,0) (0,0) (1,1) (0,1)` — every addend selector plus one round with +/// no add at all. +#[test] +fn nb_schedule_matches_hand_worked_example() { + let g = generator(); + let r = ref_scalar_mul(&scalar(42), &g); + let (u1, u2) = (BigUint::from(0b1010u32), BigUint::from(0b0011u32)); + + let w = lincomb2_witness(&le32(&u1), &le32(&u2), &g, &r).expect("witness"); + assert_eq!(w.len, 4, "len = max(bits(u1), bits(u2))"); + check_nb_schedule(&w, &u1, &u2); + + // (sel, round, nb, d1, d2) + let expected = [ + (JointSel::Precompute, 0u8, 0u8, 0u8, 0u8), + (JointSel::Double, 3, 1, 1, 0), + (JointSel::AddP1, 3, 0, 1, 0), + (JointSel::Double, 2, 0, 0, 0), + (JointSel::Double, 1, 1, 1, 1), + (JointSel::AddP12, 1, 0, 1, 1), + (JointSel::Double, 0, 1, 0, 1), + (JointSel::AddP2, 0, 0, 0, 1), + (JointSel::Correction, 0, 0, 0, 0), + ]; + let got: Vec<_> = w + .steps + .iter() + .map(|js| (js.sel, js.step.round, js.nb, js.d1, js.d2)) + .collect(); + assert_eq!(got, expected.to_vec(), "joint schedule changed"); +} + +#[test] +fn lincomb2_edge_scalars() { + let g = generator(); + let r = ref_scalar_mul(&scalar(42), &g); + let edges = [ + (BigUint::from(1u32), BigUint::from(1u32)), + (BigUint::from(1u32), BigUint::from(2u32)), + (BigUint::from(3u32), BigUint::from(5u32)), + ( + BigUint::from(1u32) << 255u32, + (BigUint::from(1u32) << 255u32) - 1u32, + ), + (n() - 1u32, n() - 1u32), + (n() - 1u32, BigUint::from(1u32)), + ( + (BigUint::from(1u32) << 200u32) - 1u32, + BigUint::from(1u32) << 199u32, + ), + ]; + for (u1, u2) in edges { + // P1 = G, P2 = a random point (R-shaped); skip if Q hits infinity. + match lincomb2_witness(&crate::to_le_32(&u1), &crate::to_le_32(&u2), &g, &r) { + Ok(_) => { + let _ = validate(&u1, &g, &u2, &r); + } + Err(Lincomb2Error::ResultInfinity) => { /* legitimate infinity */ } + Err(e) => panic!("unexpected error {e:?} for u1={u1}, u2={u2}"), + } + } +} + +#[test] +fn lincomb2_rejects_degenerate_sum() { + let g = generator(); + let neg_g = AffinePoint { + x: g.x.clone(), + y: (p() - &g.y) % p(), + }; + // P1 = G, P2 = -G ⇒ P1 = -P2 ⇒ SumDegenerate. + let err = lincomb2_witness( + &crate::to_le_32(&scalar(1)), + &crate::to_le_32(&scalar(2)), + &g, + &neg_g, + ); + assert_eq!(err.unwrap_err(), Lincomb2Error::SumDegenerate); + // P1 = P2 = G ⇒ equal x ⇒ SumDegenerate. + let err2 = lincomb2_witness( + &crate::to_le_32(&scalar(1)), + &crate::to_le_32(&scalar(2)), + &g, + &g, + ); + assert_eq!(err2.unwrap_err(), Lincomb2Error::SumDegenerate); +} + +#[test] +fn lincomb2_rejects_bad_scalars() { + let g = generator(); + let r = ref_scalar_mul(&scalar(7), &g); + let zero = [0u8; 32]; + assert_eq!( + lincomb2_witness(&zero, &crate::to_le_32(&scalar(1)), &g, &r).unwrap_err(), + Lincomb2Error::ScalarIsZero + ); + assert_eq!( + lincomb2_witness(&crate::to_le_32(&n()), &crate::to_le_32(&scalar(1)), &g, &r).unwrap_err(), + Lincomb2Error::ScalarOutOfRange + ); +} + +#[test] +fn t0_derivation_matches() { + use sha2::{Digest, Sha256}; + let tag = b"lambdavm/ecsm/lincomb2/T0/v1"; + let mut counter: u32 = 0; + let (x, y) = loop { + let mut h = Sha256::new(); + h.update(tag); + h.update(counter.to_be_bytes()); + let digest = h.finalize(); + let x = BigUint::from_bytes_be(&digest); + if x < p() { + // even y with y² = x³ + 7, if x is on the curve. + let rhs = (&x * &x % p() * &x + 7u32) % p(); + // sqrt via p ≡ 3 mod 4 + let exp = (p() + 1u32) / 4u32; + let root = rhs.modpow(&exp, &p()); + if (&root * &root) % p() == rhs { + let y = if &root % 2u32 == BigUint::from(0u32) { + root.clone() + } else { + p() - &root + }; + break (x, y); + } + } + counter += 1; + }; + assert_eq!(counter, 1, "T0 derivation counter changed"); + let t = t0(); + assert_eq!(t.x, x, "T0.x derivation mismatch"); + assert_eq!(t.y, y, "T0.y derivation mismatch"); +} diff --git a/crypto/ecsm/src/tests/mod.rs b/crypto/ecsm/src/tests/mod.rs index 74e5080c0..73d7885eb 100644 --- a/crypto/ecsm/src/tests/mod.rs +++ b/crypto/ecsm/src/tests/mod.rs @@ -12,4 +12,6 @@ pub mod reference_field; mod curve_tests; mod lib_tests; +mod lincomb2_table_tests; +mod lincomb2_tests; mod witness_tests; diff --git a/crypto/ecsm/src/witness.rs b/crypto/ecsm/src/witness.rs index acfd820f2..99b0d9125 100644 --- a/crypto/ecsm/src/witness.rs +++ b/crypto/ecsm/src/witness.rs @@ -83,7 +83,12 @@ pub struct EcdasStep { // ========================================================================= /// Zero-extends a little-endian byte slice (≤ 64 bytes) to 64 `i128` limbs. -fn ext64(bytes: &[u8]) -> [i128; 64] { +/// +/// `pub` so the chips can build the *same* limb identities this module does. +/// There must be exactly one implementation of this arithmetic: a second copy in +/// the prover would be the classic divergence, where one side is edited years +/// later and the other is not. +pub fn ext64(bytes: &[u8]) -> [i128; 64] { let mut a = [0i128; 64]; for (i, &b) in bytes.iter().enumerate() { a[i] = b as i128; @@ -91,8 +96,8 @@ fn ext64(bytes: &[u8]) -> [i128; 64] { a } -/// Convolution `Σ_{j=0}^{i} a[j]·b[i-j]`. -fn conv(a: &[i128; 64], b: &[i128; 64], i: usize) -> i128 { +/// Convolution `Σ_{j=0}^{i} a[j]·b[i-j]`. `pub` for the reason on [`ext64`]. +pub fn conv(a: &[i128; 64], b: &[i128; 64], i: usize) -> i128 { let mut s = 0i128; for j in 0..=i { s += a[j] * b[i - j]; @@ -105,7 +110,9 @@ fn conv(a: &[i128; 64], b: &[i128; 64], i: usize) -> i128 { /// /// These asserts catch any transcription error in the `terms` builders: for valid inputs /// the relation `LHS − RHS = 0` holds exactly, so every partial sum is divisible by 256. -fn limb_carries(relation: &str, terms: &[i128; 64]) -> [i64; 64] { +/// +/// `pub` for the reason on [`ext64`]; `relation` names the caller in the panics. +pub fn limb_carries(relation: &str, terms: &[i128; 64]) -> [i64; 64] { let mut c = [0i64; 64]; let mut carry: i128 = 0; for i in 0..64 { @@ -241,7 +248,8 @@ fn carries_yr( // ========================================================================= /// Little-endian 33 bytes of a non-negative value that fits in 264 bits. -fn to_le_33(relation: &str, v: &BigUint) -> [u8; 33] { +/// `pub` for the reason on [`ext64`]. +pub fn to_le_33(relation: &str, v: &BigUint) -> [u8; 33] { let mut bytes = v.to_bytes_le(); assert!( bytes.len() <= 33, @@ -457,3 +465,625 @@ fn build_step( c2, } } + +// ========================================================================= +// lincomb2: Q = u1·P1 + u2·P2 via NUMS-blinded joint Shamir/Straus. +// +// PHASE A (this block): witness generation + host validation only. The +// prover chip, executor syscall, and guest switch come in later phases; this +// is the layout lock the chip consumes. The per-row math REUSES the audited, +// gate-verified `build_step` / `carries_*` machinery above — a joint-chain row +// is exactly one double-or-add step, so only the schedule and the choice of +// addend differ from the single-scalar chain. +// ========================================================================= + +use crate::curve::AffinePoint; + +/// NUMS blinding point `T₀` — hash-to-curve of the tag +/// `"lambdavm/ecsm/lincomb2/T0/v1"` by SHA-256 try-and-increment: candidate +/// `x = SHA-256(tag || counter_be32)` (big-endian), first `counter` giving a +/// canonical curve `x` with the even `y`. Result: counter = 1, y even. Derived +/// and reproduced independently in `thoughts/ec-recover-opt/lincomb2/T0.md`, +/// the Python `oracle/lincomb2_ref.py::t0_ref`, and the `t0_derivation_matches` +/// dev test (which re-runs the SHA-256 search). Pinned here as a constant so +/// the crate needs no runtime hash dependency. +pub const T0_X_LE: [u8; 32] = [ + 0x64, 0x78, 0xAE, 0xB1, 0x0C, 0x07, 0x49, 0x1B, 0xDB, 0x93, 0x88, 0xA9, 0x9A, 0xA7, 0xFB, 0x5E, + 0x66, 0x0A, 0x33, 0xDB, 0x5E, 0xE8, 0x7D, 0x29, 0x6B, 0xA8, 0x91, 0x0F, 0xA9, 0x9A, 0x31, 0xAF, +]; +pub const T0_Y_LE: [u8; 32] = [ + 0xA0, 0x77, 0x62, 0x60, 0x4A, 0x25, 0x3C, 0x3F, 0x19, 0x82, 0x7D, 0x21, 0xFA, 0x24, 0xE6, 0xA2, + 0x8C, 0x5B, 0xB0, 0xF3, 0xBC, 0xB0, 0x1D, 0x07, 0x32, 0x07, 0x3C, 0x14, 0x38, 0xA0, 0x81, 0x14, +]; + +/// The pinned NUMS blinding point `T₀` as an affine point. +pub fn t0() -> AffinePoint { + AffinePoint { + x: BigUint::from_bytes_le(&T0_X_LE), + y: BigUint::from_bytes_le(&T0_Y_LE), + } +} + +/// Reasons a sound lincomb2 witness cannot be built. The executor maps these to +/// a non-zero status word; the guest then takes its pure-Rust software fallback +/// (`ProjectivePoint::lincomb`), which is sound because guest code is proven +/// execution — a lying status only wastes cycles, it can never forge a result. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Lincomb2Error { + /// `u1` or `u2` is zero. + ScalarIsZero, + /// `u1` or `u2` is `>= N`. + ScalarOutOfRange, + /// `P1` or `P2` is not on the curve. + PointNotOnCurve, + /// `P1` or `P2` has a non-canonical coordinate (`>= p`). + PointNotCanonical, + /// `P1 = ±P2`: the `P1 + P2` precompute is a double or infinity (the + /// addend table would be degenerate). + SumDegenerate, + /// `Q = u1·P1 + u2·P2` is the point at infinity, or an intermediate + /// accumulator collided with its addend (blinding makes the latter a + /// discrete-log event; either way there is no affine witness). + ResultInfinity, +} + +/// Curve-membership sub-witness proving `y² ≡ x³ + b (mod p)` for a point +/// `(x, y)` — the same two byte-limb convolutions ECSM proves for its +/// generator, reused here for the variable point `P2`. +#[derive(Debug, Clone)] +pub struct MembershipWitness { + /// `x2 = x² mod p` + pub x2: [u8; 32], + /// quotient for the `x2` relation + pub q0: [u8; 32], + /// carries for the `x2` relation + pub c0: [i64; 64], + /// quotient for the `y²` relation (33 bytes) + pub q1: [u8; 33], + /// carries for the `y²` relation + pub c1: [i64; 64], +} + +/// The role of one joint-chain row, and which addend (if any) it consumes. +/// Distinguishes the rows the chip treats differently even though all share the +/// double/add convolution core. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum JointSel { + /// A doubling (`op = 0`); no addend (the addend columns are zero and cancel + /// out of all three relations). + Double, + /// An add of `P1` (joint digit `10`). + AddP1, + /// An add of `P2` (joint digit `01`). + AddP2, + /// An add of `P12 = P1 + P2` (joint digit `11`). + AddP12, + /// The `P1 + P2` precompute row (produces `P12`). + Precompute, + /// The final blinding correction: add `−2^len·T₀` to strip the blind. + Correction, +} + +/// One row of the joint chain: the double/add step witness (identical shape to +/// [`EcdasStep`], reusing its λ/quotient/carry math) plus the joint-chain +/// bookkeeping the chip needs (which addend, the two scalar digit bits, and +/// whether an add follows). +#[derive(Debug, Clone)] +pub struct JointStep { + pub step: EcdasStep, + pub sel: JointSel, + /// `u1`'s bit at this row's round (0 on the precompute/correction rows, + /// which belong to no round). Set on **both** the double and the add of a + /// round: the double needs it to derive [`nb`](Self::nb) and to drive its + /// per-stream `Bit` sends, the add needs it to select the addend. + pub d1: u8, + /// `u2`'s bit at this row's round. Same rows as [`d1`](Self::d1). + pub d2: u8, + /// "An add follows me at this same round" — `nb = d1 ∨ d2 = d1 + d2 − d1·d2` + /// on a double row, and `0` on every add / precompute / correction row. + /// + /// # Why this exists + /// + /// The joint schedule emits a doubling and its optional add at the **same** + /// round, decrementing only at the loop boundary, so the successor round is + /// `round − 1 + nb`. Without `nb` that successor is not a function of the + /// row's own columns, and a prover could stall `round` — inserting or + /// dropping doublings while every per-row relation still holds. It is the + /// joint-chain analogue of `EcdasStep::next_op` in the single-scalar chain + /// (`prover/src/tables/ecdas.rs` sends `round - 1 + next_op` on its + /// outgoing accumulator tuple), and is mirrored into + /// [`EcdasStep::next_op`] so a chip can reuse that column and expression + /// unchanged. + /// + /// The chain still drains at the sentinel round `−1`: the last row of a + /// round-0 iteration always has `nb = 0` (an add is never followed by an + /// add), so `0 − 1 + 0 = −1` either way. + pub nb: u8, +} + +/// Full lincomb2-chip witness for one `Q = u1·P1 + u2·P2` evaluation. +/// +/// This struct IS the layout lock: every field is a column block the ECSM′/joint +/// chip must carry. LE byte order throughout, matching the ECSM ABI. +#[derive(Debug, Clone)] +pub struct Lincomb2Witness { + pub x_p1: [u8; 32], + pub y_p1: [u8; 32], + pub x_p2: [u8; 32], + pub y_p2: [u8; 32], + /// `P2` curve-membership witness (`P1` is the fixed generator for ecrecover, + /// on-curve by definition — the chip may hardcode it). + pub mem_p2: MembershipWitness, + /// `yP2 < p` canonicalization (NEW load-bearing: `yP2 + p` would flip the + /// effective parity of `P2` as bytes and hence the sign of `Q`). + pub y_p2_sub_p: [u8; 32], + pub x_p12: [u8; 32], + pub y_p12: [u8; 32], + pub u1: [u8; 32], + pub u2: [u8; 32], + /// `u1 < N` / `u2 < N` overflow witnesses (`2^256 + u − N`). + pub u1_sub_n: [u8; 32], + pub u2_sub_n: [u8; 32], + /// Number of doublings = `max(msb(u1), msb(u2)) + 1`; also the exponent of + /// the blind `2^len·T₀` the correction row strips. + pub len: u16, + pub x_q: [u8; 32], + pub y_q: [u8; 32], + /// `xQ < p` / `yQ < p` canonicalization (NEW load-bearing: a `+p`-shifted + /// output coordinate hashes to a different address in the guest's keccak). + pub x_q_sub_p: [u8; 32], + pub y_q_sub_p: [u8; 32], + /// `T₀` and `2^len·T₀`, the blinding constants (from the preprocessed + /// T₀ table, indexed by `len`); recorded so the chip can bind them. + pub x_t0: [u8; 32], + pub y_t0: [u8; 32], + pub x_t0_pow: [u8; 32], + pub y_t0_pow: [u8; 32], + /// The chain rows: `[Precompute, , Correction]`. + pub steps: Vec, +} + +// ---- minimal affine group law over BigInt mod p (witness-side, not perf-critical) ---- + +/// `v mod p`, always in `[0, p)`. +fn red(v: &BigInt, p_big: &BigInt) -> BigInt { + let m = v % p_big; + if m.is_negative() { m + p_big } else { m } +} + +/// Modular inverse via Fermat (`p` prime). +fn finv_i(a: &BigInt, p_big: &BigInt) -> BigInt { + red(a, p_big).modpow(&(p_big - BigInt::from(2)), p_big) +} + +/// Point double, returning `(2·P, λ)` with `λ = 3x²/(2y)`. +fn ec_double(a: &(BigInt, BigInt), p_big: &BigInt) -> (BigInt, BigInt, BigInt) { + let (x, y) = a; + let two = BigInt::from(2u32); + let three = BigInt::from(3u32); + let lam = red(&(&three * x * x * finv_i(&(&two * y), p_big)), p_big); + let x3 = red(&(&lam * &lam - &two * x), p_big); + let y3 = red(&(&lam * (x - &x3) - y), p_big); + (x3, y3, lam) +} + +/// Point add of distinct-x points, returning `(P + G, λ)` with `λ = (yG−y)/(xG−x)`. +fn ec_add(a: &(BigInt, BigInt), g: &(BigInt, BigInt), p_big: &BigInt) -> (BigInt, BigInt, BigInt) { + let (xa, ya) = a; + let (xg, yg) = g; + let lam = red(&((yg - ya) * finv_i(&(xg - xa), p_big)), p_big); + let x3 = red(&(&lam * &lam - xa - xg), p_big); + let y3 = red(&(&lam * (xa - &x3) - ya), p_big); + (x3, y3, lam) +} + +fn to_pt(a: &AffinePoint) -> (BigInt, BigInt) { + (BigInt::from(a.x.clone()), BigInt::from(a.y.clone())) +} + +fn to_affine(p: &(BigInt, BigInt)) -> AffinePoint { + AffinePoint { + x: p.0.to_biguint().expect("reduced"), + y: p.1.to_biguint().expect("reduced"), + } +} + +/// `2^256 + v − modulus` as 32 LE bytes — the strict-inequality (`v < modulus`) +/// overflow witness, mirroring `x_g_sub_p` in `compute_witness`. Requires +/// `v < modulus` so the result is `< 2^256`. +fn sub_witness(v: &BigUint, modulus: &BigUint) -> [u8; 32] { + let two_256 = BigUint::from(1u8) << 256u32; + to_le_32(&((&two_256 + v) - modulus)) +} + +/// Curve-membership sub-witness for `(x, y)`: reuses the exact `x2` and `yG` +/// convolutions of `compute_witness`. +fn membership_witness(x: &BigUint, y: &BigUint, pp: &[i128; 64]) -> MembershipWitness { + let p_big = BigInt::from(p()); + let x_b = to_le_32(x); + let y_b = to_le_32(y); + + let x_sq = x * x; + let x2_big = &x_sq % p(); + let q0_big = (&x_sq - &x2_big) / p(); // exact + let x2_b = to_le_32(&x2_big); + let q0_b = to_le_32(&q0_big); + let c0 = carries_x2(&ext64(&x_b), &ext64(&x2_b), &ext64(&q0_b), pp); + + let num_y = BigInt::from(y * y) - BigInt::from(x * &x2_big) - BigInt::from(B); + let q1_big = shifted_quotient("membership-y", &num_y, &p_big, &p_big); + let q1_b = to_le_33("membership-y", &q1_big); + let b_ext = ext64(&{ + let mut a = [0u8; 32]; + a[0] = B as u8; + a + }); + let c1 = carries_yg( + &ext64(&y_b), + pp, + &ext64(&x2_b), + &ext64(&x_b), + &ext64(&q1_b), + &b_ext, + ); + + MembershipWitness { + x2: x2_b, + q0: q0_b, + c0, + q1: q1_b, + c1, + } +} + +/// Validates a point is on-curve and canonical (both coordinates `< p`). +fn check_point(pt: &AffinePoint) -> Result<(), Lincomb2Error> { + if pt.x >= p() || pt.y >= p() { + return Err(Lincomb2Error::PointNotCanonical); + } + let lhs = (&pt.y * &pt.y) % p(); + let rhs = (&pt.x * &pt.x % p() * &pt.x + B) % p(); + if lhs != rhs { + return Err(Lincomb2Error::PointNotOnCurve); + } + Ok(()) +} + +/// Builds one joint-chain row from a raw (a, addend, op, result, λ) tuple by +/// delegating to the shared `build_step`. `round`/`nb` are bookkeeping the +/// convolution relations do not consume (`build_step` copies `next_op` straight +/// through and never reads it); on a `Double` row the addend is `(0,0)` and +/// cancels out of all three relations. +/// +/// `nb` lands in both [`JointStep::nb`] — the named joint-schedule field — and +/// [`EcdasStep::next_op`], whose documented meaning ("1 ⇒ next row adds at this +/// round") is exactly the same predicate. Keeping them in sync lets a chip use +/// either slot; `tests::lincomb2_tests::check_nb_schedule` asserts on every +/// emitted row that they never diverge. +#[allow(clippy::too_many_arguments)] +fn joint_row( + a: &AffinePoint, + addend: &AffinePoint, + op: u8, + round: u8, + nb: u8, + r: &AffinePoint, + lambda: BigUint, + sel: JointSel, + d1: u8, + d2: u8, + p_big: &BigInt, + r_big: &BigInt, + r_ext: &[i128; 64], + pp: &[i128; 64], +) -> JointStep { + let s = StepPts { + a: a.clone(), + g: addend.clone(), + round, + op, + next_op: nb, + r: r.clone(), + lambda, + }; + JointStep { + step: build_step(&s, p_big, r_big, r_ext, pp), + sel, + d1, + d2, + nb, + } +} + +/// Computes the full lincomb2 witness for `Q = u1·P1 + u2·P2` over secp256k1. +/// `u1_le`, `u2_le` are little-endian 32-byte scalars in `[1, N)`; `p1`, `p2` +/// are canonical on-curve affine points. For ecrecover `P1 = G`, `P2 = R`. +pub fn lincomb2_witness( + u1_le: &[u8; 32], + u2_le: &[u8; 32], + p1: &AffinePoint, + p2: &AffinePoint, +) -> Result { + let u1 = BigUint::from_bytes_le(u1_le); + let u2 = BigUint::from_bytes_le(u2_le); + for u in [&u1, &u2] { + if u.is_zero() { + return Err(Lincomb2Error::ScalarIsZero); + } + if *u >= n() { + return Err(Lincomb2Error::ScalarOutOfRange); + } + } + check_point(p1)?; + check_point(p2)?; + + let p_big = BigInt::from(p()); + let r_big = BigInt::from(BigUint::from_bytes_le(&R_BYTES)); // r = 3p + let pp = ext64(&P_BYTES); + let r_ext = ext64(&R_BYTES); + let zero_pt = AffinePoint { + x: BigUint::zero(), + y: BigUint::zero(), + }; + + // --- P12 = P1 + P2 (must be a genuine chord: P1 ≠ ±P2) --- + if p1.x == p2.x { + return Err(Lincomb2Error::SumDegenerate); + } + let p1_i = to_pt(p1); + let p2_i = to_pt(p2); + let (x12, y12, lam12) = ec_add(&p1_i, &p2_i, &p_big); + let p12 = to_affine(&(x12.clone(), y12.clone())); + + // --- schedule length and the blind exponent --- + let len = core::cmp::max(u1.bits(), u2.bits()) as usize; // = max_msb + 1 + let t0_pt = t0(); + let t0_i = to_pt(&t0_pt); + + // --- NUMS-blinded joint Shamir/Straus replay --- + let mut steps: Vec = Vec::with_capacity(len + 194); + + // Row 0: the P12 precompute (a chord add of P1 + P2). + steps.push(joint_row( + p1, + p2, + 1, + 0, + 0, + &p12, + lam12.to_biguint().expect("reduced"), + JointSel::Precompute, + 0, + 0, + &p_big, + &r_big, + &r_ext, + &pp, + )); + + let mut acc = t0_i.clone(); + for round in (0..len).rev() { + // This round's joint digit, read before the doubling is emitted: the + // double row carries it too, because `nb` (whether the add below + // follows) is what pins its successor round. See `JointStep::nb`. + let d1 = u1.bit(round as u64) as u8; + let d2 = u2.bit(round as u64) as u8; + // `d1 ∨ d2`; for 0/1 bytes this is exactly `d1 + d2 − d1·d2`, the + // degree-2 form the chip constrains. + let nb = d1 | d2; + + // double + let a_dbl = acc.clone(); + let (dx, dy, dlam) = ec_double(&a_dbl, &p_big); + acc = (dx.clone(), dy.clone()); + steps.push(joint_row( + &to_affine(&a_dbl), + &zero_pt, + 0, + round as u8, + nb, + &to_affine(&acc), + dlam.to_biguint().expect("reduced"), + JointSel::Double, + d1, + d2, + &p_big, + &r_big, + &r_ext, + &pp, + )); + + // conditional add of the selected addend; `nb = 0` on the add row, so + // its successor round is `round − 1` (an add is never followed by an add). + let (addend_i, addend_pt, sel) = match (d1, d2) { + (0, 0) => continue, + (1, 0) => (p1_i.clone(), p1.clone(), JointSel::AddP1), + (0, 1) => (p2_i.clone(), p2.clone(), JointSel::AddP2), + _ => ((x12.clone(), y12.clone()), p12.clone(), JointSel::AddP12), + }; + // acc = ±addend would be a discrete-log collision (blinding); no witness. + if acc.0 == addend_i.0 { + return Err(Lincomb2Error::ResultInfinity); + } + let a_add = acc.clone(); + let (ax, ay, alam) = ec_add(&a_add, &addend_i, &p_big); + acc = (ax, ay); + steps.push(joint_row( + &to_affine(&a_add), + &addend_pt, + 1, + round as u8, + 0, + &to_affine(&acc), + alam.to_biguint().expect("reduced"), + sel, + d1, + d2, + &p_big, + &r_big, + &r_ext, + &pp, + )); + } + + // --- blind = 2^len·T₀ --- + let mut tpow = t0_i.clone(); + for _ in 0..len { + let (x, y, _) = ec_double(&tpow, &p_big); + tpow = (x, y); + } + // acc == Q + 2^len·T₀; correction row adds −2^len·T₀ to recover Q. + let neg_tpow = (tpow.0.clone(), red(&(-&tpow.1), &p_big)); + if acc.0 == neg_tpow.0 { + // acc = ±(−tpow): Q = ∞ (or Q = −2^{len+1}T₀, a dlog event) — degenerate. + return Err(Lincomb2Error::ResultInfinity); + } + let a_corr = acc.clone(); + let (qx, qy, clam) = ec_add(&a_corr, &neg_tpow, &p_big); + let q = (qx.clone(), qy.clone()); + steps.push(joint_row( + &to_affine(&a_corr), + &to_affine(&neg_tpow), + 1, + 0, + 0, + &to_affine(&q), + clam.to_biguint().expect("reduced"), + JointSel::Correction, + 0, + 0, + &p_big, + &r_big, + &r_ext, + &pp, + )); + + let q_aff = to_affine(&q); + let tpow_aff = to_affine(&tpow); + + Ok(Lincomb2Witness { + x_p1: to_le_32(&p1.x), + y_p1: to_le_32(&p1.y), + x_p2: to_le_32(&p2.x), + y_p2: to_le_32(&p2.y), + mem_p2: membership_witness(&p2.x, &p2.y, &pp), + y_p2_sub_p: sub_witness(&p2.y, &p()), + x_p12: to_le_32(&p12.x), + y_p12: to_le_32(&p12.y), + u1: *u1_le, + u2: *u2_le, + u1_sub_n: sub_witness(&u1, &n()), + u2_sub_n: sub_witness(&u2, &n()), + len: len as u16, + x_q: to_le_32(&q_aff.x), + y_q: to_le_32(&q_aff.y), + x_q_sub_p: sub_witness(&q_aff.x, &p()), + y_q_sub_p: sub_witness(&q_aff.y, &p()), + x_t0: T0_X_LE, + y_t0: T0_Y_LE, + x_t0_pow: to_le_32(&tpow_aff.x), + y_t0_pow: to_le_32(&tpow_aff.y), + steps, + }) +} + +// ========================================================================= +// Non-degeneracy witness for the joint chain +// ========================================================================= +// +// `D_INV·(xB − xA) ≡ 1 (mod p)` is the ECDAS2 relation that makes an addition +// provably a genuine chord. It is not part of the data `lincomb2_witness` +// returns — the schedule above never needs the inverse, because it *refuses* +// every input whose chain would add a point to itself (`ResultInfinity`). The +// chip needs it anyway, since a malicious prover's row never passes through this +// generator. +// +// It lives here rather than in the prover so that all of this limb arithmetic +// has exactly one home. A second copy of `ext64`/`conv`/`limb_carries` in a chip +// would be the classic silent divergence: one side gets edited, the other does +// not, and nothing notices until a proof is wrong. + +/// The `D_INV·(xB − xA) ≡ 1 (mod p)` columns of one joint-chain row. +#[derive(Debug, Clone)] +pub struct DinvWitness { + /// `(xB − xA)^{-1} mod p`, little-endian. + pub d_inv: [u8; 32], + /// Shifted quotient of the relation, `r + numerator/p` with `r = 3p`. + pub q3: [u8; 33], + /// The 64 limb carries. + pub c3: [i64; 64], +} + +impl DinvWitness { + /// The shape a row that consumes no addend carries. + /// + /// The chip gates the relation by `S1 + S2 + S3 + S_CORR`, so on a doubling + /// only the `μ·R·P − q3·P` term survives — and it closes at zero carries + /// exactly when `q3 = r = 3p`. (An all-zero padding row closes the same term + /// at `q3 = 0`, because `μ = 0` kills `R·P` too.) + pub fn gated_off() -> Self { + Self { + d_inv: [0; 32], + q3: R_BYTES, + c3: [0; 64], + } + } +} + +/// Builds the non-degeneracy columns for one joint-chain row. +/// +/// Returns [`DinvWitness::gated_off`] for a doubling (no addend to check) and +/// also for a *degenerate* add, where `xB ≡ xA (mod p)` and no inverse exists: +/// no assignment satisfies the relation there, so the right behaviour is to let +/// the proof fail rather than to panic on prover-supplied data. The honest +/// schedule never produces such a row. +/// +/// Both `xB` and `xA` are reduced mod `p` before the difference is taken, so a +/// non-canonical *encoding* of an equal field element is treated as the +/// degeneracy it is. +pub fn dinv_witness(step: &JointStep) -> DinvWitness { + if step.sel == JointSel::Double { + return DinvWitness::gated_off(); + } + + let s = &step.step; + let p_big = p(); + let xa = BigUint::from_bytes_le(&s.x_a); + let xb = BigUint::from_bytes_le(&s.x_g); + let delta = ((&xb % &p_big) + &p_big - (&xa % &p_big)) % &p_big; + if delta.is_zero() { + return DinvWitness::gated_off(); + } + let d_inv = delta.modpow(&(&p_big - 2u32), &p_big); + + // numerator = d_inv·(xB − xA) − 1, over the RAW limb values: the identity the + // chip proves is limb-wise, and raw ≡ canonical (mod p) makes it the same + // statement either way. + let p_int = BigInt::from(p_big); + let numerator = + BigInt::from(d_inv.clone()) * (BigInt::from(xb) - BigInt::from(xa)) - BigInt::from(1u32); + let r_int = BigInt::from(BigUint::from_bytes_le(&R_BYTES)); + let q3 = shifted_quotient("d_inv", &numerator, &p_int, &r_int); + let q3 = to_le_33("d_inv", &q3); + + let d_inv = to_le_32(&d_inv); + let (d_e, xb_e, xa_e) = (ext64(&d_inv), ext64(&s.x_g), ext64(&s.x_a)); + let (q3_e, r_e, p_e) = (ext64(&q3), ext64(&R_BYTES), ext64(&P_BYTES)); + let mut terms = [0i128; 64]; + for (i, slot) in terms.iter_mut().enumerate() { + let mut t = 0i128; + for j in 0..=i { + t += d_e[j] * (xb_e[i - j] - xa_e[i - j]); + } + if i == 0 { + t -= 1; + } + *slot = t + conv(&r_e, &p_e, i) - conv(&q3_e, &p_e, i); + } + + DinvWitness { + d_inv, + q3, + c3: limb_carries("d_inv", &terms), + } +} diff --git a/crypto/ethrex-crypto/src/lib.rs b/crypto/ethrex-crypto/src/lib.rs index 980154e0f..bba7dd938 100644 --- a/crypto/ethrex-crypto/src/lib.rs +++ b/crypto/ethrex-crypto/src/lib.rs @@ -8,10 +8,15 @@ //! Accelerated today: //! - `keccak256`: a sponge over the `keccak_permute` precompile (riscv64; on //! host it falls back to software keccak for tests). -//! - `secp256k1_ecrecover`: the ECDSA recovery's 2-term linear combination is -//! evaluated through the ECSM `ecsm_mul` precompile (riscv64), reconstructing -//! the full point from x-only queries; on host / degenerate inputs it falls -//! back to the pure-Rust `ProjectivePoint::lincomb`. +//! - `secp256k1_ecrecover`: the ECDSA recovery's 2-term linear combination +//! `u1·G + u2·R` is evaluated by a single `ecsm_lincomb2` ecall (riscv64), +//! which returns the full affine point; on host, and whenever the accelerator +//! reports a non-zero status, it falls back to the pure-Rust +//! `ProjectivePoint::lincomb`. +//! +//! The `(r, v)` → `R` decompression stays in the guest and is **not** delegated: +//! the guest is the parity authority (proven CPU execution), and the +//! accelerator's obligations are curve membership and canonicalization only. //! //! Every other `Crypto` method inherits the trait default (vetted pure-Rust //! crates: `ark-bn254`, `bls12_381`, `p256`, `sha2`, `ripemd`, …). @@ -25,8 +30,8 @@ use k256::elliptic_curve::sec1::ToEncodedPoint; use k256::elliptic_curve::PrimeField; use k256::{AffinePoint, FieldBytes, ProjectivePoint, Scalar, U256}; -// Used only by the x-only point reconstruction (riscv accelerated path + the -// host unit tests); unused on a non-test host build. +// Used only by the `ecsm_lincomb2` ABI marshalling (riscv accelerated path + the +// host unit tests that cover it); unused on a non-test host build. #[cfg(any(target_arch = "riscv64", test))] use k256::elliptic_curve::sec1::FromEncodedPoint; #[cfg(any(target_arch = "riscv64", test))] @@ -71,9 +76,10 @@ impl Crypto for LambdaVmEcsmCrypto { /// /// Mirrors the pure-Rust recovery in the `Crypto` trait default /// (`pk = r⁻¹·(s·R − z·G)`), but evaluates the 2-term linear combination -/// `lincomb(G, u1, R, u2)` through the ECSM accelerator via [`ecsm_lincomb2`], -/// falling back to the software `ProjectivePoint::lincomb` whenever the -/// accelerated path declines (degenerate scalars/points, or non-riscv builds). +/// `lincomb(G, u1, R, u2)` through the lincomb2 accelerator via +/// [`ecsm_lincomb2`], falling back to the software `ProjectivePoint::lincomb` +/// whenever the accelerated path declines (a non-zero accelerator status, or a +/// non-riscv build). /// We compute the recovery directly rather than calling k256's /// `recover_from_prehash`, which internally runs a *second* lincomb to /// re-verify the key — doubling the ECSM ecalls for no gain here. @@ -130,10 +136,29 @@ fn ecsm_ecrecover(sig: &[u8; 64], recid: u8, msg: &[u8; 32]) -> Result<[u8; 64], /// ECSM-accelerated 2-term linear combination `k1·P1 + k2·P2`. /// -/// On riscv64 this reconstructs the full affine result from four x-only ECSM -/// queries (see [`lincomb2_with_oracle`]); on other targets, and whenever a -/// guard trips (degenerate input or oracle inconsistency), it returns `None` -/// so the caller uses the pure-Rust `ProjectivePoint::lincomb`. +/// On riscv64 this is **one** `ecsm_lincomb2` ecall: the accelerator evaluates +/// the joint Shamir/Straus chain and writes the full affine `Q`. On other +/// targets it returns `None` so the caller uses the pure-Rust +/// `ProjectivePoint::lincomb`. +/// +/// # The status contract is the only guard +/// +/// The guest performs no degeneracy checks of its own beyond marshalling: every +/// case that the accelerator cannot prove — `k = 0`, `k >= N`, an off-curve or +/// non-canonical `P2`, `P1 != G`, `P1 = ±P2`, `Q = ∞`, and the chain's own +/// interior collisions — comes back as a non-zero status with `q` untouched, and +/// a non-zero status means `None` means the software fallback. Falling back is +/// always sound: the fallback is proven guest execution, so a status the +/// accelerator gets *wrong* costs cycles and nothing else. +/// +/// The one guest-side guard that remains is structural rather than a policy +/// choice: an identity point has no affine `(x, y)` to marshal, so +/// [`lincomb2_operands`] returns `None` before any ecall. +/// +/// `P1` must be the generator — the chip has no membership witness for an +/// arbitrary first point. We do not check that here: the accelerator reports +/// status `7` for any other `P1`, which is exactly the same fallback path, and +/// the only caller passes `ProjectivePoint::GENERATOR`. #[cfg(target_arch = "riscv64")] fn ecsm_lincomb2( p1: &ProjectivePoint, @@ -141,7 +166,15 @@ fn ecsm_lincomb2( p2: &ProjectivePoint, k2: &Scalar, ) -> Option { - lincomb2_with_oracle(p1, k1, p2, k2, ecsm_oracle) + let (p1_op, p2_op, u_op) = lincomb2_operands(p1, k1, p2, k2)?; + // Four distinct live locals: pairwise disjoint by construction, which the + // executor requires (an overlap is a hard `ExecutionError`, not a status). + let mut q = Operand([0u8; 64]); + let status = lambda_vm_syscalls::syscalls::ecsm_lincomb2(&mut q.0, &p1_op.0, &p2_op.0, &u_op.0); + if status != lambda_vm_syscalls::syscalls::ECSM_LINCOMB2_OK { + return None; + } + point_from_le_q(&q.0) } #[cfg(not(target_arch = "riscv64"))] @@ -154,131 +187,71 @@ fn ecsm_lincomb2( None } -/// x-only scalar-mul oracle backed by the ECSM precompile: computes `x(k·P)` -/// for the curve point P whose x-coordinate is passed in. `x` must be the -/// x-coordinate of a curve point and `k` in `(0, N)` (N = curve order) — -/// guaranteed by the guards in [`lincomb2_with_oracle`]. Values cross the ABI -/// as 32-byte little-endian; `x_le` and `k_le` are distinct stack arrays so -/// the executor's `|addr_x_le − addr_k_le| ≥ 32` assumption holds by -/// construction. -#[cfg(target_arch = "riscv64")] -fn ecsm_oracle(x: &FieldElement, k: &Scalar) -> Option { - let x_be = x.to_bytes(); - let k_be = k.to_bytes(); - let mut x_le = [0u8; 32]; - let mut k_le = [0u8; 32]; +/// One 64-byte `ecsm_lincomb2` operand: two 32-byte little-endian values. +/// +/// The `repr(align(8))` is load-bearing, not cosmetic. The executor reads and +/// writes each operand as eight *aligned* doubleword MEMW accesses and rejects a +/// misaligned address as a hard `ExecutionError` — it is a guest bug, not an +/// attacker input, so it aborts the run rather than returning a status. A bare +/// `[u8; 64]` is only 1-byte aligned and would abort on a bad stack layout. +#[cfg(any(target_arch = "riscv64", test))] +#[repr(align(8))] +struct Operand([u8; 64]); + +/// Packs two big-endian 32-byte values into one operand, each reversed into the +/// little-endian order the ABI uses. +#[cfg(any(target_arch = "riscv64", test))] +fn operand(first_be: &FieldBytes, second_be: &FieldBytes) -> Operand { + let mut out = Operand([0u8; 64]); for i in 0..32 { - x_le[i] = x_be[31 - i]; - k_le[i] = k_be[31 - i]; + out.0[i] = first_be[31 - i]; + out.0[32 + i] = second_be[31 - i]; } - let mut xr_le = [0u8; 32]; - lambda_vm_syscalls::syscalls::ecsm_mul(&mut xr_le, &x_le, &k_le); - xr_le.reverse(); - Option::from(FieldElement::from_bytes(&xr_le.into())) + out } -/// Computes `k1·P1 + k2·P2` from four x-only oracle queries, or `None` if any -/// degenerate-configuration guard trips. +/// The three input operands `(xP1‖yP1, xP2‖yP2, u1‖u2)` for one +/// `ecsm_lincomb2` ecall, or `None` if either point is the identity — which has +/// no affine `(x, y)` encoding to marshal, and is the one degenerate case the +/// status word cannot report because the call cannot be formed at all. /// -/// The lambda-vm ECSM precompile returns only `x(k·P)`. For `A = k1·P1` with -/// `P1 = (xp, yp)` fully known, query `xa = x(k1·P1)` and `xc = x((k1+1)·P1)`. -/// The chord-addition law gives `λ² = xc + xa + xp =: t` and `ya = yp + λ·dx` -/// with `dx = xa − xp`; substituting into `ya² = xa³ + b` makes λ *linear*: -/// `λ = (xa³ − xp³ − t·dx²) / (2·yp·dx)`. The wrong sign `−ya` would force -/// `x((k1−1)·P1) = xc`, i.e. `k1 ≡ 0` or `2·k1 ≡ 0 (mod n)`, excluded by the -/// scalar guards. x-only queries are parity-invariant (`x(k·P) = x(k·(−P))`), -/// so the precompile's canonical-y lift never matters. Same for `B = k2·P2`, -/// then `Q = A + B` is one affine addition. All three inversions are batched. -/// -/// Generic over the oracle so unit tests can substitute a software stand-in. +/// Split out from [`ecsm_lincomb2`] so the ABI is reachable from host tests: the +/// ecall itself only exists on riscv64, but the byte-order conversion — the part +/// most likely to carry a bug — is ordinary code. #[cfg(any(target_arch = "riscv64", test))] -fn lincomb2_with_oracle( +fn lincomb2_operands( p1: &ProjectivePoint, k1: &Scalar, p2: &ProjectivePoint, k2: &Scalar, - oracle: O, -) -> Option -where - O: Fn(&FieldElement, &Scalar) -> Option, -{ - let a1 = p1.to_affine(); - let a2 = p2.to_affine(); - if bool::from(a1.is_identity()) || bool::from(a2.is_identity()) { - return None; - } - if scalar_near_edge(k1) || scalar_near_edge(k2) { - return None; - } - - let (x1, y1) = affine_xy(&a1)?; - let (x2, y2) = affine_xy(&a2)?; - - let xa = oracle(&x1, k1)?; - let xc1 = oracle(&x1, &(*k1 + Scalar::ONE))?; - let xb = oracle(&x2, k2)?; - let xc2 = oracle(&x2, &(*k2 + Scalar::ONE))?; - - let dx1 = (xa - x1).normalize(); - let dx2 = (xb - x2).normalize(); - let dxq = (xb - xa).normalize(); - if bool::from(dx1.is_zero()) || bool::from(dx2.is_zero()) || bool::from(dxq.is_zero()) { - return None; - } - - // One shared inversion for the two λ denominators and the final chord. - let den1 = y1.double() * dx1; - let den2 = y2.double() * dx2; - let inv = Option::::from((den1 * den2 * dxq).invert())?; - let inv_den1 = inv * den2 * dxq; - let inv_den2 = inv * den1 * dxq; - let inv_dxq = inv * den1 * den2; - - let ya = solve_y(&x1, &y1, &xa, &xc1, &dx1, &inv_den1)?; - let yb = solve_y(&x2, &y2, &xb, &xc2, &dx2, &inv_den2)?; - - // Q = A + B, with A ≠ ±B ensured by dxq ≠ 0. - let lq = (yb - ya) * inv_dxq; - let xq = (lq.square() - xa - xb).normalize(); - let yq = (lq * (xa - xq) - ya).normalize(); - - // `point_from_xy` checks the result is on the curve as a cheap backstop: - // it rejects gross off-curve garbage and falls back to software, but - // correctness rests on the algebra above — an on-curve-but-wrong point - // would still pass this check. - point_from_xy(&xq, &yq) +) -> Option<(Operand, Operand, Operand)> { + let (x1, y1) = affine_xy(&p1.to_affine())?; + let (x2, y2) = affine_xy(&p2.to_affine())?; + Some(( + operand(&x1.to_bytes(), &y1.to_bytes()), + operand(&x2.to_bytes(), &y2.to_bytes()), + operand(&k1.to_bytes(), &k2.to_bytes()), + )) } -/// Recovers `y(k·P)` from `xa = x(k·P)` and `xc = x((k+1)·P)`. -/// Returns `None` if `xc` is inconsistent with the computed `lambda` -/// (oracle misbehavior); degeneracy guards are in [`lincomb2_with_oracle`]. +/// Rebuilds `Q` from the syscall's 64-byte result operand (`xQ‖yQ`, each 32-byte +/// little-endian). +/// +/// `point_from_xy` re-checks the point is on the curve. That is a cheap backstop +/// against a marshalling bug on our side, not a soundness check on the +/// accelerator: the chip's own constraints are what bind `Q`, and an +/// on-curve-but-wrong point would pass this. #[cfg(any(target_arch = "riscv64", test))] -fn solve_y( - xp: &FieldElement, - yp: &FieldElement, - xa: &FieldElement, - xc: &FieldElement, - dx: &FieldElement, - inv_den: &FieldElement, -) -> Option { - let t = *xc + xa + xp; - let xa3 = xa.square() * xa; - let xp3 = xp.square() * xp; - let lambda = (xa3 - xp3 - t * dx.square()) * inv_den; - if lambda.square().normalize() != t.normalize() { - return None; +fn point_from_le_q(q: &[u8; 64]) -> Option { + let mut x_be = [0u8; 32]; + let mut y_be = [0u8; 32]; + for i in 0..32 { + x_be[i] = q[31 - i]; + y_be[i] = q[63 - i]; } - Some((*yp + lambda * dx).normalize()) -} - -/// `k ∈ {0, 1, n−1}`: fast early-exit before oracle calls. -/// k=0: invalid ecall scalar. k=1: dx=0. k=n-1: k+1 wraps to 0 mod n. -#[cfg(any(target_arch = "riscv64", test))] -fn scalar_near_edge(k: &Scalar) -> bool { - use k256::elliptic_curve::subtle::ConstantTimeEq; - bool::from(k.is_zero()) - || bool::from(k.ct_eq(&Scalar::ONE)) - || bool::from(k.ct_eq(&(-Scalar::ONE))) + let x = Option::::from(FieldElement::from_bytes(&x_be.into()))?; + let y = Option::::from(FieldElement::from_bytes(&y_be.into()))?; + point_from_xy(&x, &y) } /// Affine `(x, y)` of a non-identity point as field elements, via its SEC1 diff --git a/crypto/ethrex-crypto/src/tests/ecsm_tests.rs b/crypto/ethrex-crypto/src/tests/ecsm_tests.rs index ace1dc63a..c485ef49a 100644 --- a/crypto/ethrex-crypto/src/tests/ecsm_tests.rs +++ b/crypto/ethrex-crypto/src/tests/ecsm_tests.rs @@ -1,177 +1,251 @@ -//! Tests for the x-only ECSM linear-combination reconstruction -//! (`lincomb2_with_oracle`) against the software `ProjectivePoint::lincomb`, -//! plus the degenerate-configuration fallback guards. +//! Tests for the `ecsm_lincomb2` ABI marshalling. +//! +//! # What these cover, and what they cannot +//! +//! The accelerated path is now three steps: pack the operands, make one ecall, +//! parse the result. The ecall exists only on riscv64, so **step 2 is not +//! reachable from a host test** — `ecsm_lincomb2` returns `None` on host before +//! it is ever issued. +//! +//! Steps 1 and 3 are ordinary code, and they are where a bug would actually +//! live: a byte-order slip in either direction silently produces a wrong point. +//! So these tests pin the ABI from both ends, and [`soft_lincomb2`] closes the +//! loop by standing in for the ecall — decoding the operands exactly as the +//! executor does, computing `Q` in pure Rust, and re-encoding it in the layout +//! the chip writes. Chained between the two real functions that is a genuine +//! differential against `ProjectivePoint::lincomb` over the whole ABI. +//! +//! What remains uncovered here is the ecall and the chip behind it. That is +//! carried by a proven guest — the ethrex block tests in the prover crate run +//! real ecrecovers through this path and verify — and by the executor's own +//! `lincomb2` suite for the status contract. See the phase-G report. use crate::*; -/// secp256k1 curve constant `b = 7`. -fn curve_b() -> FieldElement { - let mut bytes = [0u8; 32]; - bytes[31] = 7; - FieldElement::from_bytes(&bytes.into()).unwrap() +/// secp256k1 `Gx‖Gy` as the ABI carries it: two 32-byte little-endian values. +/// Written out independently of anything in this crate (the constant an +/// ecrecover caller's `P1` operand must equal), so it cross-checks +/// [`lincomb2_operands`]'s byte order against a source outside k256. +const GENERATOR_LE: [u8; 64] = { + let mut out = [0u8; 64]; + // Gx, big-endian 79BE667E…16F81798, reversed below. + let gx_be: [u8; 32] = [ + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, + 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, + 0x17, 0x98, + ]; + // Gy, big-endian 483ADA77…FB10D4B8. + let gy_be: [u8; 32] = [ + 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, + 0xA8, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, + 0xD4, 0xB8, + ]; + let mut i = 0; + while i < 32 { + out[i] = gx_be[31 - i]; + out[32 + i] = gy_be[31 - i]; + i += 1; + } + out +}; + +fn g_times(n: u64) -> ProjectivePoint { + ProjectivePoint::GENERATOR * Scalar::from(n) } -/// Software stand-in for the ECSM precompile: lift `x` to a curve point and -/// return `x(k·P)` (parity-invariant, like the real ecall). -fn soft_oracle(x: &FieldElement, k: &Scalar) -> Option { - let xn = x.normalize(); - let y2 = (xn.square() * xn + curve_b()).normalize(); - let y = Option::::from(y2.sqrt())?; - let p = point_from_xy(&xn, &y.normalize())?; - let prod = (p * k).to_affine(); - Some(affine_xy(&prod)?.0) +/// Decodes one 32-byte little-endian half of an operand into big-endian bytes. +fn le_half(op: &Operand, half: usize) -> [u8; 32] { + let mut be = [0u8; 32]; + for (i, b) in be.iter_mut().enumerate() { + *b = op.0[half * 32 + 31 - i]; + } + be } -fn g_times(n: u64) -> ProjectivePoint { - ProjectivePoint::GENERATOR * Scalar::from(n) +/// Software stand-in for the `ecsm_lincomb2` ecall. +/// +/// Decodes the three operands the way the executor does, computes +/// `Q = u1·P1 + u2·P2` with the pure-Rust lincomb, and writes `xQ‖yQ` back in +/// the chip's little-endian layout. Returns `None` where the accelerator would +/// return a non-zero status. +fn soft_lincomb2(p1: &Operand, p2: &Operand, u: &Operand) -> Option { + let point = |op: &Operand| -> Option { + let x = Option::::from(FieldElement::from_bytes(&le_half(op, 0).into()))?; + let y = Option::::from(FieldElement::from_bytes(&le_half(op, 1).into()))?; + point_from_xy(&x, &y) + }; + let scalar = |op: &Operand, half: usize| -> Option { + Option::from(Scalar::from_repr(le_half(op, half).into())) + }; + + let q = ProjectivePoint::lincomb(&point(p1)?, &scalar(u, 0)?, &point(p2)?, &scalar(u, 1)?); + let affine = q.to_affine(); + if bool::from(affine.is_identity()) { + return None; // the accelerator reports status 6 (ResultInfinity) + } + let (x, y) = affine_xy(&affine)?; + Some(operand(&x.to_bytes(), &y.to_bytes())) } +// ── The ABI, both directions ──────────────────────────────────────────────── + +/// The full round trip: pack real operands, run the software stand-in for the +/// ecall, parse the result — and land on exactly what `ProjectivePoint::lincomb` +/// computes. A byte-order error anywhere in the ABI breaks this. #[test] -fn matches_software_lincomb_on_fixed_inputs() { +fn abi_round_trip_matches_software_lincomb() { let cases = [ (g_times(3), 123_456_789u64, g_times(7), 987_654_321u64), (g_times(11), 2u64.pow(20) + 5, g_times(2), 42u64), (ProjectivePoint::GENERATOR, 7u64, g_times(5), 9u64), + // The ecrecover shape: generator first, R second. + ( + ProjectivePoint::GENERATOR, + 0xdead_beefu64, + g_times(0x1234), + 0x0bad_f00du64, + ), ]; for (p1, k1, p2, k2) in cases { let (k1, k2) = (Scalar::from(k1), Scalar::from(k2)); let expected = ProjectivePoint::lincomb(&p1, &k1, &p2, &k2); - let got = lincomb2_with_oracle(&p1, &k1, &p2, &k2, soft_oracle) - .expect("non-degenerate inputs must reconstruct"); + + let (p1_op, p2_op, u_op) = + lincomb2_operands(&p1, &k1, &p2, &k2).expect("non-identity points must marshal"); + let q = soft_lincomb2(&p1_op, &p2_op, &u_op).expect("non-degenerate case"); + let got = point_from_le_q(&q.0).expect("the result must parse back"); + assert_eq!(got.to_affine(), expected.to_affine()); } } +/// A base point with odd `y` marshals correctly — the parity byte moves from +/// index 31 (big-endian) to index 0 (little-endian), so a half-reversed +/// conversion would survive the even-`y` cases above and fail here. #[test] -fn matches_software_lincomb_on_recovery_shape() { - // u1·G + u2·R, generator first, like ECDSA recovery. - let g = ProjectivePoint::GENERATOR; - let r = g_times(0x1234); - let u1 = Scalar::from(0xdead_beefu64); - let u2 = Scalar::from(0x0bad_f00du64); - let expected = ProjectivePoint::lincomb(&g, &u1, &r, &u2); - let got = lincomb2_with_oracle(&g, &u1, &r, &u2, soft_oracle) - .expect("non-degenerate inputs must reconstruct"); - assert_eq!(got.to_affine(), expected.to_affine()); -} +fn odd_y_base_point_round_trips() { + let p1 = (2u64..200) + .find_map(|n| { + let p = g_times(n); + let (_, y) = affine_xy(&p.to_affine())?; + (y.normalize().to_bytes()[31] & 1 == 1).then_some(p) + }) + .expect("one of the first 200 multiples of G has odd y"); -#[test] -fn edge_scalars_fall_back() { - let p1 = g_times(3); - let p2 = g_times(5); - let ok = Scalar::from(12345u64); - for bad in [Scalar::ZERO, Scalar::ONE, -Scalar::ONE] { - assert!(lincomb2_with_oracle(&p1, &bad, &p2, &ok, soft_oracle).is_none()); - assert!(lincomb2_with_oracle(&p1, &ok, &p2, &bad, soft_oracle).is_none()); - } + let (k1, k2) = (Scalar::from(54321u64), Scalar::from(11111u64)); + let p2 = g_times(13); + let expected = ProjectivePoint::lincomb(&p1, &k1, &p2, &k2); + + let (p1_op, p2_op, u_op) = lincomb2_operands(&p1, &k1, &p2, &k2).unwrap(); + let q = soft_lincomb2(&p1_op, &p2_op, &u_op).unwrap(); + assert_eq!( + point_from_le_q(&q.0).unwrap().to_affine(), + expected.to_affine() + ); } +/// `P1 = G` must marshal to the exact 64 bytes the chip pins as the generator. +/// If this drifts, every ecrecover silently takes the software fallback with +/// status 7 (`P1 != G`) and the accelerator does nothing. #[test] -fn identity_points_fall_back() { - let p = g_times(3); - let k = Scalar::from(7u64); - let id = ProjectivePoint::IDENTITY; - assert!(lincomb2_with_oracle(&id, &k, &p, &k, soft_oracle).is_none()); - assert!(lincomb2_with_oracle(&p, &k, &id, &k, soft_oracle).is_none()); +fn generator_operand_matches_the_pinned_constant() { + let (k1, k2) = (Scalar::from(5u64), Scalar::from(9u64)); + let (p1_op, _, _) = + lincomb2_operands(&ProjectivePoint::GENERATOR, &k1, &g_times(3), &k2).unwrap(); + assert_eq!(p1_op.0, GENERATOR_LE, "P1 operand must be G in ABI order"); } +/// The scalar operand is `u1‖u2`, in that order, each little-endian. Swapping +/// the halves would compute `u2·G + u1·R` and still land on the curve, so pin it. #[test] -fn cancelling_and_doubling_terms_fall_back() { - let p = g_times(3); - let k = Scalar::from(7u64); - // A = B (doubling chord) and A = −B (Q = O): both share x(A) = x(B). - assert!(lincomb2_with_oracle(&p, &k, &p, &k, soft_oracle).is_none()); - assert!(lincomb2_with_oracle(&p, &k, &(-p), &k, soft_oracle).is_none()); +fn scalar_operand_packs_u1_then_u2() { + let k1 = Scalar::from(0x0102_0304_0506_0708u64); + let k2 = Scalar::from(0x1112_1314_1516_1718u64); + let (_, _, u_op) = + lincomb2_operands(&ProjectivePoint::GENERATOR, &k1, &g_times(3), &k2).unwrap(); + + assert_eq!( + &le_half(&u_op, 0)[..], + &k1.to_bytes()[..], + "first half is u1" + ); + assert_eq!( + &le_half(&u_op, 1)[..], + &k2.to_bytes()[..], + "second half is u2" + ); + // Little-endian: the least-significant byte leads. + assert_eq!(u_op.0[0], 0x08); + assert_eq!(u_op.0[32], 0x18); } +/// The executor rejects a misaligned operand as a hard `ExecutionError`, not a +/// status word — so a 1-byte-aligned buffer would abort the proof rather than +/// fall back. `Operand` carries `repr(align(8))` to prevent that; pin it here, +/// since nothing else in the crate would notice if it were removed. #[test] -fn k_half_n_minus_1_reconstructs_correctly() { - // k = (n-1)/2 satisfies k·P = -(k+1)·P for any P, so the oracle returns - // the same x-coordinate for both the k and k+1 calls (xa = xc). The - // solve_y algebra still holds: lambda² = 2·xa + xp = t, so the check - // passes and the correct ya is recovered. - let two_inv = Scalar::from(2u64) - .invert_vartime() - .expect("2 is invertible mod n"); - let k_half = -Scalar::ONE * two_inv; // (n-1)/2 - - let p1 = g_times(5); - let p2 = g_times(11); - let k2 = Scalar::from(99999u64); - - let expected = ProjectivePoint::lincomb(&p1, &k_half, &p2, &k2); - let got = lincomb2_with_oracle(&p1, &k_half, &p2, &k2, soft_oracle) - .expect("k=(n-1)/2 is not near-edge and must reconstruct correctly"); - assert_eq!(got.to_affine(), expected.to_affine()); +fn operands_are_eight_byte_aligned() { + assert_eq!(core::mem::align_of::(), 8); + let (p1_op, p2_op, u_op) = lincomb2_operands( + &ProjectivePoint::GENERATOR, + &Scalar::from(7u64), + &g_times(3), + &Scalar::from(9u64), + ) + .unwrap(); + for op in [&p1_op, &p2_op, &u_op] { + assert_eq!( + op.0.as_ptr() as usize % 8, + 0, + "operand bytes must start 8-byte aligned" + ); + } } +// ── Guards ───────────────────────────────────────────────────────────────── + +/// An identity input has no affine `(x, y)` to marshal, so the call is never +/// formed. This is the only degeneracy the guest still screens: every other one +/// comes back as a status word. #[test] -fn cross_point_cancellation_falls_back() { - // Construct k1, k2, P1 ≠ ±P2 such that k1·P1 = -(k2·P2), so - // k1·P1 + k2·P2 = O. The shared x-coordinate makes dxq = 0 → None. - // P1 = 3G, P2 = 7G: k1·3G = -k2·7G → k1 = -k2·7·3^{-1} mod n. - let p1 = g_times(3); - let p2 = g_times(7); - let k2 = Scalar::from(12345u64); - let three_inv = Scalar::from(3u64) - .invert_vartime() - .expect("3 is invertible mod n"); - let k1 = -(k2 * Scalar::from(7u64) * three_inv); - assert!( - lincomb2_with_oracle(&p1, &k1, &p2, &k2, soft_oracle).is_none(), - "cross-point cancellation (P1 ≠ ±P2, result = O) must fall back" - ); +fn identity_points_do_not_marshal() { + let p = g_times(3); + let k = Scalar::from(7u64); + let id = ProjectivePoint::IDENTITY; + assert!(lincomb2_operands(&id, &k, &p, &k).is_none()); + assert!(lincomb2_operands(&p, &k, &id, &k).is_none()); } +/// The result parser rejects a point that is not on the curve — the backstop +/// against a marshalling bug on our side. #[test] -fn solve_y_rejects_inconsistent_oracle_xc() { - // Directly test that solve_y's lambda² == t check fires when xc is wrong. - // This is the oracle-misbehavior guard: it cannot easily be reached via - // lincomb2_with_oracle because the oracle is Fn (no mutable state to - // return xa correct and xc wrong in separate calls). - let (xp, yp) = affine_xy(&g_times(3).to_affine()).unwrap(); - let k = Scalar::from(12345u64); - - let xa = soft_oracle(&xp, &k).unwrap(); - let xc_correct = soft_oracle(&xp, &(k + Scalar::ONE)).unwrap(); - // xc from k+100 is inconsistent with xa from k — lambda²=t must reject it. - let xc_wrong = soft_oracle(&xp, &(k + Scalar::from(100u64))).unwrap(); - - let dx = (xa - xp).normalize(); - let inv_den = Option::::from((yp.double() * dx).invert()) - .expect("dx is nonzero for k=12345"); - - assert!( - solve_y(&xp, &yp, &xa, &xc_correct, &dx, &inv_den).is_some(), - "correct xc must pass the lambda² check" - ); +fn off_curve_result_is_rejected() { + let (x, y) = affine_xy(&g_times(3).to_affine()).unwrap(); + let mut q = operand(&x.to_bytes(), &y.to_bytes()); + assert!(point_from_le_q(&q.0).is_some(), "the real point must parse"); + q.0[32] ^= 1; // perturb yQ: (x, y+1) is not on the curve assert!( - solve_y(&xp, &yp, &xa, &xc_wrong, &dx, &inv_den).is_none(), - "inconsistent xc (oracle misbehavior) must be rejected by the lambda² check" + point_from_le_q(&q.0).is_none(), + "an off-curve result must be rejected" ); } +/// Degenerate configurations the accelerator reports as a status: `P1 = ±P2` +/// (status 5) and a cancelling combination (`Q = ∞`, status 6). The guest +/// marshals them happily — that is correct, the chip is the one that declines — +/// so this pins that the *stand-in* declines where the chip would, keeping the +/// round-trip test honest about what it is and is not exercising. #[test] -fn odd_y_base_point_reconstructs_correctly() { - // Validates the solve_y sign-selection argument: when P1 has odd y the - // reconstruction must still match ProjectivePoint::lincomb. - let (p1, _k_gen) = (2u64..200) - .find_map(|n| { - let p = g_times(n); - let (_, y) = affine_xy(&p.to_affine())?; - if y.normalize().to_bytes()[31] & 1 == 1 { - Some((p, n)) - } else { - None - } - }) - .expect("at least one of the first 200 multiples of G has odd y"); +fn cancelling_terms_are_declined_by_the_accelerator_not_the_guest() { + let p = g_times(3); + let k = Scalar::from(7u64); - let p2 = g_times(13); - let k1 = Scalar::from(54321u64); - let k2 = Scalar::from(11111u64); - let expected = ProjectivePoint::lincomb(&p1, &k1, &p2, &k2); - let got = lincomb2_with_oracle(&p1, &k1, &p2, &k2, soft_oracle) - .expect("odd-y base point is non-degenerate and must reconstruct correctly"); - assert_eq!(got.to_affine(), expected.to_affine()); + // P1 = P2: marshals fine; the chip answers SumDegenerate. + let (p1_op, p2_op, _) = lincomb2_operands(&p, &k, &p, &k).expect("marshals"); + assert_eq!(p1_op.0, p2_op.0); + + // k1·P + k2·(−P) = O with k1 = k2: the stand-in returns None, as the chip + // would with ResultInfinity. + let (p1_op, p2_op, u_op) = lincomb2_operands(&p, &k, &(-p), &k).expect("marshals"); + assert!(soft_lincomb2(&p1_op, &p2_op, &u_op).is_none()); } diff --git a/executor/Cargo.toml b/executor/Cargo.toml index 3f278e1c6..785cf1107 100644 --- a/executor/Cargo.toml +++ b/executor/Cargo.toml @@ -8,8 +8,14 @@ license.workspace = true thiserror = "1.0.68" rustc-demangle = "0.1" ecsm = { path = "../crypto/ecsm" } +# The lincomb2 syscall hands `ecsm` its curve points as `AffinePoint { x, y: BigUint }`, +# so the executor names the same big-integer type the ecsm crate already builds on. +num-bigint = "0.4.6" [dev-dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tiny-keccak = { version = "2.0", features = ["keccak"] } +# Third reference for the lincomb2 syscall tests: `ProjectivePoint::lincomb` is the very +# software fallback the guest takes when the syscall reports a non-zero status. +k256 = { version = "0.13", default-features = false, features = ["arithmetic"] } diff --git a/executor/programs/asm/test_ecsm_lincomb2.s b/executor/programs/asm/test_ecsm_lincomb2.s new file mode 100644 index 000000000..cd33910d1 --- /dev/null +++ b/executor/programs/asm/test_ecsm_lincomb2.s @@ -0,0 +1,99 @@ + .attribute 5, "rv64i2p1_m2p0_zmmul1p0" + .globl main +main: + # ECSM lincomb2 round trip: Q = 3·G + 5·(2G) = 13·G. + # + # Stack layout (384 bytes). Every operand is 64 bytes — two 32-byte + # little-endian values back to back — 8-byte aligned and pairwise disjoint, + # as the syscall's address guards require: + # sp+0 P1 = xG‖yG sp+64 P2 = x(2G)‖y(2G) + # sp+128 u1‖u2 sp+200 Q = xQ‖yQ (result) + # sp+192 status word (8 bytes, stored from a0 after the call) + # + # The frame is deliberately larger than the 264 bytes it uses: an operand's + # last byte (+63) must not cross a 4 GiB boundary, and STACK_TOP + # (0xFFFF_FFFF_FFFF_FFF0) sits right below one. 384 bytes keeps every + # operand clear of it. + addi sp, sp, -384 + + # P1 = G (xP1 at sp+0, yP1 at sp+32) + li t0, 0x59F2815B16F81798 + sd t0, 0(sp) + li t0, 0x029BFCDB2DCE28D9 + sd t0, 8(sp) + li t0, 0x55A06295CE870B07 + sd t0, 16(sp) + li t0, 0x79BE667EF9DCBBAC + sd t0, 24(sp) + li t0, 0x9C47D08FFB10D4B8 + sd t0, 32(sp) + li t0, 0xFD17B448A6855419 + sd t0, 40(sp) + li t0, 0x5DA4FBFC0E1108A8 + sd t0, 48(sp) + li t0, 0x483ADA7726A3C465 + sd t0, 56(sp) + + # P2 = 2G (xP2 at sp+64, yP2 at sp+96) + li t0, 0xABAC09B95C709EE5 + sd t0, 64(sp) + li t0, 0x5C778E4B8CEF3CA7 + sd t0, 72(sp) + li t0, 0x3045406E95C07CD8 + sd t0, 80(sp) + li t0, 0xC6047F9441ED7D6D + sd t0, 88(sp) + li t0, 0x236431A950CFE52A + sd t0, 96(sp) + li t0, 0xF7F632653266D0E1 + sd t0, 104(sp) + li t0, 0xA3C58419466CEAEE + sd t0, 112(sp) + li t0, 0x1AE168FEA63DC339 + sd t0, 120(sp) + + # u1 = 3 at sp+128, u2 = 5 at sp+160 + li t0, 0x0000000000000003 + sd t0, 128(sp) + li t0, 0x0000000000000000 + sd t0, 136(sp) + li t0, 0x0000000000000000 + sd t0, 144(sp) + li t0, 0x0000000000000000 + sd t0, 152(sp) + li t0, 0x0000000000000005 + sd t0, 160(sp) + li t0, 0x0000000000000000 + sd t0, 168(sp) + li t0, 0x0000000000000000 + sd t0, 176(sp) + li t0, 0x0000000000000000 + sd t0, 184(sp) + + + # lincomb2 ecall: a0 = &Q, a1 = &P1, a2 = &P2, a3 = &u, a7 = -12. + addi a0, sp, 200 + addi a1, sp, 0 + addi a2, sp, 64 + addi a3, sp, 128 + li a7, -12 + ecall + + # a0 now holds the status word; stash it just below the result so the host + # test can commit status‖xQ‖yQ as one contiguous 72-byte block. + sd a0, 192(sp) + + # Commit syscall: a0 = fd(1), a1 = buf_addr, a2 = count, a7 = 64. + li a0, 1 + addi a1, sp, 192 + li a2, 72 + li a7, 64 + ecall + + # Restore stack and halt. + addi sp, sp, 384 + li a0, 0 + li a7, 93 + ecall +.Lfunc_end1: + .size main, .Lfunc_end1-main diff --git a/executor/programs/asm/test_ecsm_lincomb2_full.s b/executor/programs/asm/test_ecsm_lincomb2_full.s new file mode 100644 index 000000000..23247ef82 --- /dev/null +++ b/executor/programs/asm/test_ecsm_lincomb2_full.s @@ -0,0 +1,104 @@ + .attribute 5, "rv64i2p1_m2p0_zmmul1p0" + .globl main +main: + # WORST-CASE lincomb2 round trip. u1 = 2^255 and u2 = 2^255 − 1 are both in + # [1, N) and their bit patterns are COMPLEMENTARY, so every one of the 256 + # rounds carries a nonzero joint digit and therefore an add: + # + # 1 precompute + 256 doublings + 256 adds + 1 correction = 514 rows + # + # That is the true maximum over the valid input domain, and it is cheap for a + # submitter to construct deliberately — so it is what any capacity-shaped + # bound must be tested against. The ~471 seen over random scalars is only a + # sample maximum. Complementarity is what maximises, not popcount: all-ones + # scalars share every add and reach just 449. + # + # `test_ecsm_lincomb2.s` covers the tiny end of the range. + # + # Stack layout (384 bytes), same as the small program: + # sp+0 P1 = xG‖yG sp+64 P2 = x(2G)‖y(2G) + # sp+128 u1‖u2 sp+192 status sp+200 Q = xQ‖yQ + addi sp, sp, -384 + + # P1 = G (xP1 at sp+0, yP1 at sp+32) + li t0, 0x59F2815B16F81798 + sd t0, 0(sp) + li t0, 0x029BFCDB2DCE28D9 + sd t0, 8(sp) + li t0, 0x55A06295CE870B07 + sd t0, 16(sp) + li t0, 0x79BE667EF9DCBBAC + sd t0, 24(sp) + li t0, 0x9C47D08FFB10D4B8 + sd t0, 32(sp) + li t0, 0xFD17B448A6855419 + sd t0, 40(sp) + li t0, 0x5DA4FBFC0E1108A8 + sd t0, 48(sp) + li t0, 0x483ADA7726A3C465 + sd t0, 56(sp) + + # P2 = 2G (xP2 at sp+64, yP2 at sp+96) + li t0, 0xABAC09B95C709EE5 + sd t0, 64(sp) + li t0, 0x5C778E4B8CEF3CA7 + sd t0, 72(sp) + li t0, 0x3045406E95C07CD8 + sd t0, 80(sp) + li t0, 0xC6047F9441ED7D6D + sd t0, 88(sp) + li t0, 0x236431A950CFE52A + sd t0, 96(sp) + li t0, 0xF7F632653266D0E1 + sd t0, 104(sp) + li t0, 0xA3C58419466CEAEE + sd t0, 112(sp) + li t0, 0x1AE168FEA63DC339 + sd t0, 120(sp) + + # u1 = 2^255 at sp+128 (bit 255 only) + li t0, 0x0000000000000000 + sd t0, 128(sp) + li t0, 0x0000000000000000 + sd t0, 136(sp) + li t0, 0x0000000000000000 + sd t0, 144(sp) + li t0, 0x8000000000000000 + sd t0, 152(sp) + + # u2 = 2^255 - 1 at sp+160 (bits 0..254) - complementary to u1 + li t0, 0xFFFFFFFFFFFFFFFF + sd t0, 160(sp) + li t0, 0xFFFFFFFFFFFFFFFF + sd t0, 168(sp) + li t0, 0xFFFFFFFFFFFFFFFF + sd t0, 176(sp) + li t0, 0x7FFFFFFFFFFFFFFF + sd t0, 184(sp) + + # lincomb2 ecall: a0 = &Q, a1 = &P1, a2 = &P2, a3 = &u, a7 = -12. + addi a0, sp, 200 + addi a1, sp, 0 + addi a2, sp, 64 + addi a3, sp, 128 + li a7, -12 + ecall + + # a0 now holds the status word; stash it just below the result so the host + # test can commit status‖xQ‖yQ as one contiguous 72-byte block. + sd a0, 192(sp) + + # Commit syscall: a0 = fd(1), a1 = buf_addr, a2 = count, a7 = 64. + li a0, 1 + addi a1, sp, 192 + li a2, 72 + li a7, 64 + ecall + + # Restore stack and halt. + addi sp, sp, 384 + li a0, 0 + li a7, 93 + ecall +.Lfunc_end1: + .size main, .Lfunc_end1-main diff --git a/executor/programs/asm/test_ecsm_lincomb2_multi.s b/executor/programs/asm/test_ecsm_lincomb2_multi.s new file mode 100644 index 000000000..b2bf44b3b --- /dev/null +++ b/executor/programs/asm/test_ecsm_lincomb2_multi.s @@ -0,0 +1,132 @@ + .attribute 5, "rv64i2p1_m2p0_zmmul1p0" + .globl main +main: + # TWO lincomb2 ecalls from one program, reusing the same P1/P2/u buffers. + # + # The chip performs every MEMW access of a call at a SINGLE timestamp (the + # four operand regions are pairwise disjoint and registers are a separate + # address space), so repetition against the same addresses is exactly what + # would break the access chain if that scheme were wrong. It is also the + # real shape: a block does many ecrecovers. + # + # Stack layout (512 bytes): + # sp+0 P1 = xG‖yG sp+64 P2 = x(2G)‖y(2G) sp+128 u1‖u2 + # sp+192 status1 sp+200 Q1 = xQ‖yQ + # sp+312 status2 sp+320 Q2 = xQ‖yQ + # Every operand address is 8-byte aligned and pairwise ≥ 64 bytes from the + # others, as the syscall's guards require. + addi sp, sp, -512 + + # P1 = G (xP1 at sp+0, yP1 at sp+32) + li t0, 0x59F2815B16F81798 + sd t0, 0(sp) + li t0, 0x029BFCDB2DCE28D9 + sd t0, 8(sp) + li t0, 0x55A06295CE870B07 + sd t0, 16(sp) + li t0, 0x79BE667EF9DCBBAC + sd t0, 24(sp) + li t0, 0x9C47D08FFB10D4B8 + sd t0, 32(sp) + li t0, 0xFD17B448A6855419 + sd t0, 40(sp) + li t0, 0x5DA4FBFC0E1108A8 + sd t0, 48(sp) + li t0, 0x483ADA7726A3C465 + sd t0, 56(sp) + + # P2 = 2G (xP2 at sp+64, yP2 at sp+96) + li t0, 0xABAC09B95C709EE5 + sd t0, 64(sp) + li t0, 0x5C778E4B8CEF3CA7 + sd t0, 72(sp) + li t0, 0x3045406E95C07CD8 + sd t0, 80(sp) + li t0, 0xC6047F9441ED7D6D + sd t0, 88(sp) + li t0, 0x236431A950CFE52A + sd t0, 96(sp) + li t0, 0xF7F632653266D0E1 + sd t0, 104(sp) + li t0, 0xA3C58419466CEAEE + sd t0, 112(sp) + li t0, 0x1AE168FEA63DC339 + sd t0, 120(sp) + + # u1 = 3, u2 = 5 + li t0, 0x0000000000000003 + sd t0, 128(sp) + li t0, 0x0000000000000000 + sd t0, 136(sp) + li t0, 0x0000000000000000 + sd t0, 144(sp) + li t0, 0x0000000000000000 + sd t0, 152(sp) + li t0, 0x0000000000000005 + sd t0, 160(sp) + li t0, 0x0000000000000000 + sd t0, 168(sp) + li t0, 0x0000000000000000 + sd t0, 176(sp) + li t0, 0x0000000000000000 + sd t0, 184(sp) + + # lincomb2 ecall: a0 = &Q, a1 = &P1, a2 = &P2, a3 = &u, a7 = -12. + addi a0, sp, 200 + addi a1, sp, 0 + addi a2, sp, 64 + addi a3, sp, 128 + li a7, -12 + ecall + # a0 holds the status; stash it just below its result block. + sd a0, 192(sp) + + # u1 = 7, u2 = 11 + li t0, 0x0000000000000007 + sd t0, 128(sp) + li t0, 0x0000000000000000 + sd t0, 136(sp) + li t0, 0x0000000000000000 + sd t0, 144(sp) + li t0, 0x0000000000000000 + sd t0, 152(sp) + li t0, 0x000000000000000B + sd t0, 160(sp) + li t0, 0x0000000000000000 + sd t0, 168(sp) + li t0, 0x0000000000000000 + sd t0, 176(sp) + li t0, 0x0000000000000000 + sd t0, 184(sp) + + # lincomb2 ecall: a0 = &Q, a1 = &P1, a2 = &P2, a3 = &u, a7 = -12. + addi a0, sp, 320 + addi a1, sp, 0 + addi a2, sp, 64 + addi a3, sp, 128 + li a7, -12 + ecall + # a0 holds the status; stash it just below its result block. + sd a0, 312(sp) + + # Commit syscall: a0 = fd(1), a1 = buf_addr, a2 = count, a7 = 64. + li a0, 1 + addi a1, sp, 192 + li a2, 72 + li a7, 64 + ecall + + # Commit syscall: a0 = fd(1), a1 = buf_addr, a2 = count, a7 = 64. + li a0, 1 + addi a1, sp, 312 + li a2, 72 + li a7, 64 + ecall + + # Restore stack and halt. + addi sp, sp, 512 + li a0, 0 + li a7, 93 + ecall +.Lfunc_end1: + .size main, .Lfunc_end1-main diff --git a/executor/programs/bench/ecrecover/.cargo/config.toml b/executor/programs/bench/ecrecover/.cargo/config.toml new file mode 100644 index 000000000..ca99a3f45 --- /dev/null +++ b/executor/programs/bench/ecrecover/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.riscv64im-lambda-vm-elf] +rustflags = [ + "--cfg", "getrandom_backend=\"custom\"", + "-C", "passes=lower-atomic" +] diff --git a/executor/programs/bench/ecrecover/Cargo.lock b/executor/programs/bench/ecrecover/Cargo.lock new file mode 100644 index 000000000..147425f52 --- /dev/null +++ b/executor/programs/bench/ecrecover/Cargo.lock @@ -0,0 +1,1091 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown", + "itertools", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "arrayvec", + "digest", + "educe", + "itertools", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "arrayvec", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.7", +] + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bls12_381" +version = "0.8.0" +source = "git+https://github.com/lambdaclass/bls12_381?branch=expose-affine-constructors#78cad0378b17fc3157b83f514be192bf46edf9a1" +dependencies = [ + "digest", + "ff", + "group", + "pairing", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ecrecover" +version = "0.1.0" +dependencies = [ + "ethrex-crypto", + "lambda-vm-ethrex-crypto", + "lambda-vm-syscalls", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "embedded-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "enum-ordinalize" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07f808d588c10e464ea6f7d3eaed500049eff30aaac103460f61828c2d65b3eb" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e528e2d34ba8a67a1a650b86beae8ef69fc5fdb638016f386b973226590432" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ethereum-types" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab15ed80916029f878e0267c3a9f92b67df55e79af370bf66199059ae2b4ee3" +dependencies = [ + "fixed-hash", + "primitive-types", + "uint", +] + +[[package]] +name = "ethrex-crypto" +version = "13.0.0" +source = "git+https://github.com/lambdaclass/ethrex.git?rev=156cb8d6a3974f411d71622eecd1b249ee37ff1c#156cb8d6a3974f411d71622eecd1b249ee37ff1c" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "bls12_381", + "ethereum-types", + "ff", + "hex-literal", + "k256", + "num-bigint", + "p256", + "ripemd", + "sha2", + "thiserror 2.0.19", + "tiny-keccak", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "bitvec", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "lambda-vm-ethrex-crypto" +version = "0.1.0" +dependencies = [ + "ethrex-crypto", + "k256", + "lambda-vm-syscalls", +] + +[[package]] +name = "lambda-vm-syscalls" +version = "0.1.0" +dependencies = [ + "embedded-alloc", + "getrandom 0.2.17", + "getrandom 0.3.4", + "lazy_static", + "rand 0.9.5", + "riscv", + "thiserror 1.0.69", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "linked_list_allocator" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897" + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "primitive-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" +dependencies = [ + "fixed-hash", + "uint", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest", +] + +[[package]] +name = "riscv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "rlsf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "rustversion", + "svgbobdoc", +] + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "subtle", + "zeroize", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl 2.0.19", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] diff --git a/executor/programs/bench/ecrecover/Cargo.toml b/executor/programs/bench/ecrecover/Cargo.toml new file mode 100644 index 000000000..3532afadc --- /dev/null +++ b/executor/programs/bench/ecrecover/Cargo.toml @@ -0,0 +1,20 @@ +[workspace] + +[package] +name = "ecrecover" +version = "0.1.0" +edition = "2024" + +[dependencies] +lambda-vm-syscalls = { path = "../../../../syscalls" } +# The REAL shipping path: `LambdaVmEcsmCrypto::secp256k1_ecrecover` is what the +# ethrex guest injects, so this bench measures production code rather than a +# synthetic ladder. Path dep — this crate is not edited here, only called. +lambda-vm-ethrex-crypto = { path = "../../../../crypto/ethrex-crypto" } +# Needed only to bring the `Crypto` trait into scope. Same pinned rev and +# `default-features = false` as `lambda-vm-ethrex-crypto` and the ethrex guest, +# so feature unification adds nothing to the build. +ethrex-crypto = { git = "https://github.com/lambdaclass/ethrex.git", rev = "156cb8d6a3974f411d71622eecd1b249ee37ff1c", package = "ethrex-crypto", default-features = false } + +[patch."https://github.com/yetanotherco/lambda_vm.git"] +lambda-vm-syscalls = { path = "../../../../syscalls" } diff --git a/executor/programs/bench/ecrecover/src/main.rs b/executor/programs/bench/ecrecover/src/main.rs new file mode 100644 index 000000000..5d8502677 --- /dev/null +++ b/executor/programs/bench/ecrecover/src/main.rs @@ -0,0 +1,207 @@ +//! ecrecover bench guest — phase H. +//! +//! Drives the REAL shipping path: `LambdaVmEcsmCrypto::secp256k1_ecrecover`, +//! i.e. guest `(r, v)` decompression -> `ecsm_lincomb2` ecall -> ECSM2/ECDAS2 -> +//! `keccak256(pk)`. Not a synthetic ECSM ladder, so the number reflects what +//! actually ships. +//! +//! Private input selects the workload — ONE ELF serves every configuration, so +//! A/B arms compare identical code: +//! byte 0 : case. 0 = mean corpus (8 real RFC 6979 signatures, cycled), +//! 1 = worst case (u1, u2) = (2^255, 2^255 - 1), 514 chain rows. +//! bytes 1..3 : signature count, little-endian u16 (0 is treated as 1). +//! +//! Commits the XOR of every recovered address. That is a deterministic function +//! of the workload, so the two A/B arms MUST commit identical bytes — which is +//! the cross-check that the switch did not change results. +//! +//! NOTE the fallback trap: on a non-zero accelerator status the provider falls +//! back to pure-Rust `lincomb`, which returns the SAME answer. Output equality +//! therefore cannot detect it — only the cell slope can. See BENCH.md. + +use ethrex_crypto::Crypto; +use lambda_vm_ethrex_crypto::LambdaVmEcsmCrypto; +use lambda_vm_syscalls as syscalls; + +struct Case { + msg: [u8; 32], + sig: [u8; 64], + recid: u8, +} + +/// Eight real RFC 6979 signatures; mean 451.8 chain rows over the set. +static SIG0: Case = Case { + msg: [ + 0x18, 0x9D, 0xA2, 0x15, 0x54, 0xAD, 0x56, 0x81, 0xCA, 0x34, 0xB6, 0xFC, 0x8E, 0xCC, + 0x51, 0xDD, 0xB7, 0x12, 0xC3, 0xCD, 0x5D, 0x89, 0x27, 0xE3, 0xC3, 0x0B, 0xDB, 0xEF, + 0x38, 0x0F, 0x40, 0x14 + ], + sig: [ + 0x1E, 0x39, 0xF2, 0x36, 0xC1, 0x9F, 0xF1, 0x57, 0xE3, 0x09, 0xB6, 0x87, 0x8F, 0xAF, + 0x44, 0x07, 0xC9, 0xB0, 0x96, 0x03, 0x8A, 0x49, 0x87, 0xC6, 0x98, 0xBA, 0x70, 0x2B, + 0x20, 0xF1, 0xEF, 0x81, 0x99, 0x27, 0x53, 0x56, 0xB8, 0xE7, 0x77, 0x6C, 0x7E, 0xCF, + 0xC8, 0xC5, 0x3F, 0x86, 0x9F, 0x08, 0x1F, 0x30, 0x83, 0x1A, 0xD0, 0xF0, 0x3C, 0x10, + 0x12, 0xD3, 0x47, 0xEE, 0xC2, 0x51, 0x7C, 0x54 + ], + recid: 0, +}; + +static SIG1: Case = Case { + msg: [ + 0x69, 0x21, 0xA2, 0x99, 0xCA, 0x53, 0x23, 0x94, 0x00, 0x35, 0xB3, 0x11, 0x50, 0xE3, + 0x0B, 0x99, 0xAE, 0x41, 0x89, 0x3E, 0xB0, 0xA6, 0xF2, 0x9A, 0x52, 0xBA, 0xBA, 0xC5, + 0x7E, 0xC5, 0x90, 0x0F + ], + sig: [ + 0xD6, 0x16, 0x3D, 0x07, 0x7A, 0x3A, 0xAD, 0xB9, 0x49, 0x54, 0x9F, 0xE7, 0xBB, 0x73, + 0x91, 0xB5, 0xD6, 0x1A, 0x79, 0x86, 0xAB, 0xDE, 0x3C, 0x9A, 0x16, 0x6D, 0x0B, 0x5C, + 0xF1, 0x91, 0x3C, 0x8D, 0x27, 0xED, 0x1C, 0x8C, 0xB9, 0x33, 0x9A, 0xF8, 0x74, 0x92, + 0xC2, 0xB5, 0x1B, 0xF9, 0x35, 0x28, 0x27, 0xC8, 0xE6, 0xC0, 0xBD, 0x34, 0x8D, 0x1D, + 0xF9, 0x32, 0x34, 0x43, 0x05, 0xDA, 0x19, 0xCE + ], + recid: 1, +}; + +static SIG2: Case = Case { + msg: [ + 0x5C, 0x43, 0xFC, 0xD0, 0x87, 0xC3, 0xDE, 0xE2, 0x6B, 0xC1, 0x70, 0x93, 0x15, 0x3D, + 0x29, 0xFB, 0x4F, 0x34, 0x22, 0xB7, 0x68, 0xC7, 0x67, 0x35, 0xC6, 0x7C, 0x3C, 0xD9, + 0x4D, 0x6F, 0xB7, 0x40 + ], + sig: [ + 0x24, 0x82, 0x44, 0xDE, 0x92, 0x40, 0xAF, 0xD8, 0x32, 0xDD, 0xE0, 0x80, 0xF5, 0x6D, + 0x9A, 0xE8, 0xE0, 0x06, 0x60, 0xCA, 0x8D, 0xBC, 0x2D, 0xF2, 0x7F, 0x8F, 0xC5, 0xAB, + 0x52, 0x3C, 0x9E, 0x69, 0x79, 0x82, 0x46, 0xAD, 0xFF, 0x92, 0x8F, 0x4B, 0x5E, 0xA9, + 0x65, 0x8D, 0xAC, 0xA5, 0x67, 0x05, 0x87, 0x91, 0x61, 0x19, 0x9F, 0x75, 0x10, 0xC8, + 0xB6, 0xD8, 0xBA, 0x6E, 0xB8, 0xC2, 0x13, 0x2D + ], + recid: 1, +}; + +static SIG3: Case = Case { + msg: [ + 0x48, 0xB5, 0xF8, 0xBD, 0x6F, 0xE1, 0x57, 0x90, 0xBF, 0xAE, 0xE6, 0x8C, 0x2F, 0xB4, + 0x37, 0xFD, 0x85, 0x09, 0x0A, 0x86, 0xC1, 0xAE, 0x44, 0xBC, 0x6F, 0x9E, 0xC6, 0x25, + 0x5B, 0x53, 0x0B, 0x6B + ], + sig: [ + 0xC5, 0x26, 0xFB, 0x9C, 0x2A, 0x8B, 0x29, 0xF8, 0x5A, 0xB5, 0xD3, 0x8B, 0xEC, 0x03, + 0x71, 0xFB, 0xEE, 0x21, 0xA1, 0xA2, 0xF9, 0xDE, 0x8B, 0x3D, 0x41, 0xC5, 0x53, 0xB9, + 0x4C, 0x5D, 0xE6, 0xA0, 0x81, 0xA5, 0x32, 0xB1, 0x76, 0x88, 0x80, 0xD7, 0x62, 0x14, + 0x73, 0x29, 0x04, 0x2D, 0xB7, 0x57, 0x3A, 0xCE, 0x6E, 0xCA, 0xC0, 0x06, 0x49, 0x97, + 0x7D, 0xD7, 0x38, 0x0F, 0x73, 0x4D, 0xEB, 0x04 + ], + recid: 0, +}; + +static SIG4: Case = Case { + msg: [ + 0xB0, 0x1D, 0xAF, 0xDA, 0x53, 0x8A, 0x84, 0x9D, 0xD1, 0xAE, 0x8D, 0xCE, 0xBC, 0xAB, + 0xC0, 0x11, 0xBB, 0x85, 0x09, 0xCB, 0x91, 0x8B, 0x8F, 0xB8, 0x56, 0x54, 0xA9, 0x77, + 0x34, 0x1E, 0x9B, 0x30 + ], + sig: [ + 0xAD, 0xA3, 0x69, 0x3C, 0x6B, 0xF1, 0xCA, 0x39, 0x53, 0x0C, 0x1A, 0xBF, 0x93, 0xCE, + 0xBA, 0xE0, 0xAF, 0xDF, 0xA1, 0xC5, 0x90, 0xBF, 0x2F, 0x98, 0x83, 0xD1, 0x63, 0x6A, + 0x7D, 0x1A, 0x6E, 0x6A, 0xA5, 0xFC, 0x20, 0x97, 0x23, 0xCA, 0x66, 0x39, 0x34, 0xDA, + 0xFA, 0xB1, 0x7F, 0x3B, 0xDF, 0xB1, 0x9E, 0x32, 0xD6, 0xB3, 0xC3, 0xD3, 0xF4, 0xA9, + 0x0F, 0x2E, 0x4A, 0xAB, 0xD7, 0xF1, 0x68, 0x68 + ], + recid: 1, +}; + +static SIG5: Case = Case { + msg: [ + 0x0A, 0x74, 0x0C, 0x13, 0x56, 0xB7, 0x5C, 0x4A, 0x96, 0x24, 0x11, 0x09, 0xB7, 0x6D, + 0x01, 0xB4, 0x30, 0x28, 0x48, 0x1E, 0x08, 0xD7, 0xC6, 0x48, 0xF1, 0x1D, 0x39, 0xAF, + 0x5E, 0x37, 0xC4, 0x85 + ], + sig: [ + 0xF1, 0xE5, 0xF7, 0xB5, 0xF4, 0x5A, 0x80, 0xDD, 0x26, 0x7F, 0xC8, 0xD8, 0x59, 0x55, + 0x5C, 0xEC, 0x59, 0x4E, 0x0E, 0x18, 0xBF, 0x92, 0xBB, 0x92, 0x71, 0x9B, 0xFF, 0xEC, + 0x26, 0xFD, 0x11, 0x41, 0x42, 0xC9, 0x27, 0xA9, 0x00, 0xF9, 0x65, 0xFB, 0xA0, 0x6B, + 0xDE, 0xA6, 0x6D, 0x8A, 0xCF, 0xD9, 0x1F, 0x43, 0x90, 0x4F, 0x42, 0x76, 0x53, 0x11, + 0x94, 0xF3, 0x68, 0x43, 0xCF, 0x30, 0xAF, 0x5A + ], + recid: 0, +}; + +static SIG6: Case = Case { + msg: [ + 0x21, 0xEB, 0xD6, 0xB2, 0x1C, 0xA8, 0x5B, 0xD3, 0xC6, 0x28, 0xD9, 0x4E, 0xC8, 0x43, + 0xA3, 0x70, 0x61, 0x38, 0xAA, 0xF8, 0x17, 0xFA, 0x49, 0xFF, 0xD8, 0xFC, 0x70, 0x7D, + 0x16, 0x4C, 0xA1, 0xF8 + ], + sig: [ + 0xF2, 0x07, 0x2E, 0x7B, 0x75, 0xA5, 0xD1, 0x7C, 0x35, 0x41, 0xA6, 0xCE, 0x1C, 0x5E, + 0xE2, 0x57, 0xD6, 0xBF, 0x92, 0xC6, 0xC3, 0xED, 0xD6, 0x93, 0xCE, 0x3A, 0xC2, 0x47, + 0x56, 0x07, 0xE7, 0xCB, 0x6C, 0x33, 0x4A, 0x46, 0x63, 0xD3, 0x3C, 0xB0, 0xF9, 0x65, + 0x51, 0x09, 0xDF, 0xFC, 0x87, 0x14, 0xD5, 0xDF, 0xDD, 0x80, 0x0A, 0x04, 0x02, 0x52, + 0x82, 0xC8, 0xE3, 0x2A, 0x11, 0x9F, 0x2E, 0x91 + ], + recid: 1, +}; + +static SIG7: Case = Case { + msg: [ + 0xBB, 0xC1, 0x38, 0xD0, 0xB7, 0x62, 0xC1, 0x0C, 0x7C, 0x9A, 0xF8, 0x08, 0x7A, 0x06, + 0xF6, 0xF0, 0x1D, 0xE0, 0xD0, 0xE6, 0x42, 0xFE, 0x4D, 0x45, 0x06, 0x58, 0x25, 0x1A, + 0x8B, 0xA1, 0xEF, 0x6C + ], + sig: [ + 0x69, 0xED, 0xD1, 0x1B, 0x12, 0x47, 0x2B, 0x8F, 0xC4, 0x91, 0x8F, 0x71, 0x96, 0xD4, + 0x0D, 0xCC, 0xF6, 0x7F, 0xFA, 0x1A, 0x2E, 0x69, 0x15, 0xD3, 0x0C, 0x58, 0x51, 0x72, + 0x9B, 0xAE, 0x2A, 0xCE, 0xE6, 0xE5, 0x95, 0xED, 0xE8, 0xF5, 0x5E, 0x8F, 0x99, 0x79, + 0xF1, 0xBF, 0x1A, 0x34, 0x00, 0x2E, 0x3A, 0xF9, 0x49, 0x8B, 0x2D, 0xCA, 0x84, 0x7A, + 0x97, 0x5F, 0x92, 0x32, 0x55, 0xEE, 0xDB, 0x2B + ], + recid: 1, +}; + +/// (u1, u2) = (2^255, 2^255 - 1): every one of the 256 rounds has a +/// non-zero joint digit, so the chain is 1 + 256 + 256 + 1 = 514 rows — +/// the true worst case over the whole valid input domain. +static WORST: Case = Case { + msg: [ + 0x01, 0x25, 0x37, 0x9C, 0x5C, 0xC6, 0x50, 0x93, 0xAA, 0xF1, 0x1C, 0xDF, 0xE4, 0xAB, + 0x41, 0x89, 0x27, 0x28, 0x7A, 0xB5, 0x19, 0xE1, 0x29, 0xE8, 0x25, 0x02, 0x00, 0x76, + 0x12, 0xD9, 0x20, 0x20 + ], + sig: [ + 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, + 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, + 0xBC, 0xE0, 0x36, 0xF9, 0x05, 0xAA, 0x3E, 0x62, 0x10, 0xE0, 0xEC, 0x5C, 0x0B, 0xDA, + 0x93, 0x9A, 0x22, 0xB7, 0x6C, 0x4B, 0xDE, 0x54, 0x99, 0xEC, 0x11, 0xF7, 0xDC, 0xA3, + 0x14, 0xCE, 0x6D, 0x03, 0x00, 0x7C, 0xEA, 0x28 + ], + recid: 0, +}; + +static MEAN: [&Case; 8] = [&SIG0, &SIG1, &SIG2, &SIG3, &SIG4, &SIG5, &SIG6, &SIG7]; + +pub fn main() { + let input = syscalls::syscalls::get_private_input_slice(); + let case = input.first().copied().unwrap_or(0); + let count = u16::from_le_bytes([ + input.get(1).copied().unwrap_or(1), + input.get(2).copied().unwrap_or(0), + ]) + .max(1) as usize; + + let crypto = LambdaVmEcsmCrypto; + let mut acc = [0u8; 32]; + for i in 0..count { + let c: &Case = if case == 1 { &WORST } else { MEAN[i % MEAN.len()] }; + match crypto.secp256k1_ecrecover(&c.sig, c.recid, &c.msg) { + Ok(addr) => { + for (a, b) in acc.iter_mut().zip(addr.iter()) { + *a ^= *b; + } + } + // Recovery failure would silently shrink the workload; make it + // visible in the committed output instead. + Err(_) => acc[0] ^= 0xFF, + } + } + syscalls::syscalls::commit(&acc); +} diff --git a/executor/src/tests/lincomb2_tests.rs b/executor/src/tests/lincomb2_tests.rs new file mode 100644 index 000000000..0b851af0c --- /dev/null +++ b/executor/src/tests/lincomb2_tests.rs @@ -0,0 +1,639 @@ +//! Tests for the ECSM `lincomb2` syscall — `Q = u1·P1 + u2·P2` on secp256k1. +//! +//! Two properties are load-bearing and get separate coverage: +//! +//! 1. **Correctness.** The `Q` the syscall writes equals both `lincomb2_witness`'s `Q` +//! (the chip spec) and `k256`'s `ProjectivePoint::lincomb` (the software fallback the +//! guest uses whenever the accelerator declines), so accelerating a call can never +//! change the recovered public key. +//! 2. **The status contract.** Degenerate *values* return a non-zero status and leave the +//! result buffer untouched — they never trap, because they come from transaction data +//! and a trap would let one crafted transaction abort a whole block's proof. Degenerate +//! *addresses* are guest-program bugs and stay hard errors. + +use k256::elliptic_curve::ff::PrimeField as _; +use k256::elliptic_curve::ops::LinearCombination as _; +use k256::elliptic_curve::sec1::ToEncodedPoint as _; +use k256::{ProjectivePoint, Scalar}; +use num_bigint::BigUint; + +use crate::vm::instruction::decoding::Instruction; +use crate::vm::instruction::execution::{ + ECSM_LINCOMB2_SYSCALL_NUMBER, ExecutionError, LINCOMB2_STATUS_OK, + LINCOMB2_STATUS_P1_NOT_GENERATOR, LINCOMB2_STATUS_POINT_NOT_CANONICAL, + LINCOMB2_STATUS_POINT_NOT_ON_CURVE, LINCOMB2_STATUS_RESULT_INFINITY, + LINCOMB2_STATUS_SCALAR_IS_ZERO, LINCOMB2_STATUS_SCALAR_OUT_OF_RANGE, + LINCOMB2_STATUS_SUM_DEGENERATE, +}; +use crate::vm::memory::Memory; +use crate::vm::registers::Registers; + +// --------------------------------------------------------------------------- +// Operand helpers. Every operand is 64 bytes: two 32-byte little-endian values. +// --------------------------------------------------------------------------- + +const ADDR_Q: u64 = 0x1000; +const ADDR_P1: u64 = 0x2000; +const ADDR_P2: u64 = 0x3000; +const ADDR_U: u64 = 0x4000; + +/// Byte pattern pre-written to the result region so "the buffer is untouched" is a +/// positive assertion rather than "it still reads as zero". +const SENTINEL: u8 = 0xA5; + +fn write_bytes(memory: &mut Memory, addr: u64, bytes: &[u8]) { + for (i, b) in bytes.iter().enumerate() { + memory.store_byte(addr + i as u64, *b); + } +} + +fn read_64(memory: &Memory, addr: u64) -> [u8; 64] { + let mut out = [0u8; 64]; + for (i, b) in out.iter_mut().enumerate() { + *b = memory.load_byte(addr + i as u64); + } + out +} + +/// Joins two 32-byte little-endian values into one 64-byte operand. +fn operand(lo: &[u8; 32], hi: &[u8; 32]) -> [u8; 64] { + let mut out = [0u8; 64]; + out[..32].copy_from_slice(lo); + out[32..].copy_from_slice(hi); + out +} + +/// `x‖y` of a k256 point, little-endian, in the syscall's operand layout. +fn point_le(p: &ProjectivePoint) -> [u8; 64] { + let affine = p.to_affine(); + let encoded = affine.to_encoded_point(false); + let mut out = [0u8; 64]; + for (i, b) in encoded.x().unwrap().iter().rev().enumerate() { + out[i] = *b; + } + for (i, b) in encoded.y().unwrap().iter().rev().enumerate() { + out[32 + i] = *b; + } + out +} + +fn scalar_le(v: u64) -> [u8; 32] { + let mut out = [0u8; 32]; + out[..8].copy_from_slice(&v.to_le_bytes()); + out +} + +fn k256_scalar(le: &[u8; 32]) -> Scalar { + let mut be = *le; + be.reverse(); + Scalar::from_repr(be.into()).unwrap() +} + +/// `k256`'s `ProjectivePoint::lincomb` — the guest's software fallback — as the +/// syscall's 64-byte result layout. +fn k256_lincomb(p1: &[u8; 64], p2: &[u8; 64], u1: &[u8; 32], u2: &[u8; 32]) -> [u8; 64] { + point_le(&ProjectivePoint::lincomb( + &le_to_k256(p1), + &k256_scalar(u1), + &le_to_k256(p2), + &k256_scalar(u2), + )) +} + +fn le_to_k256(p: &[u8; 64]) -> ProjectivePoint { + use k256::elliptic_curve::sec1::FromEncodedPoint as _; + let mut x = [0u8; 32]; + let mut y = [0u8; 32]; + x.copy_from_slice(&p[..32]); + y.copy_from_slice(&p[32..]); + x.reverse(); + y.reverse(); + let encoded = k256::EncodedPoint::from_affine_coordinates(&x.into(), &y.into(), false); + ProjectivePoint::from(k256::AffinePoint::from_encoded_point(&encoded).unwrap()) +} + +/// `lincomb2_witness`'s `Q` (the chip spec) in the syscall's result layout. +fn witness_q(p1: &[u8; 64], p2: &[u8; 64], u1: &[u8; 32], u2: &[u8; 32]) -> [u8; 64] { + let point = |b: &[u8; 64]| ecsm::AffinePoint { + x: BigUint::from_bytes_le(&b[..32]), + y: BigUint::from_bytes_le(&b[32..]), + }; + let w = ecsm::witness::lincomb2_witness(u1, u2, &point(p1), &point(p2)).expect("witness"); + operand(&w.x_q, &w.y_q) +} + +/// One syscall invocation at caller-chosen addresses. Returns the status word left in +/// `a0` and the 64 bytes at the result address. +fn run_lincomb2_at( + addrs: [u64; 4], + p1: &[u8; 64], + p2: &[u8; 64], + u: &[u8; 64], +) -> Result<(u64, [u8; 64]), ExecutionError> { + let [addr_q, addr_p1, addr_p2, addr_u] = addrs; + let mut pc = 0; + let mut registers = Registers::default(); + let mut memory = Memory::default(); + + // The inputs are written before the result sentinel so that an overlapping result + // region visibly clobbers them rather than the other way round. + write_bytes(&mut memory, addr_p1, p1); + write_bytes(&mut memory, addr_p2, p2); + write_bytes(&mut memory, addr_u, u); + write_bytes(&mut memory, addr_q, &[SENTINEL; 64]); + + registers.write(17, ECSM_LINCOMB2_SYSCALL_NUMBER).unwrap(); + registers.write(10, addr_q).unwrap(); + registers.write(11, addr_p1).unwrap(); + registers.write(12, addr_p2).unwrap(); + registers.write(13, addr_u).unwrap(); + + Instruction::EcallEbreak.run(&mut pc, &mut registers, &mut memory)?; + + // The status is returned in a0; the three input pointers must survive the call. + let status = registers.read(10).unwrap(); + assert_eq!(registers.read(11).unwrap(), addr_p1, "a1 clobbered"); + assert_eq!(registers.read(12).unwrap(), addr_p2, "a2 clobbered"); + assert_eq!(registers.read(13).unwrap(), addr_u, "a3 clobbered"); + + // Both paths must leave the inputs exactly as they were: the chip re-reads these + // bytes at the ecall's timestamp and proves what it consumed. + assert_eq!(&read_64(&memory, addr_p1), p1, "P1 operand modified"); + assert_eq!(&read_64(&memory, addr_p2), p2, "P2 operand modified"); + assert_eq!(&read_64(&memory, addr_u), u, "scalar operand modified"); + + Ok((status, read_64(&memory, addr_q))) +} + +/// One syscall invocation at the standard disjoint addresses. +fn run_lincomb2(p1: &[u8; 64], p2: &[u8; 64], u: &[u8; 64]) -> (u64, [u8; 64]) { + run_lincomb2_at([ADDR_Q, ADDR_P1, ADDR_P2, ADDR_U], p1, p2, u) + .expect("valid addresses must not error") +} + +fn g() -> [u8; 64] { + point_le(&ProjectivePoint::GENERATOR) +} + +/// `m·G` as an operand — a convenient supply of distinct valid points. +fn mul_g(m: u64) -> [u8; 64] { + point_le(&(ProjectivePoint::GENERATOR * k256_scalar(&scalar_le(m)))) +} + +/// Asserts a rejected call left the result buffer exactly as the sentinel found it. +fn assert_untouched(out: &[u8; 64]) { + assert_eq!( + out, &[SENTINEL; 64], + "a non-zero status must leave the result buffer untouched" + ); +} + +// --------------------------------------------------------------------------- +// Happy path +// --------------------------------------------------------------------------- + +/// One happy-path input tuple: `(P2, u1, u2)`. `P1` is always `G` — the syscall accepts +/// no other `P1` (see `lincomb2_syscall_rejects_non_generator_p1`). +type Case = ([u8; 64], [u8; 32], [u8; 32]); + +#[test] +fn lincomb2_syscall_matches_witness_and_k256() { + // P2 = m·G for a few m, over a spread of scalar sizes (including the 256-bit range + // where the joint schedule runs its full 256 doublings). + let mut n_minus_3 = ecsm::N_BYTES; + n_minus_3[0] -= 3; // N ends in 0x41 little-endian, so no borrow + + let cases: [Case; 6] = [ + (mul_g(2), scalar_le(1), scalar_le(1)), + (mul_g(2), scalar_le(3), scalar_le(5)), + (mul_g(7), scalar_le(0xFFFF), scalar_le(1_000_003)), + (mul_g(11), scalar_le(u64::MAX), scalar_le(2)), + (mul_g(2), n_minus_3, scalar_le(1)), + (mul_g(9), n_minus_3, n_minus_3), + ]; + + let p1 = g(); + for (i, (p2, u1, u2)) in cases.iter().enumerate() { + let (status, out) = run_lincomb2(&p1, p2, &operand(u1, u2)); + assert_eq!(status, LINCOMB2_STATUS_OK, "case {i}"); + assert_eq!(out, witness_q(&p1, p2, u1, u2), "case {i}: Q != witness Q"); + assert_eq!(out, k256_lincomb(&p1, p2, u1, u2), "case {i}: Q != k256 Q"); + } +} + +#[test] +fn lincomb2_syscall_writes_exactly_the_result_region() { + // The write must be the 64 bytes at a0 and nothing else: a wider store would + // silently corrupt whatever the guest put next to its buffer. + let mut pc = 0; + let mut registers = Registers::default(); + let mut memory = Memory::default(); + + let (p1, p2) = (g(), mul_g(2)); + let u = operand(&scalar_le(3), &scalar_le(5)); + write_bytes(&mut memory, ADDR_P1, &p1); + write_bytes(&mut memory, ADDR_P2, &p2); + write_bytes(&mut memory, ADDR_U, &u); + write_bytes(&mut memory, ADDR_Q - 8, &[SENTINEL; 80]); // 8 before .. 8 after + + registers.write(17, ECSM_LINCOMB2_SYSCALL_NUMBER).unwrap(); + registers.write(10, ADDR_Q).unwrap(); + registers.write(11, ADDR_P1).unwrap(); + registers.write(12, ADDR_P2).unwrap(); + registers.write(13, ADDR_U).unwrap(); + Instruction::EcallEbreak + .run(&mut pc, &mut registers, &mut memory) + .unwrap(); + + assert_eq!(registers.read(10).unwrap(), LINCOMB2_STATUS_OK); + for offset in 0..8u64 { + assert_eq!( + memory.load_byte(ADDR_Q - 8 + offset), + SENTINEL, + "wrote below" + ); + assert_eq!( + memory.load_byte(ADDR_Q + 64 + offset), + SENTINEL, + "wrote above" + ); + } +} + +// --------------------------------------------------------------------------- +// Status contract: one test per `Lincomb2Error` variant +// --------------------------------------------------------------------------- + +#[test] +fn lincomb2_syscall_reports_zero_scalar() { + let (p1, p2) = (g(), mul_g(2)); + for u in [ + operand(&scalar_le(0), &scalar_le(5)), + operand(&scalar_le(5), &scalar_le(0)), + ] { + let (status, out) = run_lincomb2(&p1, &p2, &u); + assert_eq!(status, LINCOMB2_STATUS_SCALAR_IS_ZERO); + assert_untouched(&out); + } +} + +#[test] +fn lincomb2_syscall_reports_out_of_range_scalar() { + let (p1, p2) = (g(), mul_g(2)); + for u in [ + operand(&ecsm::N_BYTES, &scalar_le(5)), + operand(&scalar_le(5), &ecsm::N_BYTES), + ] { + let (status, out) = run_lincomb2(&p1, &p2, &u); + assert_eq!(status, LINCOMB2_STATUS_SCALAR_OUT_OF_RANGE); + assert_untouched(&out); + } +} + +#[test] +fn lincomb2_syscall_reports_point_not_on_curve() { + // Only P2 can reach this: P1 is pinned to G, so a malformed P1 is caught earlier by + // the generator check. + // y + 1 is still canonical (G's y is nowhere near p) but off the curve. + let mut bad = g(); + bad[32] += 1; + let u = operand(&scalar_le(3), &scalar_le(5)); + let (status, out) = run_lincomb2(&g(), &bad, &u); + assert_eq!(status, LINCOMB2_STATUS_POINT_NOT_ON_CURVE); + assert_untouched(&out); +} + +#[test] +fn lincomb2_syscall_reports_non_canonical_point() { + // y = p is the non-canonical alias of y = 0. Dropping this check is a real forgery: + // yP2 + p is the same point mod p but has the OPPOSITE parity as bytes, which flips + // the sign of Q. The executor must never hand such a point to the chip. + let mut bad_y = g(); + bad_y[32..].copy_from_slice(&ecsm::P_BYTES); + let mut bad_x = g(); + bad_x[..32].copy_from_slice(&ecsm::P_BYTES); + let u = operand(&scalar_le(3), &scalar_le(5)); + for p2 in [bad_y, bad_x] { + let (status, out) = run_lincomb2(&g(), &p2, &u); + assert_eq!(status, LINCOMB2_STATUS_POINT_NOT_CANONICAL); + assert_untouched(&out); + } +} + +#[test] +fn lincomb2_syscall_rejects_non_generator_p1() { + // ECSM′ binds a1's bytes to G by construction — it has no `mem_p1` membership + // witness — so a P1 the chip cannot represent must NOT come back as status 0. If it + // did, the trace builder would emit a row asserting bytes that are not in memory, the + // constraint would fail, and the block would be unprovable. Returning a status keeps + // executor and chip in agreement and degrades such a caller to software. + let u = operand(&scalar_le(3), &scalar_le(5)); + + // Perfectly valid curve points that simply are not G. + for p1 in [mul_g(2), mul_g(3), mul_g(0xDEAD_BEEF)] { + let (status, out) = run_lincomb2(&p1, &mul_g(7), &u); + assert_eq!(status, LINCOMB2_STATUS_P1_NOT_GENERATOR); + assert_untouched(&out); + } + + // −G: same x as G, opposite y. The check is on all 64 bytes, not just x, because the + // chip binds both coordinates. + let mut neg_g = g(); + neg_g[32..].copy_from_slice(&ecsm::to_le_32( + &(ecsm::p() - BigUint::from_bytes_le(&g()[32..])), + )); + let (status, out) = run_lincomb2(&neg_g, &mul_g(7), &u); + assert_eq!(status, LINCOMB2_STATUS_P1_NOT_GENERATOR); + assert_untouched(&out); + + // A single flipped byte in either coordinate is caught too. + for i in [0usize, 31, 32, 63] { + let mut p1 = g(); + p1[i] ^= 1; + let (status, out) = run_lincomb2(&p1, &mul_g(7), &u); + assert_eq!(status, LINCOMB2_STATUS_P1_NOT_GENERATOR, "byte {i}"); + assert_untouched(&out); + } + + // The real G is accepted, so the check is not vacuous. + let (status, _) = run_lincomb2(&g(), &mul_g(7), &u); + assert_eq!(status, LINCOMB2_STATUS_OK); +} + +#[test] +fn generator_le_is_the_secp256k1_generator() { + // The pinned constant must be the curve's actual generator; k256 re-derives it. + use crate::vm::instruction::execution::GENERATOR_LE; + assert_eq!(GENERATOR_LE, g()); +} + +#[test] +fn lincomb2_syscall_reports_degenerate_sum() { + // P1 = ±P2 makes the P1 + P2 precompute a doubling (or infinity), so the addend + // table the joint chain indexes does not exist. + let g = g(); + let mut neg_g = g; + neg_g[32..].copy_from_slice(&ecsm::to_le_32( + &(ecsm::p() - BigUint::from_bytes_le(&g[32..])), + )); + let u = operand(&scalar_le(3), &scalar_le(5)); + for p2 in [g, neg_g] { + let (status, out) = run_lincomb2(&g, &p2, &u); + assert_eq!(status, LINCOMB2_STATUS_SUM_DEGENERATE); + assert_untouched(&out); + } +} + +#[test] +fn lincomb2_syscall_reports_infinite_result() { + // (N-2)·G + 1·(2G) = N·G = ∞, which has no affine witness. + let mut u1 = ecsm::N_BYTES; + u1[0] -= 2; // N ends in 0x41 little-endian, so no borrow + let (status, out) = run_lincomb2(&g(), &mul_g(2), &operand(&u1, &scalar_le(1))); + assert_eq!(status, LINCOMB2_STATUS_RESULT_INFINITY); + assert_untouched(&out); +} + +#[test] +fn lincomb2_syscall_always_writes_the_status_register() { + // The error path must be expressible as a proof row: the chip gives every lincomb2 + // ecall one row that receives the Ecall bus and performs the same fixed MEMW + // accesses, so `a0` must be overwritten with the status whether or not a witness + // exists. If a future refactor early-returns before `registers.write(10, ...)`, `a0` + // would still hold the result address and the ecall would have no receiver. + let (p1, p2) = (g(), mul_g(2)); + let good = operand(&scalar_le(3), &scalar_le(5)); + let bad = operand(&scalar_le(0), &scalar_le(5)); + + for (u, expected) in [ + (good, LINCOMB2_STATUS_OK), + (bad, LINCOMB2_STATUS_SCALAR_IS_ZERO), + ] { + let mut pc = 0; + let mut registers = Registers::default(); + let mut memory = Memory::default(); + write_bytes(&mut memory, ADDR_P1, &p1); + write_bytes(&mut memory, ADDR_P2, &p2); + write_bytes(&mut memory, ADDR_U, &u); + registers.write(17, ECSM_LINCOMB2_SYSCALL_NUMBER).unwrap(); + registers.write(10, ADDR_Q).unwrap(); + registers.write(11, ADDR_P1).unwrap(); + registers.write(12, ADDR_P2).unwrap(); + registers.write(13, ADDR_U).unwrap(); + Instruction::EcallEbreak + .run(&mut pc, &mut registers, &mut memory) + .unwrap(); + + let a0 = registers.read(10).unwrap(); + assert_eq!(a0, expected); + assert_ne!( + a0, ADDR_Q, + "a0 must be overwritten, not left as the address" + ); + } +} + +#[test] +fn lincomb2_status_codes_are_distinct() { + // The guest only tests `!= 0`, but the codes must stay distinguishable for + // debugging — a collision would silently merge two failure modes. + let codes = [ + LINCOMB2_STATUS_OK, + LINCOMB2_STATUS_SCALAR_IS_ZERO, + LINCOMB2_STATUS_SCALAR_OUT_OF_RANGE, + LINCOMB2_STATUS_POINT_NOT_ON_CURVE, + LINCOMB2_STATUS_POINT_NOT_CANONICAL, + LINCOMB2_STATUS_SUM_DEGENERATE, + LINCOMB2_STATUS_RESULT_INFINITY, + LINCOMB2_STATUS_P1_NOT_GENERATOR, + ]; + let mut sorted = codes.to_vec(); + sorted.sort_unstable(); + sorted.dedup(); + assert_eq!(sorted.len(), codes.len(), "status codes collide"); + assert_eq!(LINCOMB2_STATUS_OK, 0, "only success may be zero"); +} + +// --------------------------------------------------------------------------- +// Address guards +// --------------------------------------------------------------------------- + +/// Runs the syscall with valid operands at caller-chosen addresses. +fn run_lincomb2_addrs(addrs: [u64; 4]) -> Result<(u64, [u8; 64]), ExecutionError> { + run_lincomb2_at( + addrs, + &g(), + &mul_g(2), + &operand(&scalar_le(3), &scalar_le(5)), + ) +} + +#[test] +fn lincomb2_syscall_rejects_unaligned_addresses() { + // Each region is read/written as eight ALIGNED doubleword MEMW accesses. + for slot in 0..4 { + for misalignment in [1u64, 2, 4, 7] { + let mut addrs = [ADDR_Q, ADDR_P1, ADDR_P2, ADDR_U]; + addrs[slot] += misalignment; + let err = run_lincomb2_addrs(addrs).unwrap_err(); + assert!( + matches!(err, ExecutionError::Lincomb2UnalignedAddress(a) if a == addrs[slot]), + "slot {slot} at +{misalignment} must be rejected, got {err:?}" + ); + } + } +} + +#[test] +fn lincomb2_syscall_rejects_address_overflow() { + // The last byte of a 64-byte operand sits at +63; crossing 2^32 splits the operand + // across the MEMW address limbs. + for slot in 0..4 { + let mut addrs = [ADDR_Q, ADDR_P1, ADDR_P2, ADDR_U]; + addrs[slot] = 0xFFFF_FFC8; // 8-aligned, but +63 lands at 2^32 + 7 + let err = run_lincomb2_addrs(addrs).unwrap_err(); + assert!( + matches!(err, ExecutionError::Lincomb2AddressOverflow(a) if a == addrs[slot]), + "slot {slot} must overflow, got {err:?}" + ); + + // The exact boundary is fine: 0xFFFF_FFC0 + 63 = 0xFFFF_FFFF. + let mut addrs = [ADDR_Q, ADDR_P1, ADDR_P2, ADDR_U]; + addrs[slot] = 0xFFFF_FFC0; + run_lincomb2_addrs(addrs) + .unwrap_or_else(|e| panic!("slot {slot} at the limb boundary must run, got {e:?}")); + } +} + +#[test] +fn lincomb2_syscall_rejects_overlapping_operands() { + // All six pairs, including the result against each input: unlike `ecsm_mul`'s xR, + // the result region may not alias an input, since it is written after the reads. + let base = [ADDR_Q, ADDR_P1, ADDR_P2, ADDR_U]; + for i in 0..4 { + for j in 0..4 { + if i == j { + continue; + } + for delta in [0i64, 8, 56, -8, -56] { + let mut addrs = base; + addrs[j] = (base[i] as i64 + delta) as u64; + let err = run_lincomb2_addrs(addrs) + .err() + .unwrap_or_else(|| panic!("slots {i}/{j} at delta {delta} must be rejected")); + assert!( + matches!(err, ExecutionError::Lincomb2OperandOverlap(_, _)), + "slots {i}/{j} at delta {delta}: expected overlap, got {err:?}" + ); + } + // Touching but disjoint (|diff| = 64) is allowed. + for delta in [64i64, -64] { + let mut addrs = base; + addrs[j] = (base[i] as i64 + delta) as u64; + run_lincomb2_addrs(addrs).unwrap_or_else(|e| { + panic!("slots {i}/{j} at delta {delta} are disjoint and must run, got {e:?}") + }); + } + } + } +} + +// --------------------------------------------------------------------------- +// Guest → executor round trip +// --------------------------------------------------------------------------- + +#[test] +fn lincomb2_syscall_round_trips_the_ecrecover_shape() { + // The shape the guest actually calls: pk = u1·G + u2·R, with R a decompressed + // signature point and u1/u2 the ECDSA recovery scalars. Both are full-width + // 256-bit scalars, so this exercises the longest joint schedule. + let u1 = { + let mut b = ecsm::N_BYTES; + b[0] -= 0x37; + b[31] -= 0x11; + b + }; + let u2 = { + let mut b = [0u8; 32]; + for (i, x) in b.iter_mut().enumerate() { + *x = (i as u8).wrapping_mul(37).wrapping_add(3); + } + b[31] &= 0x7F; // keep it below N + b + }; + let r = mul_g(0xDEAD_BEEF); + + let (status, out) = run_lincomb2(&g(), &r, &operand(&u1, &u2)); + assert_eq!(status, LINCOMB2_STATUS_OK); + assert_eq!(out, k256_lincomb(&g(), &r, &u1, &u2)); + + // A guest that trusts the status word gets exactly what the fallback would produce. + let pk = if status == LINCOMB2_STATUS_OK { + out + } else { + k256_lincomb(&g(), &r, &u1, &u2) + }; + assert_eq!(pk, witness_q(&g(), &r, &u1, &u2)); +} + +/// The full guest → executor path: a real ELF, decoded and executed, whose `main` +/// materializes the operands on its stack, issues `ecall` with `a7 = -12`, and commits +/// `status‖xQ‖yQ`. This is what the register-level tests above cannot cover — that the +/// ABI's register assignment survives instruction decode and that the guest observes the +/// status in `a0`. +/// +/// Reads a prebuilt artifact, like every other guest-ELF test here; run +/// `make compile-programs-asm` first. +#[test] +fn lincomb2_asm_guest_round_trip() { + use crate::elf::Elf; + use crate::vm::execution::Executor; + + let path = "./program_artifacts/asm/test_ecsm_lincomb2.elf"; + let elf_data = std::fs::read(path).unwrap_or_else(|e| panic!("{path}: {e}")); + let program = Elf::load(&elf_data).unwrap(); + let result = Executor::new(&program, vec![]).unwrap().run().unwrap(); + + // The guest commits status(8, little-endian) ‖ xQ(32) ‖ yQ(32). + let committed = result.return_values.memory_values; + assert_eq!(committed.len(), 72, "guest must commit 72 bytes"); + let status = u64::from_le_bytes(committed[..8].try_into().unwrap()); + assert_eq!(status, LINCOMB2_STATUS_OK, "guest saw a non-zero status"); + + let mut q = [0u8; 64]; + q.copy_from_slice(&committed[8..]); + + // The guest computes 3·G + 5·(2G) = 13·G. + let (p1, p2) = (g(), mul_g(2)); + let (u1, u2) = (scalar_le(3), scalar_le(5)); + assert_eq!(q, witness_q(&p1, &p2, &u1, &u2)); + assert_eq!(q, k256_lincomb(&p1, &p2, &u1, &u2)); + assert_eq!(q, mul_g(13), "3G + 5·(2G) must be 13G"); + + // The program halts with exit code 0. + assert_eq!(result.return_values.register_values.0, 0); +} + +#[test] +fn lincomb2_syscall_number_is_free() { + use crate::vm::instruction::execution::{ + ECSM_SYSCALL_NUMBER, KECCAK_SYSCALL_NUMBER, SyscallNumbers, + }; + + // -12, one below ECSM's -11, and distinct from every other syscall this VM decodes. + assert_eq!(ECSM_LINCOMB2_SYSCALL_NUMBER, u64::MAX - 11); + for taken in [ + KECCAK_SYSCALL_NUMBER, + ECSM_SYSCALL_NUMBER, + SyscallNumbers::Print as u64, + SyscallNumbers::Panic as u64, + SyscallNumbers::Commit as u64, + SyscallNumbers::Halt as u64, + ] { + assert_ne!(ECSM_LINCOMB2_SYSCALL_NUMBER, taken); + } + assert!(matches!( + SyscallNumbers::try_from(ECSM_LINCOMB2_SYSCALL_NUMBER), + Ok(SyscallNumbers::EcsmLincomb2) + )); +} diff --git a/executor/src/tests/mod.rs b/executor/src/tests/mod.rs index 456607433..7f3a3949d 100644 --- a/executor/src/tests/mod.rs +++ b/executor/src/tests/mod.rs @@ -1,4 +1,5 @@ pub mod ecsm_tests; pub mod flamegraph_tests; pub mod keccak_tests; +pub mod lincomb2_tests; pub mod memory_tests; diff --git a/executor/src/vm/instruction/execution.rs b/executor/src/vm/instruction/execution.rs index c92c0ab88..12309b23b 100644 --- a/executor/src/vm/instruction/execution.rs +++ b/executor/src/vm/instruction/execution.rs @@ -1,3 +1,7 @@ +use num_bigint::BigUint; + +use ecsm::witness::{Lincomb2Error, Lincomb2Witness}; + use crate::vm::{ instruction::decoding::{ArithOp, Comparison, Instruction, LoadStoreWidth}, logs::Log, @@ -16,6 +20,9 @@ pub enum SyscallNumbers { Halt = 93, // Placeholder discriminant. The actual syscall value is ECSM_SYSCALL_NUMBER. Ecsm = 94, + // Placeholder discriminant. The actual syscall value is + // ECSM_LINCOMB2_SYSCALL_NUMBER. + EcsmLincomb2 = 95, } /// Syscall number for KeccakPermute (u64::MAX - 1 = 0xFFFF_FFFF_FFFF_FFFE). @@ -31,10 +38,23 @@ const KECCAK_STATE_BYTES: u64 = 25 * 8; /// bus as `[lo32, hi32] = [2^32 - 11, 2^32 - 1]`. pub const ECSM_SYSCALL_NUMBER: u64 = u64::MAX - 10; +/// Syscall number for the ECSM `lincomb2` accelerator: `Q = u1·P1 + u2·P2` on secp256k1 +/// in one call (the ecrecover shape `s·R − z·G`). +/// +/// ECALL number `-12`, i.e. `u64::MAX - 11 = 0xFFFF_FFFF_FFFF_FFF4` — the slot directly +/// below ECSM's `-11`, keeping the EC accelerators contiguous. `-2` (Keccak) and `-11` +/// (ECSM) are the only other negative syscall numbers this VM defines, so `-12` is free. +pub const ECSM_LINCOMB2_SYSCALL_NUMBER: u64 = u64::MAX - 11; + /// `2^32`. ECSM memory operands must not overflow their lower 32-bit address limb when the -/// largest per-access offset is added: the 32-byte operands reach offset +31 (last byte). +/// largest per-access offset is added: the 32-byte operands reach offset +31 (last byte), +/// the 64-byte `lincomb2` operands offset +63. const LOW_LIMB: u64 = 1 << 32; +/// Byte length of one `ecsm_lincomb2` memory operand: two 32-byte little-endian values +/// (`xP‖yP`, or `u1‖u2`) laid out back to back. +const LINCOMB2_OPERAND_BYTES: u64 = 64; + impl TryFrom for SyscallNumbers { type Error = (); fn try_from(value: u64) -> Result { @@ -45,6 +65,7 @@ impl TryFrom for SyscallNumbers { 93 => Ok(SyscallNumbers::Halt), v if v == KECCAK_SYSCALL_NUMBER => Ok(SyscallNumbers::KeccakPermute), v if v == ECSM_SYSCALL_NUMBER => Ok(SyscallNumbers::Ecsm), + v if v == ECSM_LINCOMB2_SYSCALL_NUMBER => Ok(SyscallNumbers::EcsmLincomb2), _ => Err(()), } } @@ -55,6 +76,7 @@ impl TryFrom for SyscallNumbers { pub enum Accelerator { Keccak, Ecsm, + EcsmLincomb2, } impl SyscallNumbers { @@ -65,6 +87,7 @@ impl SyscallNumbers { match self { SyscallNumbers::KeccakPermute => Some(Accelerator::Keccak), SyscallNumbers::Ecsm => Some(Accelerator::Ecsm), + SyscallNumbers::EcsmLincomb2 => Some(Accelerator::EcsmLincomb2), SyscallNumbers::Print | SyscallNumbers::Panic | SyscallNumbers::Commit @@ -93,11 +116,207 @@ fn store_u256_le(memory: &mut Memory, addr: u64, bytes: &[u8; 32]) -> Result<(), Ok(()) } +/// Reads a 512-bit little-endian `ecsm_lincomb2` operand as eight doublewords at `addr + 8i`. +fn load_u512_le(memory: &Memory, addr: u64) -> Result<[u8; 64], MemoryError> { + let mut out = [0u8; 64]; + for (i, chunk) in out.chunks_mut(8).enumerate() { + let dw = memory.load_doubleword(addr + (i as u64) * 8)?; + chunk.copy_from_slice(&dw.to_le_bytes()); + } + Ok(out) +} + /// Checks the ECSM address-alignment assumption: `(addr mod 2^32) + max_offset < 2^32`. fn ecsm_addr_ok(addr: u64, max_offset: u64) -> bool { (addr % LOW_LIMB) + max_offset < LOW_LIMB } +// ============================================================================= +// ECSM lincomb2 status contract +// ============================================================================= + +// The word the `ecsm_lincomb2` syscall leaves in `a0`. `0` means "the result at the +// `a0` buffer is `Q = u1·P1 + u2·P2`"; every other value means "no sound witness +// exists for these inputs, nothing was written", and the guest falls back to its +// pure-Rust `ProjectivePoint::lincomb`. +// +// A non-zero status is ALWAYS sound: the fallback is proven guest execution, so a +// lying status can only waste cycles, never forge a result. That is why degenerate +// *values* return a status instead of trapping the way `ecsm_mul` does — the scalars +// and points come from transaction data, and a trap would let one crafted transaction +// abort the proof of an entire block. (Operand *addresses* are a different matter: +// they are chosen by the guest program, not by the transaction, so a bad address is a +// guest bug and stays a hard `ExecutionError` — see `lincomb2_addrs_ok`.) +// +// The codes are distinct per `Lincomb2Error` variant purely so debugging and bench +// runs can tell the cases apart; the guest only ever tests `!= 0`. + +/// `Q` was computed and written to the `a0` buffer. +pub const LINCOMB2_STATUS_OK: u64 = 0; +/// `u1` or `u2` is zero. +pub const LINCOMB2_STATUS_SCALAR_IS_ZERO: u64 = 1; +/// `u1` or `u2` is `>= N`. +pub const LINCOMB2_STATUS_SCALAR_OUT_OF_RANGE: u64 = 2; +/// `P1` or `P2` is not on the curve. +pub const LINCOMB2_STATUS_POINT_NOT_ON_CURVE: u64 = 3; +/// `P1` or `P2` has a coordinate `>= p`. +pub const LINCOMB2_STATUS_POINT_NOT_CANONICAL: u64 = 4; +/// `P1 = ±P2`, so the `P1 + P2` precompute is not a chord. +pub const LINCOMB2_STATUS_SUM_DEGENERATE: u64 = 5; +/// `Q` is the point at infinity (or an accumulator collided with its addend). +pub const LINCOMB2_STATUS_RESULT_INFINITY: u64 = 6; +/// `P1` is not the secp256k1 generator `G`. See [`GENERATOR_LE`]. +pub const LINCOMB2_STATUS_P1_NOT_GENERATOR: u64 = 7; + +/// The secp256k1 generator `G` as the syscall's 64-byte operand: `xG ‖ yG`, little-endian. +/// +/// Pinned here rather than imported because the executor has no curve library of its own; +/// `generator_le_is_the_secp256k1_generator` re-derives it from `k256` so a typo cannot +/// survive. Same idiom as `ecsm::witness`'s pinned `T₀`. +pub const GENERATOR_LE: [u8; 64] = [ + 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59, 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02, + 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55, 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79, + 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C, 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD, + 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D, 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48, +]; + +/// Maps a witness-generation failure to its `a0` status word. +/// +/// Exhaustive on purpose: a new `Lincomb2Error` variant must be a compile error here +/// rather than silently collapsing onto an existing code. +fn lincomb2_status(error: &Lincomb2Error) -> u64 { + match error { + Lincomb2Error::ScalarIsZero => LINCOMB2_STATUS_SCALAR_IS_ZERO, + Lincomb2Error::ScalarOutOfRange => LINCOMB2_STATUS_SCALAR_OUT_OF_RANGE, + Lincomb2Error::PointNotOnCurve => LINCOMB2_STATUS_POINT_NOT_ON_CURVE, + Lincomb2Error::PointNotCanonical => LINCOMB2_STATUS_POINT_NOT_CANONICAL, + Lincomb2Error::SumDegenerate => LINCOMB2_STATUS_SUM_DEGENERATE, + Lincomb2Error::ResultInfinity => LINCOMB2_STATUS_RESULT_INFINITY, + } +} + +/// The outcome of one `ecsm_lincomb2` invocation: the status word written back to `a0` +/// and, on success, the chip witness for the call. +/// +/// This is the "row log" the proving side consumes. The executor deliberately does NOT +/// retain these: one `Lincomb2Witness` holds ~450 double/add steps of 1,872 bytes each +/// (three `[i64; 64]` carry arrays apiece), i.e. ~820 KiB per call — a block's worth would +/// be gigabytes. Instead the trace builder re-reads the operand bytes at the ecall's +/// timestamp and calls [`lincomb2_outcome`] — the very function the executor arm calls +/// below — so the two sides cannot disagree about the status or about which rows exist. +/// This mirrors ECSM, where the executor computes only `xR` and `collect_ecsm_ops` +/// rebuilds the full witness at trace-build time. +pub struct Lincomb2Outcome { + /// The word written to `a0`. [`LINCOMB2_STATUS_OK`] iff `witness.is_some()`. + pub status: u64, + /// The chip witness, present exactly when the status is OK. Boxed because it is + /// large enough that moving it around by value is measurable. + pub witness: Option>, +} + +/// Evaluates one `lincomb2` call from its three 64-byte operands, each holding two +/// 32-byte little-endian values: `p1 = xP1‖yP1`, `p2 = xP2‖yP2`, `u = u1‖u2`. +/// +/// `status == LINCOMB2_STATUS_OK` holds exactly when the proving side can back the +/// result, which takes two things: +/// +/// 1. **A witness exists.** The status comes from `lincomb2_witness` itself, never from a +/// cheaper pre-check. A "just compute Q" shortcut could succeed where witness +/// generation fails (an interior accumulator collision, say), and the executor would +/// then promise the guest a result the prover cannot produce. +/// 2. **`P1` is the generator.** `Lincomb2Witness` carries `mem_p2` but no `mem_p1` and +/// no `P1` canonicalization witness, so ECSM′ binds `a1`'s bytes to `G` by +/// construction (constant-valued MEMW reads) instead of proving membership. Without +/// this check a caller passing `P1 ≠ G` would get `status == 0`, the trace builder +/// would emit a row asserting bytes that are not there, the constraint would fail, +/// and the whole **block would become unprovable** — a completeness hole, not a +/// forgery, but one that a non-ecrecover caller could open. Returning +/// [`LINCOMB2_STATUS_P1_NOT_GENERATOR`] instead degrades that caller to the software +/// fallback and keeps executor and chip in agreement by construction. +/// +/// The `P1` operand is still read in full, so the ABI stays general: **if a `mem_p1` +/// membership witness is added later, deleting the `GENERATOR_LE` comparison below is the +/// only change needed here.** Today's only caller is the guest's ecrecover, which always +/// passes `ProjectivePoint::GENERATOR`. +pub fn lincomb2_outcome(p1: &[u8; 64], p2: &[u8; 64], u: &[u8; 64]) -> Lincomb2Outcome { + fn halves(operand: &[u8; 64]) -> ([u8; 32], [u8; 32]) { + let mut lo = [0u8; 32]; + let mut hi = [0u8; 32]; + lo.copy_from_slice(&operand[..32]); + hi.copy_from_slice(&operand[32..]); + (lo, hi) + } + fn point(x: &[u8; 32], y: &[u8; 32]) -> ecsm::AffinePoint { + ecsm::AffinePoint { + x: BigUint::from_bytes_le(x), + y: BigUint::from_bytes_le(y), + } + } + + // Checked before witness generation: it is the cheapest of the conditions and the one + // the chip's row shape depends on, so there is nothing to compute if it fails. + if *p1 != GENERATOR_LE { + return Lincomb2Outcome { + status: LINCOMB2_STATUS_P1_NOT_GENERATOR, + witness: None, + }; + } + + let (x_p1, y_p1) = halves(p1); + let (x_p2, y_p2) = halves(p2); + let (u1, u2) = halves(u); + + match ecsm::witness::lincomb2_witness(&u1, &u2, &point(&x_p1, &y_p1), &point(&x_p2, &y_p2)) { + Ok(witness) => Lincomb2Outcome { + status: LINCOMB2_STATUS_OK, + witness: Some(Box::new(witness)), + }, + Err(error) => Lincomb2Outcome { + status: lincomb2_status(&error), + witness: None, + }, + } +} + +/// Validates the four `ecsm_lincomb2` operand addresses (`a0` result, then the `a1`/`a2`/`a3` +/// inputs, in that order). +/// +/// Each 64-byte region must be 8-byte aligned, stay inside its lower 32-bit address limb, +/// and be pairwise disjoint from the other three: +/// +/// * **Alignment** — the proving side reads and writes each region as eight *aligned* +/// doubleword MEMW accesses, the same requirement the Keccak state address carries. +/// * **Limb bound** — an operand whose last byte (offset +63) crosses `2^32` would split +/// across the MEMW address limbs. This also makes `addr + 63` overflow-free in `u64`: +/// any `addr > u64::MAX - 63` has `addr % 2^32 > 2^32 - 64` and is rejected here. +/// * **Disjointness** — the chip proves one MEMW access chain per operand within a single +/// ecall; overlapping regions would touch the same address from two of those chains, +/// which the MEMW consistency argument cannot order. This is `ecsm_mul`'s +/// `EcsmOperandOverlap` rule widened to four operands. Note the result region may NOT +/// alias an input, unlike `ecsm_mul`'s `xR`: it is written after all three reads, so an +/// alias would leave the stored input bytes disagreeing with what the chip consumed. +/// +/// These are guest-program bugs, not attacker-controlled input, so they are hard errors +/// rather than a status word — see the status-contract note above. +fn lincomb2_addrs_ok(addrs: [u64; 4]) -> Result<(), ExecutionError> { + for &addr in &addrs { + if !addr.is_multiple_of(8) { + return Err(ExecutionError::Lincomb2UnalignedAddress(addr)); + } + if !ecsm_addr_ok(addr, LINCOMB2_OPERAND_BYTES - 1) { + return Err(ExecutionError::Lincomb2AddressOverflow(addr)); + } + } + for (i, &a) in addrs.iter().enumerate() { + for &b in &addrs[i + 1..] { + if a.abs_diff(b) < LINCOMB2_OPERAND_BYTES { + return Err(ExecutionError::Lincomb2OperandOverlap(a, b)); + } + } + } + Ok(()) +} + impl Instruction { /// Runs the given instruction and returns its execution log pub fn run( @@ -454,6 +673,59 @@ impl Instruction { src2_val = addr_xg; dst_val = addr_k; } + SyscallNumbers::EcsmLincomb2 => { + // ECSM lincomb2(-12): Q = u1·P1 + u2·P2 on secp256k1. + // x10 = addr to write Q, x11 = addr of P1, x12 = addr of P2, + // x13 = addr of the scalars. Every operand is 64 bytes: two + // 32-byte little-endian values back to back (xQ‖yQ, xP‖yP, + // u1‖u2). On return x10 holds the status word: 0 means Q was + // written, non-zero means Q was NOT written and the guest must + // use its software fallback. + // + // THE MEMORY ACCESS PATTERN IS THE SAME ON BOTH PATHS. All three + // operands are read, and x10 is written, whether or not a witness + // exists — only the 64-byte Q store is conditional. The proving + // side gives every lincomb2 ecall one row that receives the Ecall + // bus and performs the same fixed set of MEMW accesses; an early + // return on the degenerate path would desynchronise those + // timestamps and leave the ecall with no receiver, unbalancing the + // bus. Do not "optimize" the reads away: `lincomb2_outcome` takes + // all three operands by value precisely so the status cannot be + // decided before they have been read. + let addr_q = registers.read(10)?; + let addr_p1 = registers.read(11)?; + let addr_p2 = registers.read(12)?; + let addr_u = registers.read(13)?; + // Address faults are the one hard error here, and they abort + // before any read or write, so they never leave a partial trace. + lincomb2_addrs_ok([addr_q, addr_p1, addr_p2, addr_u])?; + + let p1 = load_u512_le(memory, addr_p1)?; + let p2 = load_u512_le(memory, addr_p2)?; + let u = load_u512_le(memory, addr_u)?; + + let outcome = lincomb2_outcome(&p1, &p2, &u); + // Q is written only on success: there is no witness to prove on + // the error path, so there must also be no bytes for the guest to + // mistake for a result. + if let Some(witness) = &outcome.witness { + store_u256_le(memory, addr_q, &witness.x_q)?; + store_u256_le(memory, addr_q + 32, &witness.y_q)?; + } + // Unconditional: the status write is what makes the error path + // expressible as a row at all. + registers.write(10, outcome.status)?; + // The three input addresses survive in x11/x12/x13 and are + // recoverable from the register state exactly as ECSM recovers + // its own, but x10 is clobbered by the status, so the CPU log + // carries both: `src2_val` = the result address, `dst_val` = + // x10's post-execution value (the status). Both are redundant + // with a trace-builder replay; they are carried because the + // fields are otherwise unused and the status saves the collector + // a witness recomputation on the error path. + src2_val = addr_q; + dst_val = outcome.status; + } SyscallNumbers::Halt => { // halt return Ok(Log { @@ -636,6 +908,12 @@ pub enum ExecutionError { EcsmOperandOverlap, #[error("ECSM scalar multiplication error: {0}")] Ecsm(#[from] ecsm::EcsmError), + #[error("ECSM lincomb2 operand address is not 8-byte aligned: {0:#018x}")] + Lincomb2UnalignedAddress(u64), + #[error("ECSM lincomb2 operand range overflows the lower 32-bit limb: {0:#018x}")] + Lincomb2AddressOverflow(u64), + #[error("ECSM lincomb2 operand ranges overlap: {0:#018x} and {1:#018x}")] + Lincomb2OperandOverlap(u64, u64), } // ============================================================================= diff --git a/executor/src/vm/logs.rs b/executor/src/vm/logs.rs index de6b73d0b..aca02f142 100644 --- a/executor/src/vm/logs.rs +++ b/executor/src/vm/logs.rs @@ -11,6 +11,13 @@ /// - `src1_val` = syscall number (from x17): 64=Commit, 93=Halt, etc. /// - `src2_val` = buf_addr (x11) for Commit, 0 otherwise /// - `dst_val` = count (x12) for Commit, 0 otherwise +/// +/// The accelerator syscalls repurpose the two spare fields further: +/// - Keccak: `src2_val` = state address (x10). +/// - ECSM: `src2_val` = addr of xG (x11), `dst_val` = addr of k (x12). +/// - ECSM lincomb2: `src2_val` = addr of the result Q (x10 *before* the call), +/// `dst_val` = the status word written back to x10. This is the one ECALL that +/// writes a register, so `dst_val` really is x10's post-execution value. #[derive(Debug, Clone)] pub struct Log { /// PC before instruction execution (use this to look up the instruction) diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 15344d138..c43ae6b12 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -20,6 +20,10 @@ crypto = { path = "../crypto/crypto" } math = { path = "../crypto/math" } executor = { path = "../executor" } ecsm = { path = "../crypto/ecsm" } +# ECDAS2 derives its non-degeneracy witness (`(xB − xA)^{-1} mod p`, its +# quotient and carries) from values `ecsm::witness` already publishes; that +# derivation needs the same 256-bit arithmetic the witness crate uses. +num-bigint = "0.4.6" rayon = { version = "1.8.0", optional = true } sysinfo = { version = "0.31", default-features = false, features = ["system"] } log = "0.4" @@ -28,6 +32,10 @@ rkyv = { version = "0.8.10", default-features = false, features = ["alloc", "byt [dev-dependencies] env_logger = "*" +# Test-only: `ec_t0_tests` recomputes the whole `-2^i·T0` table from the pinned +# T0 with its own affine doubling, independent of the k256 path the table +# generator uses, and checks every entry is on-curve. +num-bigint = "0.4.6" criterion = { version = "0.5", default-features = false } tikv-jemallocator = "0.6" tikv-jemalloc-ctl = { version = "0.6", features = ["stats"] } diff --git a/prover/src/bin/compute_static_commitments.rs b/prover/src/bin/compute_static_commitments.rs index 045e15a4c..01d510354 100644 --- a/prover/src/bin/compute_static_commitments.rs +++ b/prover/src/bin/compute_static_commitments.rs @@ -1,7 +1,8 @@ -//! Prints static `(bitwise, keccak_rc, zero_page)` preprocessed-table commitments -//! for a fixed set of `blowup_factor` values. The output is pasted into the -//! `static_commitment` match bodies in `prover/src/tables/{bitwise,keccak_rc}.rs` -//! and the `static_zero_page_commitment` match body in `prover/src/tables/page.rs`. +//! Prints static `(bitwise, keccak_rc, ec_t0, zero_page)` preprocessed-table +//! commitments for a fixed set of `blowup_factor` values. The output is pasted +//! into the `static_commitment` match bodies in +//! `prover/src/tables/{bitwise,keccak_rc,ec_t0}.rs` and the +//! `static_zero_page_commitment` match body in `prover/src/tables/page.rs`. //! The `static_commitments_tests` test suite pins the values so any drift in //! the AIR or FFT pipeline is caught at test time. //! @@ -10,10 +11,10 @@ //! //! ⚠️ Do not run this just to silence a failing drift test — see the //! "Regenerating" section on `static_commitment` in `bitwise.rs` / -//! `keccak_rc.rs` and `static_zero_page_commitment` in `page.rs` for when -//! it's actually appropriate to bless new bytes. +//! `keccak_rc.rs` / `ec_t0.rs` and `static_zero_page_commitment` in `page.rs` +//! for when it's actually appropriate to bless new bytes. -use lambda_vm_prover::tables::{STATIC_BLOWUP_FACTORS, bitwise, keccak_rc, page}; +use lambda_vm_prover::tables::{STATIC_BLOWUP_FACTORS, bitwise, ec_t0, keccak_rc, page}; use stark::config::Commitment; use stark::proof::options::GoldilocksCubicProofOptions; @@ -36,7 +37,7 @@ fn format_commitment(commitment: &Commitment) -> String { fn main() { println!( "// Paste these match arms into the `static_commitment` match bodies\n\ - // in `prover/src/tables/{{bitwise,keccak_rc}}.rs` and the\n\ + // in `prover/src/tables/{{bitwise,keccak_rc,ec_t0}}.rs` and the\n\ // `static_zero_page_commitment` match body in `prover/src/tables/page.rs`.\n" ); @@ -53,6 +54,7 @@ fn main() { let bitwise = bitwise::compute_preprocessed_commitment(&options); let keccak_rc = keccak_rc::compute_preprocessed_commitment(&options); + let ec_t0 = ec_t0::compute_preprocessed_commitment(&options); let zero_page = page::compute_precomputed_commitment(&zero_page_config, &options); println!( @@ -61,10 +63,13 @@ fn main() { {blowup} => Some({bitwise_fmt}),\n\ // ---- keccak_rc:\n \ {blowup} => Some({keccak_fmt}),\n\ + // ---- ec_t0:\n \ + {blowup} => Some({ec_t0_fmt}),\n\ // ---- zero_page:\n \ {blowup} => Some({zero_page_fmt}),\n", bitwise_fmt = format_commitment(&bitwise), keccak_fmt = format_commitment(&keccak_rc), + ec_t0_fmt = format_commitment(&ec_t0), zero_page_fmt = format_commitment(&zero_page), ); } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index ff9601bb4..0fad6cb0b 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -52,11 +52,12 @@ use crate::tables::trace_builder::count_table_lengths; use crate::tables::types::BusId; use crate::test_utils::{ E, F, VmAir, create_bitwise_air, create_branch_air, create_bytewise_air, create_commit_air, - create_cpu_air, create_cpu32_air, create_decode_air, create_dvrm_air, create_ecdas_air, - create_ecsm_air, create_eq_air, create_halt_air, create_keccak_air, create_keccak_rc_air, - create_keccak_rnd_air, create_load_air, create_lt_air, create_memw_air, - create_memw_aligned_air, create_memw_register_air, create_mul_air, create_page_air, - create_register_air, create_shift_air, create_store_air, + create_cpu_air, create_cpu32_air, create_decode_air, create_dvrm_air, create_ec_t0_air, + create_ecdas_air, create_ecdas2_air, create_ecsm_air, create_ecsm2_air, create_eq_air, + create_halt_air, create_keccak_air, create_keccak_rc_air, create_keccak_rnd_air, + create_load_air, create_lt_air, create_memw_air, create_memw_aligned_air, + create_memw_register_air, create_mul_air, create_page_air, create_register_air, + create_shift_air, create_store_air, }; // Re-exported for downstream hosts and verifier guests (e.g. the in-VM @@ -82,8 +83,8 @@ pub struct RuntimePageRange { /// Number of tables that always contribute exactly one sub-proof, regardless /// of `TableCounts`: bitwise, decode, halt, commit, keccak, keccak_rnd, -/// keccak_rc, register, ecsm, ecdas. -pub const FIXED_TABLE_COUNT: usize = 10; +/// keccak_rc, register, ecsm, ecdas, ecsm2, ecdas2, ec_t0. +pub const FIXED_TABLE_COUNT: usize = 13; /// Number of chunks for each split table. /// The verifier needs this to reconstruct matching AIRs. @@ -503,6 +504,12 @@ pub(crate) struct VmAirs { pub keccak_rc: VmAir, pub ecsm: VmAir, pub ecdas: VmAir, + /// ECSM2: the lincomb2 (`Q = u1·P1 + u2·P2`) orchestrator. + pub ecsm2: VmAir, + /// ECDAS2: one step of the lincomb2 joint double-add chain. + pub ecdas2: VmAir, + /// EC_T0: preprocessed `−2^len·T₀` table for the lincomb2 correction row. + pub ec_t0: VmAir, pub register: VmAir, pub pages: Vec, pub memw_registers: Vec, @@ -528,6 +535,9 @@ impl VmAirs { (self.keccak_rc.as_ref(), &mut traces.keccak_rc, &()), (self.ecsm.as_ref(), &mut traces.ecsm, &()), (self.ecdas.as_ref(), &mut traces.ecdas, &()), + (self.ecsm2.as_ref(), &mut traces.ecsm2, &()), + (self.ecdas2.as_ref(), &mut traces.ecdas2, &()), + (self.ec_t0.as_ref(), &mut traces.ec_t0, &()), (self.register.as_ref(), &mut traces.register, &()), ]; if self.include_halt { @@ -602,6 +612,9 @@ impl VmAirs { self.keccak_rc.as_ref(), self.ecsm.as_ref(), self.ecdas.as_ref(), + self.ecsm2.as_ref(), + self.ecdas2.as_ref(), + self.ec_t0.as_ref(), self.register.as_ref(), ]; if self.include_halt { @@ -759,6 +772,12 @@ impl VmAirs { )); let ecsm: VmAir = Box::new(create_ecsm_air(proof_options)); let ecdas: VmAir = Box::new(create_ecdas_air(proof_options)); + let ecsm2: VmAir = Box::new(create_ecsm2_air(proof_options)); + let ecdas2: VmAir = Box::new(create_ecdas2_air(proof_options)); + let ec_t0: VmAir = Box::new(create_ec_t0_air(proof_options).with_preprocessed( + tables::ec_t0::preprocessed_commitment(proof_options), + tables::ec_t0::NUM_PRECOMPUTED_COLS, + )); let register: VmAir = if let Some((commitment, num_preprocessed_cols)) = register_preprocessed { Box::new( @@ -865,6 +884,9 @@ impl VmAirs { keccak_rc, ecsm, ecdas, + ecsm2, + ecdas2, + ec_t0, register, pages, memw_registers, @@ -1034,6 +1056,43 @@ pub fn count_elements(elf_bytes: &[u8], private_inputs: &[u8]) -> Result<(u64, u )) } +/// The same counts as [`count_elements`], broken down per table. +/// +/// Returns `(table_name, main_elements, aux_elements)` per table, in a fixed +/// order. The two columns sum to exactly what [`count_elements`] returns — they +/// share one implementation (`Traces::field_elements_by_table`), so the +/// breakdown and the totals cannot drift apart. +/// +/// Split tables (CPU, MEMW, …) appear once, summed over their chunks: a chunk +/// boundary is an artefact of `MaxRowsConfig`, not something a caller wants to +/// see. Preprocessed columns are excluded from the main count, matching +/// [`count_elements`]. +/// +/// The motivating use is measuring one component's **share** of a real +/// workload's prover cells — e.g. what fraction of an ethrex block is EC work, +/// which is the multiplier that converts a per-operation win into a +/// whole-prover number. +pub fn count_elements_by_table( + elf_bytes: &[u8], + private_inputs: &[u8], +) -> Result, Error> { + let program = Elf::load(elf_bytes).map_err(|e| Error::ElfLoad(format!("{e}")))?; + let executor = Executor::new(&program, private_inputs.to_vec()) + .map_err(|e| Error::Execution(format!("{e}")))?; + let result = executor + .run() + .map_err(|e| Error::Execution(format!("{e}")))?; + let traces = Traces::from_elf_and_logs( + &program, + &result.logs, + &MaxRowsConfig::default(), + private_inputs, + #[cfg(feature = "disk-spill")] + StorageMode::Ram, + )?; + Ok(traces.field_elements_by_table()) +} + /// Prove an ELF binary execution with custom proof options and max rows config. pub fn prove_with_options( elf_bytes: &[u8], diff --git a/prover/src/tables/cpu.rs b/prover/src/tables/cpu.rs index 781bb02b0..0b559534e 100644 --- a/prover/src/tables/cpu.rs +++ b/prover/src/tables/cpu.rs @@ -188,6 +188,15 @@ pub struct CpuOperation { /// Whether this ECALL is an ECSM (elliptic-curve scalar multiply) syscall pub ecall_ecsm: bool, + + /// Whether this ECALL is an ECSM `lincomb2` syscall (`Q = u1·P1 + u2·P2`). + pub ecall_lincomb2: bool, + /// For lincomb2 ECALLs: the result address `a0`, carried in the log because + /// x10 is clobbered by the status word on return. + pub lincomb2_addr_q: u64, + /// For lincomb2 ECALLs: the status word left in x10. Redundant with the + /// trace builder's replay, and asserted against it. + pub lincomb2_status: u64, } impl CpuOperation { @@ -235,6 +244,16 @@ impl CpuOperation { // in the trace builder. let ecall_ecsm = f.ecall && log.src1_val == executor::vm::instruction::execution::ECSM_SYSCALL_NUMBER; + // lincomb2's operand addresses live in x11/x12/x13 and are recovered from + // the register state, but x10 is overwritten with the status word before + // the trace builder runs, so the result address rides `src2_val`. + let ecall_lincomb2 = f.ecall + && log.src1_val == executor::vm::instruction::execution::ECSM_LINCOMB2_SYSCALL_NUMBER; + let (lincomb2_addr_q, lincomb2_status) = if ecall_lincomb2 { + (log.src2_val, log.dst_val) + } else { + (0, 0) + }; // Word instructions are fully handled by CPU32; the main CPU row is a // delegate that only advances the PC and sends the CPU32 lookup. We still @@ -353,6 +372,9 @@ impl CpuOperation { ecall_keccak, keccak_state_addr, ecall_ecsm, + ecall_lincomb2, + lincomb2_addr_q, + lincomb2_status, } } diff --git a/prover/src/tables/ec_t0.rs b/prover/src/tables/ec_t0.rs new file mode 100644 index 000000000..81f03eb62 --- /dev/null +++ b/prover/src/tables/ec_t0.rs @@ -0,0 +1,369 @@ +//! EC_T0: preprocessed lookup table of the lincomb2 NUMS correction constants. +//! +//! Exactly 256 rows, every one of them real — there is no padding. Row `j` +//! carries `LEN_M1 = j` and the blinding point for schedule length +//! `len = j + 1`: +//! +//! ```text +//! row j = ( j, x(2^(j+1)·T₀), y(−2^(j+1)·T₀) ) j ∈ [0, 255] +//! ``` +//! +//! The joint chain seeds its accumulator with the nothing-up-my-sleeve point +//! `T₀` (`ecsm::witness::t0`), so after `len` doublings the accumulator carries +//! a blind of `2^len·T₀`. The chain's last row strips it by adding +//! `−2^len·T₀`; it gets that addend by looking up this table on the `EcT0` bus. +//! +//! # Sign convention: the y column holds the NEGATED coordinate +//! +//! `Y` is `y(−2^len·T₀) = p − y(2^len·T₀)`, **not** `y(2^len·T₀)`. This is not +//! a preference — it is what `ecsm::witness::lincomb2_witness` emits. Its +//! `JointSel::Correction` row builds `neg_tpow` by negating the blind's `y` and +//! passes it as the row's *addend*, which `build_step` writes into the step's +//! `(x_g, y_g)`. Storing the negation therefore lets the consumer chip wire a +//! table lookup straight into its addend columns with no in-circuit modular +//! negation. `ecsm::tests::lincomb2_table_tests` asserts the match against real +//! witnesses; `ec_t0_tests::table_matches_lincomb2_witness_correction_row` +//! re-asserts it against the committed columns of this table. +//! +//! ## ⚠️ The witness carries the OPPOSITE convention in a second place +//! +//! `Lincomb2Witness::x_t0_pow` / `y_t0_pow` (`witness.rs:936-937` at the time of +//! writing) hold the **positive** `2^len·T₀` — not the negation this table +//! stores. Only `y` differs, since `x(−P) = x(P)`: +//! +//! ```text +//! x_t0_pow == this table's X (identical, no conversion) +//! y_t0_pow == p − this table's Y (a modular negation apart) +//! ``` +//! +//! A consumer that binds its correction addend from this table does **not** +//! need `y_t0_pow` at all. Reading `y_t0_pow` where you meant `Y` is a silent +//! sign flip that still type-checks — do not mix them. +//! +//! # Why no consumer range check is needed +//! +//! The key column stores `len − 1`, and the bus receive re-adds the 1 +//! (`LinearTerm::Constant(1)` in [`bus_interactions`]). So the tuple the +//! receiver publishes spans exactly `len ∈ [1, 256]`, with one row per value +//! and nothing else in the table. A send at `len = 0` or `len > 256` matches no +//! row, so the LogUp argument cannot balance and the proof is rejected — the +//! bound holds **by construction**. +//! +//! That range is also exactly the reachable one: +//! `len = max(u1.bits(), u2.bits())` (`witness.rs:830`) with both scalars +//! non-zero (`witness.rs:801-802` rejects `ScalarIsZero`) and `< N < 2^256`, +//! so `len ∈ [1, 256]` and `LEN_M1` fills a byte with no unreachable row. +//! +//! **Do not add a `len ≤ 256` check to the consumer chip** — it would be +//! redundant with the lookup itself. An earlier draft of this table keyed by +//! `len` directly over 257 rows padded to 512, which *did* need such a check, +//! because a send at `len > 256` would have resolved to a zeroed padding row +//! holding the off-curve point `(0, 0)`. The `LEN_M1` encoding removes both the +//! padding and the obligation. +//! +//! Follows the KECCAK_RC preprocessed-table pattern: precomputed columns are +//! committed via a static lookup table (with recompute as fallback for +//! `ProofOptions` not covered by the static table). + +use std::sync::LazyLock; + +use math::polynomial::Polynomial; +use stark::commitment::{ROWS_PER_LEAF, commit_bit_reversed}; +use stark::config::Commitment; +use stark::lookup::{BusInteraction, BusValue, LinearTerm, Multiplicity}; +use stark::proof::options::ProofOptions; +use stark::prover::evaluate_polynomial_on_lde_domain; +use stark::trace::TraceTable; + +use ecsm::lincomb2_table::neg_t0_pow2_points; +use ecsm::to_le_32; + +use super::ecsm::point_coord_busvalues; +use super::types::{BusId, FE, GoldilocksExtension, GoldilocksField, VmTable}; + +// ========================================================================= +// Column indices +// ========================================================================= + +pub mod cols { + /// `len − 1`, the row index. A byte: `len ∈ [1, 256] ⇒ LEN_M1 ∈ [0, 255]`. + /// The bus receive re-adds the 1 (see [`super::bus_interactions`]). + pub const LEN_M1: usize = 0; + /// `x(2^(LEN_M1+1)·T₀)`, 32 little-endian bytes. + pub const X: usize = 1; + pub const X_END: usize = X + 32; // = 33 + /// `y(−2^(LEN_M1+1)·T₀) = p − y(2^(LEN_M1+1)·T₀)`, 32 little-endian bytes. + pub const Y: usize = X_END; + pub const Y_END: usize = Y + 32; // = 65 + /// Multiplicity (how many times this row is looked up). + pub const MU: usize = Y_END; + + pub const NUM_COLUMNS: usize = 66; +} + +/// Number of precomputed columns (everything except MU). +pub const NUM_PRECOMPUTED_COLS: usize = 65; + +/// Smallest schedule length the table defines. +pub const MIN_LEN: usize = 1; + +/// Largest schedule length the table defines. +pub const MAX_LEN: usize = 256; + +/// Rows in the trace. Every row is real — `MAX_LEN − MIN_LEN + 1` is already a +/// power of two, so the table needs no padding and a lookup can only ever +/// resolve to a genuine curve point. +pub const NUM_ROWS: usize = MAX_LEN - MIN_LEN + 1; // 256 + +/// Whether this table is preprocessed. +pub const fn is_preprocessed() -> bool { + true +} + +/// All `NUM_ROWS` precomputed rows, built once. +/// +/// The constants come from [`neg_t0_pow2_points`] — a deterministic doubling +/// chain off the pinned `T₀`, so this is a constant table in every sense that +/// matters; it is merely computed rather than transcribed. That helper is +/// indexed by the exponent `i` (entry `i` = `−2^i·T₀`), so row `j` takes entry +/// `j + MIN_LEN`; entry 0 (`−T₀`, the chain's anchor) is unreachable as a +/// schedule length and has no row. +static ROWS: LazyLock> = LazyLock::new(|| { + let points = neg_t0_pow2_points(); + assert!( + points.len() > MAX_LEN, + "EC_T0: constant chain too short ({} entries, need {} to reach len={MAX_LEN})", + points.len(), + MAX_LEN + 1, + ); + (0..NUM_ROWS) + .map(|idx| { + let mut row = [0u64; NUM_PRECOMPUTED_COLS]; + row[cols::LEN_M1] = idx as u64; + let pt = &points[idx + MIN_LEN]; + for (i, b) in to_le_32(&pt.x).iter().enumerate() { + row[cols::X + i] = *b as u64; + } + for (i, b) in to_le_32(&pt.y).iter().enumerate() { + row[cols::Y + i] = *b as u64; + } + row + }) + .collect() +}); + +/// Generate one precomputed row: `[len − 1, x[0..32], y_neg[0..32]]`. +pub fn generate_row(idx: usize) -> [u64; NUM_PRECOMPUTED_COLS] { + ROWS[idx] +} + +// ========================================================================= +// Preprocessed commitment +// ========================================================================= + +/// Returns the static EC_T0 preprocessed commitment for `blowup_factor`, or +/// `None` if no value is shipped for it. Values were generated by the +/// `compute_static_commitments` binary at the project's standard +/// `coset_offset = 3` (the value every in-tree `ProofOptions` constructor +/// pins) and pinned by the `ec_t0_static_matches_recompute_*` test so any +/// drift in the AIR, in `T₀`, or in the FFT pipeline is caught at test time. +/// The verifier reads these from its compiled binary — no input data is +/// trusted. +/// +/// # Regenerating +/// +/// Only regenerate these match arms after a *deliberate, reviewed* change to +/// the EC_T0 table layout, the AIR's preprocessed column count, the pinned +/// `T₀`, or the FFT / LDE / Merkle pipeline. Run: +/// +/// ```text +/// cargo run --bin compute_static_commitments --release +/// ``` +/// +/// and paste the printed match arms over the ones below. +/// +/// **If a drift test failed, do not regenerate first.** The drift tests exist +/// to force a human to ask "why did this change?" before the new bytes get +/// blessed. Re-pasting on a drift failure silently launders an unintended +/// change to the NUMS blinding constants into the verifier's compiled-in trust +/// anchor. +fn static_commitment(blowup_factor: u8) -> Option { + match blowup_factor { + 2 => Some([ + 0x8e, 0x6a, 0xa6, 0x11, 0x05, 0x57, 0x36, 0x2e, 0x32, 0xc8, 0x2f, 0xc4, 0x25, 0x1d, + 0xfd, 0x33, 0x5a, 0xa4, 0x93, 0x3a, 0x84, 0xde, 0xc5, 0x95, 0x23, 0xae, 0x7c, 0x66, + 0x3f, 0xd5, 0xb6, 0x4d, + ]), + 4 => Some([ + 0xe7, 0xdf, 0x42, 0x22, 0x59, 0xfa, 0xef, 0x01, 0x80, 0x34, 0xaa, 0x04, 0xfa, 0xcf, + 0x27, 0x64, 0x21, 0x4b, 0x0a, 0x2f, 0xd4, 0x74, 0x94, 0x65, 0x80, 0x6b, 0x16, 0xee, + 0x74, 0x47, 0x78, 0x1e, + ]), + 8 => Some([ + 0x4b, 0xc4, 0x57, 0x2d, 0xb0, 0xad, 0x11, 0x7f, 0xe8, 0xdd, 0x49, 0x39, 0xbc, 0x01, + 0x0e, 0x12, 0x5e, 0x53, 0xc7, 0x71, 0xb5, 0xdc, 0x99, 0x41, 0x0a, 0xf3, 0xec, 0x16, + 0x14, 0xd6, 0x2d, 0x1f, + ]), + _ => None, + } +} + +/// Exposed for the `compute_static_commitments` binary and the +/// drift-detection tests in `static_commitments_tests`. Production callers +/// should go through [`preprocessed_commitment`] so the static const-table +/// shortcut is used when applicable. +#[doc(hidden)] +pub fn compute_preprocessed_commitment(options: &ProofOptions) -> Commitment { + // Generate precomputed columns + let mut columns: Vec> = (0..NUM_PRECOMPUTED_COLS) + .map(|_| Vec::with_capacity(NUM_ROWS)) + .collect(); + for idx in 0..NUM_ROWS { + let row = generate_row(idx); + for (col_idx, &value) in row.iter().enumerate() { + columns[col_idx].push(FE::from(value)); + } + } + + // Interpolate each column to a polynomial + let polys: Vec> = columns + .iter() + .map(|col| { + Polynomial::interpolate_fft::(col) + .expect("FFT interpolation failed for ec_t0 column") + }) + .collect(); + + // Evaluate on LDE domain + let blowup_factor = options.blowup_factor as usize; + let coset_offset = FE::from(options.coset_offset); + let lde_columns: Vec> = polys + .iter() + .map(|poly| { + evaluate_polynomial_on_lde_domain(poly, blowup_factor, NUM_ROWS, &coset_offset) + .expect("LDE evaluation failed for ec_t0 polynomial") + }) + .collect(); + + let (_, root) = commit_bit_reversed(&lde_columns, ROWS_PER_LEAF) + .expect("Failed to build Merkle tree for ec_t0 LDE"); + root +} + +/// Returns the preprocessed commitment for the EC_T0 table. +/// +/// Looks up `blowup_factor` via [`static_commitment`] when `coset_offset == 3` +/// (the value every in-tree `ProofOptions` constructor pins, and the offset +/// the static bytes were generated for); on miss — either a non-3 coset or a +/// `blowup_factor` outside `STATIC_BLOWUP_FACTORS` — recomputes from scratch. +#[inline] +pub fn preprocessed_commitment(options: &ProofOptions) -> Commitment { + if options.coset_offset == 3 + && let Some(commitment) = static_commitment(options.blowup_factor) + { + return commitment; + } + log::warn!( + "ec_t0 preprocessed commitment not static for (blowup={}, coset={}); \ + falling back to recompute. Add a match arm to `static_commitment` by running \ + `cargo run --bin compute_static_commitments --release`.", + options.blowup_factor, + options.coset_offset, + ); + compute_preprocessed_commitment(options) +} + +// ========================================================================= +// Trace generation +// ========================================================================= + +/// Generate the EC_T0 trace table. +/// +/// All precomputed columns are filled; MU is initialized to zero and must be +/// updated via [`update_multiplicities`] once every correction-row lookup is +/// known. +pub fn generate_ec_t0_trace() -> TraceTable { + let mut trace = TraceTable::new_main( + crate::tables::types::zeroed_fe_vec(NUM_ROWS * cols::NUM_COLUMNS), + cols::NUM_COLUMNS, + 1, + ); + let table = &mut trace.main_table; + + for idx in 0..NUM_ROWS { + let row = generate_row(idx); + for (col_idx, &value) in row.iter().enumerate() { + table.set_u64(idx, col_idx, value); + } + // MU = 0 (will be updated later) + } + + trace +} + +/// Set MU from the `len` of every lincomb2 correction row in the proof. +/// +/// Takes schedule lengths (`len`, not `len − 1`) and writes row `len − 1`, so +/// callers work in the same units as `Lincomb2Witness::len`. Each lincomb2 +/// evaluation performs exactly one lookup, so `MU[len − 1]` is the number of +/// evaluations that used that schedule length. +/// +/// Panics outside `[MIN_LEN, MAX_LEN]`. The lookup already enforces that range +/// on the proof side ("Why no consumer range check is needed" in the module +/// header), so this is a witness-side backstop: it turns a malformed schedule +/// into a loud failure here rather than an unbalanced bus much later. +pub fn update_multiplicities( + trace: &mut TraceTable, + lens: impl IntoIterator, +) { + let mut counts = vec![0u64; NUM_ROWS]; + for len in lens { + let len = len as usize; + assert!( + (MIN_LEN..=MAX_LEN).contains(&len), + "EC_T0: correction lookup at len={len} outside [{MIN_LEN}, {MAX_LEN}]", + ); + counts[len - MIN_LEN] += 1; + } + for (idx, count) in counts.iter().enumerate() { + if *count != 0 { + trace.main_table.set_u64(idx, cols::MU, *count); + } + } +} + +// ========================================================================= +// Bus interactions +// ========================================================================= + +/// Single receiver on the EcT0 bus. +/// +/// Format: `[len, x[0..32](Direct), y_neg[0..32](Direct)]` — 65 elements. +/// +/// The key element is `LEN_M1 + 1`, so the consumer sends a plain `len` and +/// never has to know about the `−1` storage encoding. Because `LEN_M1` spans +/// `[0, 255]` across the 256 rows and there are no other rows, the published +/// keys are exactly `[1, 256]` — which is what makes the range bound hold by +/// construction rather than by a consumer-side check. +/// +/// Coordinates ride the bus as 32 individual byte elements, the same shape +/// ECSM/ECDAS use for every point tuple ([`point_coord_busvalues`]), so the +/// consumer's addend columns inherit byte-ness from these committed constants +/// through plain tuple equality. +pub fn bus_interactions() -> Vec { + let mut values = vec![BusValue::linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: cols::LEN_M1, + }, + LinearTerm::Constant(1), + ])]; + values.extend(point_coord_busvalues(cols::X)); + values.extend(point_coord_busvalues(cols::Y)); + + vec![BusInteraction::receiver( + BusId::EcT0, + Multiplicity::Column(cols::MU), + values, + )] +} diff --git a/prover/src/tables/ecdas.rs b/prover/src/tables/ecdas.rs index ff0c41f84..eb656fc7c 100644 --- a/prover/src/tables/ecdas.rs +++ b/prover/src/tables/ecdas.rs @@ -171,23 +171,34 @@ pub fn bus_interactions() -> Vec { ), )); - // IS_BYTE range checks (single byte → AreBytes[x, 0]). - let is_byte = |col: usize, len: usize, out: &mut Vec| { - for i in 0..len { - out.push(BusInteraction::sender( - BusId::AreBytes, - Multiplicity::Column(cols::MU), - vec![packed(col + i), BusValue::constant(0)], - )); - } + // ARE_BYTES range checks, paired: `ARE_BYTES[X, Y]` checks BOTH elements + // (bitwise.rs `generate_bitwise_row` enumerates every (x, y) byte pair), so + // adjacent bytes share one send — 196 single-byte `[b, 0]` sends become 98. + // Layout: the 32-byte prefixes of LAMBDA, XR, YR, Q0, Q1, Q2 pair internally + // as (2i, 2i+1); the four odd bytes pair as (ROUND, Q0[32]) and + // (Q1[32], Q2[32]). `collect_bitwise_from_ecdas` mirrors this layout exactly + // (sends and BITWISE multiplicities must move together). + let pair = |col_x: usize, col_y: usize, out: &mut Vec| { + out.push(BusInteraction::sender( + BusId::AreBytes, + Multiplicity::Column(cols::MU), + vec![packed(col_x), packed(col_y)], + )); }; - is_byte(cols::ROUND, 1, &mut out); - is_byte(cols::LAMBDA, 32, &mut out); - is_byte(cols::Q0, 33, &mut out); - is_byte(cols::XR, 32, &mut out); - is_byte(cols::Q1, 33, &mut out); - is_byte(cols::YR, 32, &mut out); - is_byte(cols::Q2, 33, &mut out); + for base in [ + cols::LAMBDA, + cols::XR, + cols::YR, + cols::Q0, + cols::Q1, + cols::Q2, + ] { + for i in 0..16 { + pair(base + 2 * i, base + 2 * i + 1, &mut out); + } + } + pair(cols::ROUND, cols::Q0 + 32, &mut out); + pair(cols::Q1 + 32, cols::Q2 + 32, &mut out); // IS_HALF range checks on the carries (offsets keep them in [0, 2^16)). let half = |col: usize, off: i64| { diff --git a/prover/src/tables/ecdas2.rs b/prover/src/tables/ecdas2.rs new file mode 100644 index 000000000..baa641eea --- /dev/null +++ b/prover/src/tables/ecdas2.rs @@ -0,0 +1,1025 @@ +//! ECDAS2 chip — one step of the lincomb2 joint (Shamir/Straus) double-add chain. +//! +//! The joint sibling of [`ecdas`](super::ecdas). Its λ/xR/yR convolution core is +//! **byte-for-byte** the same machinery (same quotients `q0/q1/q2`, same 64-entry +//! carry arrays with the same offsets, same shifted-quotient `r = 3p` term), and +//! the witness reuses `ecsm::witness::build_step` unchanged to produce it. What +//! differs: +//! +//! * a **fourth relation** proving the addition is non-degenerate (see below); +//! * the addend `(XB, YB)` varies per row and arrives on the [`Addend`](BusId::Addend) +//! bus instead of being a loop-invariant generator carried in the chain tuple; +//! * the chain is split into three separately-keyed **phases** so the two rows +//! that break the `a = prev.r` telescoping cannot be confused with main-chain +//! rows (both are emitted at `round = 0`, which the main loop also produces); +//! * two scalar-digit streams are counted instead of one. +//! +//! ## The non-degeneracy relation `D_INV·(xB − xA) ≡ 1 (mod p)` +//! +//! **This is the check that makes the chip sound, and it is unconditional — it +//! rests on no computational assumption.** +//! +//! When `xB = xA` the λ relation `Σλ(xB − xA) + yA − yB` degenerates: with +//! `yB = yA` it reads `0 = 0` for *every* λ, so `xR = λ² − xA − xB` and +//! `yR = λ(xA − xR) − yA` produce a point of the prover's choosing that the rest +//! of the chain then accepts. Everything downstream — the Addend balance, the +//! digit counting, the phase pinning — is satisfied. The row proves nothing. +//! +//! DESIGN §4 argued the NUMS blind `T₀` closes this by making a collision imply +//! a known linear relation on `dlog_G(T₀)`. **That argument does not hold, and +//! the edge is cheaply reachable.** The prover chooses `P2` — for ecrecover it is +//! `lift_x(r)` and `r` is free signature bytes — so setting `P2 = μ·T₀` cancels +//! `T₀`'s coefficient and leaves a collision condition solvable with *no* +//! knowledge of `dlog(T₀)`: with `P1 = G` and `u1 = 1` it reduces to +//! `μ·(c2 − 1) ≡ −2^j (mod N)`, one modular inversion. Verified 5/5 over +//! `len ∈ {8, 12, 16, 32, 256}`, each packaged as a well-formed `(z, v, r, s)` +//! (`thoughts/ec-recover-opt/oracle/nums_blinding_probe.py`, +//! `thoughts/ec-recover-opt/lincomb2/FINDING-nums-blinding.log`). The blind made +//! the edge *easier* to aim at than the unblinded chain's ~2^−j search. +//! +//! Phase A is unaffected: `lincomb2_witness` rejects all of these with +//! `ResultInfinity` (status ≠ 0 ⇒ guest fallback). The forgery lives entirely on +//! the malicious-prover side, where the row never passes through the witness +//! generator, so **only this constraint catches it**. +//! +//! The blind survives for a different, non-soundness reason: it lets any +//! `len ∈ [max_msb + 1, 256]` yield the correct `Q`, which is what drops the +//! exact-MSB sub-lemma. It is a convenience, not a defence — do not describe it +//! as one. +//! +//! The relation is gated to rows that actually consume an addend — the same +//! `S1 + S2 + S3 + S_CORR` sum as the Addend receive, so the precompute and +//! correction rows (both chord adds) are covered and doublings are not. Gating is +//! a cost choice rather than a correctness one: `x = 0` is not on secp256k1 +//! (`7` is a non-residue mod `p`), so `xB − xA = −xA` would be invertible on +//! doublings too — but there is no addend there, so the cells would be wasted. +//! +//! ## Phases +//! +//! `PHASE = PH1 + 2·PH2` rides the chain tuple. ECSM2 pins every segment at both +//! ends, at multiplicity `OK`: +//! +//! | phase | rows | seeded with | drained to | +//! |---|---|---|---| +//! | 0 precompute | exactly 1 | `a = P1 = G`, addend `P2` | `X_P12/Y_P12` | +//! | 1 main chain | `len` doubles + their adds | `a = T₀`, `round = LEN_M1` | `ACC_X/ACC_Y` | +//! | 2 correction | exactly 1 | `a = ACC`, addend `−2^len·T₀` | `X_Q/Y_Q` | +//! +//! The phase-1 → phase-2 hand-off deliberately goes **through ECSM2** (drain then +//! re-send on the same columns) rather than along the chain: the outgoing tuple +//! pins the successor's `op` to this row's `NB`, and the last main row has +//! `NB = 0` while the correction row is an add (`op = 1`), so a direct hand-off +//! is not expressible. +//! +//! ## Round bookkeeping +//! +//! A doubling and its optional add share a `round`, so the successor round is +//! `round − 1 + NB` and the successor `op` is `NB` — exactly the `NEXT_OP` +//! mechanism of the single-scalar chain (`ecdas.rs`), under the joint name +//! `nb` ("an add follows me at this round"). Its two defining constraints are +//! op-gated: an add row carries its round's real digits (it needs them to pick +//! the addend) but always has `NB = 0`. +//! +//! ## Why double rows may carry a zero addend +//! +//! On `OP = 0` **no** convolution constraint reads `XB`/`YB`: in the λ relation +//! every occurrence sits inside the `op·(…)` product; in the xR relation the +//! `−xg(i)` cancels exactly against the `+xg(i)` released by `−(1−op)(xa−xg)`; +//! the yR relation never mentions them; and the non-degeneracy relation's whole +//! `d·(xB − xA)` term sits inside its `ΣS` gate, which `OP = ΣS` pins to zero. +//! So the addend columns are zero on doublings and the `Addend` receive stays +//! silent — but only because `OP = S1 + S2 + S3 + S_CORR` forces every selector +//! to zero there. Without that constraint the cancellation is still real and the +//! *gating* is forgeable: a prover would set `S2 = 1` on a doubling and mint a +//! spurious receive. +//! +//! ## Padding +//! +//! Padding rows are all-zero (including `OP = 0`, unlike `ecdas.rs` which pads +//! with `OP = 1`). All four relations then close at zero carries: the `μ`-gated +//! `R·P` term vanishes and every byte limb is zero. Keeping `OP = 0` lets +//! `OP = ΣS` stay an ungated degree-1 constraint. +//! +//! A padding row must also be inert on every *bus*, and "the columns are zero as +//! generated" is **not** an argument — a malicious prover fills padding rows +//! freely. The question to ask of each interaction is not "is it gated?" but +//! "which column supplies its multiplicity, and what forces that column to +//! zero?": +//! +//! | interaction | multiplicity | inert because | +//! |---|---|---| +//! | `Ecdas` receive + send | `MU` | by construction | +//! | 131 `AreBytes`, 252 `IsHalfword` | `MU` | by construction | +//! | `Addend` receive | `S1 + S2 + S3 + S_CORR` — **raw columns** | idx 24..=27 | +//! | 2 `JointBit` sends | `D1` / `D2` — **raw columns** | idx 22, 23 | +//! +//! The bottom two rows are where the live hole was: `(1 − MU)·{D1, D2, S1, S2, +//! S3, S_CORR} = 0` is what closes it, and idx 22..=27 writes out both forgeries +//! in full. Note that `NB` needs no companion — with every selector zero, +//! `OP = ΣS` forces `OP = 0` and idx 13 then reads `NB = D1 ∨ D2 = 0`. + +use stark::lookup::{BusInteraction, BusValue, LinearTerm, Multiplicity, Packing}; +use stark::trace::TraceTable; + +use super::types::{BusId, FE, GoldilocksExtension, GoldilocksField, VmTable}; +use ecsm::P_BYTES; +use ecsm::witness::{JointSel, JointStep}; + +pub(crate) use ecsm::R_BYTES; + +// Bias signed convolution carries into IsHalfword [0, 2^16). Identical to +// `ecdas.rs`: the relations, and therefore the carry ranges, are the same. +pub(crate) use super::ecdas::{CARRY_OFFSET_LAMBDA, CARRY_OFFSET_XR, CARRY_OFFSET_YR}; + +/// Carry bias for the non-degeneracy relation. It needs no window of its own: +/// its honest carries measure `[-581, 6041]` (`WIDTH-AUDIT.md` §4, 6,346 real +/// rows) and its worst-case soundness magnitude is the *smallest* of the four +/// relations, so `CARRY_OFFSET_XR`'s window `[-8161, 57374]` holds it with an +/// order of magnitude of slack. Named separately only so the use sites read. +pub(crate) const CARRY_OFFSET_DINV: i64 = CARRY_OFFSET_XR; + +/// Worst-case joint-chain rows for one lincomb2 evaluation. +/// +/// `1 precompute + 256 doublings + 256 adds + 1 correction`. Reached at +/// `(u1, u2) = (2^255, 2^255 − 1)`: both lie in `[1, N)` and their bit patterns +/// are **complementary**, so every one of the 256 rounds carries a nonzero joint +/// digit and therefore an add. Complementarity is what maximises, not popcount — +/// `(N−1, N−1)` shares every add and reaches only 449. +/// +/// **This is the number for anything capacity-shaped** (padding bounds, +/// per-ecall row allowances, any rows-per-call assertion). The measured mean of +/// 449.1 governs the *cost model* and nothing else: a random corpus tops out +/// around 471, but a submitter can construct the worst case deliberately, so no +/// bound may be derived from a sample maximum. +/// +/// Exercised end to end by `test_prove_elfs_ecsm_lincomb2_full_size`, whose +/// guest uses exactly those scalars and asserts the emitted row count. +pub const MAX_ROWS_PER_EVALUATION: usize = 1 + 256 + 256 + 1; + +/// The chain identifier carried in tuple position 0 of every +/// [`Ecdas`](BusId::Ecdas) interaction of the joint chain. +/// +/// The single-scalar chain pins that position to the constant `0` +/// (`ecsm::ecdas_tuple`, "id = 0 (secp256k1)"), so the two chains sharing bus 28 +/// differ in the α¹ coefficient of their fingerprints — a non-zero difference at +/// a fixed power, which Schwartz–Zippel closes. An old-chain tuple therefore +/// cannot be received by ECDAS2 or vice versa. +/// +/// The separation is *not* about zeros shifting tuple positions: they do not. +/// `alpha_offset` advances by `num_bus_elements()` unconditionally +/// (`lookup.rs:1651-1663`), and the `if result != zero` guard at `lookup.rs:679` +/// only skips the multiply for a zero element. Nothing re-aligns. +pub const JOINT_CHAIN_ID: u64 = 1; + +// ========================================================================= +// Column indices (658 columns; keep in sync with NUM_COLUMNS below) +// ========================================================================= + +pub mod cols { + pub const TIMESTAMP_0: usize = 0; + pub const TIMESTAMP_1: usize = 1; + /// Addend x, received on the `Addend` bus (zero on doublings). + pub const XB: usize = 2; // U256BL (32) + /// Addend y. + pub const YB: usize = 34; // U256BL (32) + /// Accumulator in. + pub const XA: usize = 66; // U256BL (32) + pub const YA: usize = 98; // U256BL (32) + pub const ROUND: usize = 130; // Byte + pub const OP: usize = 131; // Bit: 0 = double, 1 = add + /// Result out. + pub const XR: usize = 132; // U256BL (32) + pub const YR: usize = 164; // U256BL (32) + pub const LAMBDA: usize = 196; // U256BL (32) + pub const Q0: usize = 228; // Byte[33] — λ relation quotient + pub const C0: usize = 261; // BaseField[64] + pub const Q1: usize = 325; // Byte[33] — xR relation quotient + pub const C1: usize = 358; // BaseField[64] + pub const Q2: usize = 422; // Byte[33] — yR relation quotient + pub const C2: usize = 455; // BaseField[64] + /// "An add follows me at this round" — pins the successor `(round, op)`. + pub const NB: usize = 519; // Bit + /// `u1`'s digit at this row's round; set on both the doubling and its add. + pub const D1: usize = 520; // Bit + /// `u2`'s digit at this row's round. + pub const D2: usize = 521; // Bit + /// One-hot addend selector: P1 / P2 / P12. + pub const S1: usize = 522; // Bit + pub const S2: usize = 523; // Bit + pub const S3: usize = 524; // Bit + /// Selects the `−2^len·T₀` correction constant. + pub const S_CORR: usize = 525; // Bit + /// `PHASE = PH1 + 2·PH2`, with `PH1·PH2 = 0` — so `PHASE ∈ {0, 1, 2}` and + /// `PH1` is a degree-1 "this is a main-chain row" gate. + pub const PH1: usize = 526; // Bit + pub const PH2: usize = 527; // Bit + pub const MU: usize = 528; // Bit + + /// `(xB − xA)^{-1} mod p` — the non-degeneracy witness, live on every row + /// that consumes an addend and zero elsewhere. + pub const D_INV: usize = 529; // U256BL (32) + /// Quotient of the non-degeneracy relation. + pub const Q3: usize = 561; // Byte[33] + pub const C3: usize = 594; // BaseField[64] + + pub const NUM_COLUMNS: usize = 658; + + #[inline] + pub const fn c0(i: usize) -> usize { + C0 + i + } + #[inline] + pub const fn c1(i: usize) -> usize { + C1 + i + } + #[inline] + pub const fn c2(i: usize) -> usize { + C2 + i + } + #[inline] + pub const fn c3(i: usize) -> usize { + C3 + i + } +} + +// ========================================================================= +// Operation struct +// ========================================================================= + +/// One ECDAS2 row: a joint-chain step witness plus its ECALL timestamp. +#[derive(Debug, Clone)] +pub struct Ecdas2Operation { + pub timestamp: u64, + pub step: JointStep, +} + +impl Ecdas2Operation { + /// `(PH1, PH2)` for this row's phase. + pub fn phase_bits(&self) -> (u8, u8) { + match self.step.sel { + JointSel::Precompute => (0, 0), + JointSel::Correction => (0, 1), + JointSel::Double | JointSel::AddP1 | JointSel::AddP2 | JointSel::AddP12 => (1, 0), + } + } + + /// `(S1, S2, S3, S_CORR)` for this row. The precompute row genuinely adds + /// `P2`, so it reuses `S2` (and hence `sel = 2` on the Addend bus). + pub fn selector_bits(&self) -> (u8, u8, u8, u8) { + match self.step.sel { + JointSel::Double => (0, 0, 0, 0), + JointSel::AddP1 => (1, 0, 0, 0), + JointSel::AddP2 | JointSel::Precompute => (0, 1, 0, 0), + JointSel::AddP12 => (0, 0, 1, 0), + JointSel::Correction => (0, 0, 0, 1), + } + } +} + +// ========================================================================= +// Trace generation +// ========================================================================= + +fn fe_from_i64(c: i64) -> FE { + if c >= 0 { + FE::from(c as u64) + } else { + FE::zero() - FE::from((-c) as u64) + } +} + +// ========================================================================= +// The non-degeneracy witness +// ========================================================================= +// +// `lincomb2_witness` does not carry these columns: the schedule it emits already +// implies `xB ≠ xA` on every add, because it refuses (`ResultInfinity`) any +// input whose chain would add a point to itself. So the inverse is a +// *derivation* from values it already publishes, not new information — but the +// chip needs it regardless, since a malicious prover's row never passes through +// that generator at all. +// +// The derivation lives in `ecsm::witness` beside `ext64`/`conv`/`limb_carries`, +// NOT here. A second copy of that limb arithmetic in the prover is the classic +// silent divergence: one side gets edited, the other does not, and nothing +// notices until a proof is wrong. Re-exported so callers keep saying +// `ecdas2::dinv_witness`. +pub use ecsm::witness::{DinvWitness, dinv_witness}; + +pub fn generate_ecdas2_trace( + ops: &[Ecdas2Operation], +) -> TraceTable { + let n = ops.len(); + let num_rows = n.next_power_of_two().max(4); + let mut trace = TraceTable::new_main( + crate::tables::types::zeroed_fe_vec(num_rows * cols::NUM_COLUMNS), + cols::NUM_COLUMNS, + 1, + ); + let table = &mut trace.main_table; + + for (row_idx, op) in ops.iter().enumerate() { + let j = &op.step; + let s = &j.step; + + table.set_dword_wl(row_idx, cols::TIMESTAMP_0, op.timestamp); + table.set_bytes(row_idx, cols::XB, &s.x_g); + table.set_bytes(row_idx, cols::YB, &s.y_g); + table.set_bytes(row_idx, cols::XA, &s.x_a); + table.set_bytes(row_idx, cols::YA, &s.y_a); + table.set_byte(row_idx, cols::ROUND, s.round); + table.set_byte(row_idx, cols::OP, s.op); + table.set_bytes(row_idx, cols::XR, &s.x_r); + table.set_bytes(row_idx, cols::YR, &s.y_r); + table.set_bytes(row_idx, cols::LAMBDA, &s.lambda); + table.set_bytes(row_idx, cols::Q0, &s.q0); + table.set_bytes(row_idx, cols::Q1, &s.q1); + table.set_bytes(row_idx, cols::Q2, &s.q2); + for i in 0..64 { + debug_assert!((0..1 << 16).contains(&(s.c0[i] + CARRY_OFFSET_LAMBDA))); + debug_assert!((0..1 << 16).contains(&(s.c1[i] + CARRY_OFFSET_XR))); + debug_assert!((0..1 << 16).contains(&(s.c2[i] + CARRY_OFFSET_YR))); + table.set_fe(row_idx, cols::c0(i), fe_from_i64(s.c0[i])); + table.set_fe(row_idx, cols::c1(i), fe_from_i64(s.c1[i])); + table.set_fe(row_idx, cols::c2(i), fe_from_i64(s.c2[i])); + } + + let (ph1, ph2) = op.phase_bits(); + let (s1, s2, s3, s_corr) = op.selector_bits(); + table.set_byte(row_idx, cols::NB, j.nb); + table.set_byte(row_idx, cols::D1, j.d1); + table.set_byte(row_idx, cols::D2, j.d2); + table.set_byte(row_idx, cols::S1, s1); + table.set_byte(row_idx, cols::S2, s2); + table.set_byte(row_idx, cols::S3, s3); + table.set_byte(row_idx, cols::S_CORR, s_corr); + table.set_byte(row_idx, cols::PH1, ph1); + table.set_byte(row_idx, cols::PH2, ph2); + table.set_fe(row_idx, cols::MU, FE::one()); + + let d = dinv_witness(j); + table.set_bytes(row_idx, cols::D_INV, &d.d_inv); + table.set_bytes(row_idx, cols::Q3, &d.q3); + for i in 0..64 { + debug_assert!((0..1 << 16).contains(&(d.c3[i] + CARRY_OFFSET_DINV))); + table.set_fe(row_idx, cols::c3(i), fe_from_i64(d.c3[i])); + } + } + + // Padding rows stay entirely zero (see the module header): with OP = 0 and + // every limb zero, all four convolution relations close at zero carries and + // `OP = ΣS` holds trivially. + + trace +} + +// ========================================================================= +// Bus value helpers +// ========================================================================= + +fn packed(col: usize) -> BusValue { + BusValue::Packed { + start_column: col, + packing: Packing::Direct, + } +} + +/// The 32 bytes of a U256BL coordinate as bus elements. Same shape ECSM/ECDAS +/// use, so publisher and consumer pack identically. +pub fn coord(col: usize) -> Vec { + super::ecsm::point_coord_busvalues(col) +} + +/// The joint chain tuple +/// `[JOINT_CHAIN_ID, ts_lo, ts_hi, phase, accX(32), accY(32), round, op]`. +/// +/// Deliberately narrower than the single-scalar `ecdas_tuple`: the addend is no +/// longer part of the accumulator state (it varies per row and arrives on the +/// `Addend` bus), so `genX`/`genY` are gone and `phase` takes their place. +pub fn joint_tuple( + acc_x: Vec, + acc_y: Vec, + phase: BusValue, + round: BusValue, + op: BusValue, + ts_lo: BusValue, + ts_hi: BusValue, +) -> Vec { + debug_assert_eq!(acc_x.len(), 32); + debug_assert_eq!(acc_y.len(), 32); + let mut v = Vec::with_capacity(1 + 2 + 1 + 2 * 32 + 2); + v.push(BusValue::constant(JOINT_CHAIN_ID)); + v.push(ts_lo); + v.push(ts_hi); + v.push(phase); + v.extend(acc_x); + v.extend(acc_y); + v.push(round); + v.push(op); + v +} + +/// The `Addend` tuple `[ts_lo, ts_hi, sel, x(32), y(32)]`. +pub fn addend_tuple( + ts_lo: BusValue, + ts_hi: BusValue, + sel: BusValue, + x: Vec, + y: Vec, +) -> Vec { + debug_assert_eq!(x.len(), 32); + debug_assert_eq!(y.len(), 32); + let mut v = Vec::with_capacity(3 + 64); + v.push(ts_lo); + v.push(ts_hi); + v.push(sel); + v.extend(x); + v.extend(y); + v +} + +// ========================================================================= +// Bus interactions +// ========================================================================= + +/// `PHASE = PH1 + 2·PH2`. +fn phase_expr() -> BusValue { + BusValue::linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: cols::PH1, + }, + LinearTerm::Column { + coefficient: 2, + column: cols::PH2, + }, + ]) +} + +pub fn bus_interactions() -> Vec { + let mu = || Multiplicity::Column(cols::MU); + let ts_lo = || packed(cols::TIMESTAMP_0); + let ts_hi = || packed(cols::TIMESTAMP_1); + let mut out = Vec::new(); + + // Receive the incoming accumulator [chain_id, ts, phase, xA, yA, round, op]. + out.push(BusInteraction::receiver( + BusId::Ecdas, + mu(), + joint_tuple( + coord(cols::XA), + coord(cols::YA), + phase_expr(), + packed(cols::ROUND), + packed(cols::OP), + ts_lo(), + ts_hi(), + ), + )); + + // Receive the addend [ts, sel, x, y] once per add row (silent on doublings, + // where `OP = ΣS = 0`). `sel = S1 + 2·S2 + 3·S3 + 4·S_CORR ∈ {1, 2, 3, 4}`. + // + // `Multiplicity::Linear`, not `Sum3`: the correction row's `S_CORR` is a + // fourth term. Still one interaction. + out.push(BusInteraction::receiver( + BusId::Addend, + Multiplicity::Linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: cols::S1, + }, + LinearTerm::Column { + coefficient: 1, + column: cols::S2, + }, + LinearTerm::Column { + coefficient: 1, + column: cols::S3, + }, + LinearTerm::Column { + coefficient: 1, + column: cols::S_CORR, + }, + ]), + addend_tuple( + ts_lo(), + ts_hi(), + BusValue::linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: cols::S1, + }, + LinearTerm::Column { + coefficient: 2, + column: cols::S2, + }, + LinearTerm::Column { + coefficient: 3, + column: cols::S3, + }, + LinearTerm::Column { + coefficient: 4, + column: cols::S_CORR, + }, + ]), + coord(cols::XB), + coord(cols::YB), + ), + )); + + // ARE_BYTES range checks, paired: `ARE_BYTES[X, Y]` checks BOTH elements, so + // adjacent bytes share one send — the identical layout `ecdas.rs` uses. The + // 32-byte prefixes of LAMBDA, XR, YR, Q0, Q1, Q2, D_INV, Q3 pair internally + // as (2i, 2i+1); of the five odd bytes, four pair as (ROUND, Q0[32]) and + // (Q1[32], Q2[32]) and Q3[32] rides alone as [b, 0] — the shape ECSM2 uses + // for `mem_q1[32]`. `collect_bitwise_from_ecdas2` mirrors this exactly. + // + // D_INV and Q3 are checked here for the same reason every other convolution + // operand is: the integer-lifting argument (`WIDTH-AUDIT.md` §2) holds only + // because every limb entering `S_i` is a byte, and these two are read by the + // non-degeneracy relation. + // + // XB/YB are deliberately absent: they inherit byte-ness from the publisher's + // already-checked columns through Addend tuple equality. + let pair = |col_x: usize, col_y: usize, out: &mut Vec| { + out.push(BusInteraction::sender( + BusId::AreBytes, + Multiplicity::Column(cols::MU), + vec![packed(col_x), packed(col_y)], + )); + }; + for base in [ + cols::LAMBDA, + cols::XR, + cols::YR, + cols::Q0, + cols::Q1, + cols::Q2, + cols::D_INV, + cols::Q3, + ] { + for i in 0..16 { + pair(base + 2 * i, base + 2 * i + 1, &mut out); + } + } + pair(cols::ROUND, cols::Q0 + 32, &mut out); + pair(cols::Q1 + 32, cols::Q2 + 32, &mut out); + out.push(BusInteraction::sender( + BusId::AreBytes, + Multiplicity::Column(cols::MU), + vec![packed(cols::Q3 + 32), BusValue::constant(0)], + )); + + // IS_HALF range checks on the carries (offsets keep them in [0, 2^16)). + let half = |col: usize, off: i64| { + BusValue::linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: col, + }, + LinearTerm::Constant(off), + ]) + }; + for (base, off) in [ + (cols::C0, CARRY_OFFSET_LAMBDA), + (cols::C1, CARRY_OFFSET_XR), + (cols::C2, CARRY_OFFSET_YR), + (cols::C3, CARRY_OFFSET_DINV), + ] { + for i in 0..63 { + out.push(BusInteraction::sender( + BusId::IsHalfword, + mu(), + vec![half(base + i, off)], + )); + } + } + + // Per-stream digit sends. ECSM2 receives at multiplicity `2·bit`, because a + // set digit is carried by BOTH the round's doubling and its add. + for (stream, col) in [(1u64, cols::D1), (2u64, cols::D2)] { + out.push(BusInteraction::sender( + BusId::JointBit, + Multiplicity::Column(col), + vec![ + ts_lo(), + ts_hi(), + packed(cols::ROUND), + BusValue::constant(stream), + ], + )); + } + + // Send the updated accumulator: [chain_id, ts, phase, xR, yR, round - 1 + NB, NB]. + // `phase` is unchanged — each segment is drained and re-seeded by ECSM2. + out.push(BusInteraction::sender( + BusId::Ecdas, + mu(), + joint_tuple( + coord(cols::XR), + coord(cols::YR), + phase_expr(), + BusValue::linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: cols::ROUND, + }, + LinearTerm::Column { + coefficient: 1, + column: cols::NB, + }, + LinearTerm::Constant(-1), + ]), + packed(cols::NB), + ts_lo(), + ts_hi(), + ), + )); + + out +} + +/// Which convolution relation an ECDAS2 carry constraint enforces. +#[derive(Clone, Copy)] +pub enum Relation { + Lambda, + Xr, + Yr, + /// `D_INV·(xB − xA) ≡ 1 (mod p)` — the addition is a genuine chord. + Dinv, +} + +// ========================================================================= +// Single-body constraint set (ConstraintSet front-end) +// ========================================================================= +// +// Constraint indices 0..=287 (288 total): +// 0..=10 : IS_BIT on MU, OP, NB, D1, D2, S1, S2, S3, S_CORR, PH1, PH2 +// 11 : PH1 · PH2 (PHASE ∈ {0, 1, 2}) +// 12 : OP · NB (an add is never followed by an add) +// 13 : (1 − OP)·(NB − D1 − D2 + D1·D2) (NB = D1 ∨ D2 on doublings) +// 14 : OP − S1 − S2 − S3 − S_CORR (adds pick exactly one addend) +// 15, 16 : (1 − PH1)·D1, (1 − PH1)·D2 (digits only on the main chain) +// 17 : PH1 · S_CORR (T₀ constant is not a main addend) +// 18 : PH1 · (S1 + S3 − OP·D1) (addend matches u1's digit) +// 19 : PH1 · (S2 + S3 − OP·D2) (addend matches u2's digit) +// 20 : MU·(1 − PH1 − PH2)·(S2 − 1) (the precompute row adds P2) +// 21 : PH2 · (S_CORR − 1) (the correction row adds −2^len·T₀) +// 22..=27 : (1 − MU)·{D1, D2, S1, S2, S3, S_CORR} (padding rows emit nothing) +// 28..=287: per relation (Lambda, Xr, Yr, Dinv): 64 ConvCarry + 1 ColIsZero(c_63) +// +// The four relation blocks are contiguous and in that order, so the `Dinv` block +// (223..=287) can be ablated as a unit — which is what the phase-E negative +// control does: drop it, feed the gate the `nums_blinding_probe` construction, +// and the forgery must reappear as SAT. + +use stark::constraints::builder::{ConstraintBuilder, ConstraintSet}; + +/// ECDAS2 transition constraints as a single-source [`ConstraintSet`] (288 +/// total). No column configuration needed (the layout is fixed via `cols`). +pub struct Ecdas2Constraints; + +impl Ecdas2Constraints { + /// Byte `m` of the field prime `P` (zero beyond 32 bytes). + fn p_byte_expr>( + b: &B, + m: usize, + ) -> B::Expr { + if m < 32 { + b.const_base(P_BYTES[m] as u64) + } else { + b.zero() + } + } + + /// Byte `m` of `R = 3p` (zero beyond 33 bytes). + fn r_byte_expr>( + b: &B, + m: usize, + ) -> B::Expr { + if m < 33 { + b.const_base(R_BYTES[m] as u64) + } else { + b.zero() + } + } + + /// `bytes[base + j]` for `j < len`, else zero. + fn byte_at>( + b: &B, + base: usize, + len: usize, + j: usize, + ) -> B::Expr { + if j < len { + b.main(0, base + j) + } else { + b.zero() + } + } + + /// The `μ·R·P − q·P` convolution term, shared by all four relations. The + /// `μ`-gate makes it vanish on padding rows (`μ = 0`, `q = 0`), keeping every + /// relation at zero carries. + fn rq>( + b: &B, + i: usize, + qbase: usize, + ) -> B::Expr { + let mu = b.main(0, cols::MU); + let mut r_p = b.zero(); + let mut q_p = b.zero(); + for j in 0..=i { + r_p = r_p + Self::r_byte_expr(b, j) * Self::p_byte_expr(b, i - j); + q_p = q_p + Self::byte_at(b, qbase, 33, j) * Self::p_byte_expr(b, i - j); + } + mu * r_p - q_p + } + + /// `S_i` for `relation` at limb `i`. Identical to `ecdas.rs`'s body with + /// `XG`/`YG` renamed to the per-row addend `XB`/`YB`. + fn s_i>( + b: &B, + relation: Relation, + i: usize, + ) -> B::Expr { + let lam = |j: usize| Self::byte_at(b, cols::LAMBDA, 32, j); + let xg = |j: usize| Self::byte_at(b, cols::XB, 32, j); + let xa = |j: usize| Self::byte_at(b, cols::XA, 32, j); + let ya = |j: usize| Self::byte_at(b, cols::YA, 32, j); + let yg = |j: usize| Self::byte_at(b, cols::YB, 32, j); + let xr = |j: usize| Self::byte_at(b, cols::XR, 32, j); + let yr = |j: usize| Self::byte_at(b, cols::YR, 32, j); + let op = b.main(0, cols::OP); + let one = b.one(); + + match relation { + Relation::Lambda => { + // op·(Σ λ_j(xB-xA)_{i-j} + (yA_i - yB_i)) + let mut op_branch = ya(i) - yg(i); + for j in 0..=i { + op_branch = op_branch + lam(j) * (xg(i - j) - xa(i - j)); + } + // (1-op)·Σ (2 λ_j yA_{i-j} - 3 xA_j xA_{i-j}) + let mut notop_branch = b.zero(); + for j in 0..=i { + let two = b.const_base(2); + let three = b.const_base(3); + notop_branch = + notop_branch + two * lam(j) * ya(i - j) - three * xa(j) * xa(i - j); + } + op.clone() * op_branch + (one - op) * notop_branch + Self::rq(b, i, cols::Q0) + } + Relation::Xr => { + // Σ λ_j λ_{i-j} − xA_i − xB_i − xR_i − (1-op)(xA_i − xB_i) + rq + let mut s = b.zero(); + for j in 0..=i { + s = s + lam(j) * lam(i - j); + } + s - xa(i) - xg(i) - xr(i) - (one - op) * (xa(i) - xg(i)) + Self::rq(b, i, cols::Q1) + } + Relation::Yr => { + // Σ λ_j(xA-xR)_{i-j} − yA_i − yR_i + rq + let mut s = b.zero(); + for j in 0..=i { + s = s + lam(j) * (xa(i - j) - xr(i - j)); + } + s - ya(i) - yr(i) + Self::rq(b, i, cols::Q2) + } + Relation::Dinv => { + // g·(Σ d_j(xB−xA)_{i−j} − [i = 0]) + rq, with + // g = S1 + S2 + S3 + S_CORR. + // + // `g` rather than `OP` deliberately: idx 14 makes the two equal, + // but this way the non-degeneracy proof is tied to the same + // expression that receives the addend, so the check can never + // drift away from the rows that consume one. + // + // On a gated-off row (`g = 0`) only `rq` remains, which closes at + // `q3 = 3p` with zero carries on a real doubling and at `q3 = 0` + // on an all-zero padding row. + let d = |j: usize| Self::byte_at(b, cols::D_INV, 32, j); + let mut s = b.zero(); + for j in 0..=i { + s = s + d(j) * (xg(i - j) - xa(i - j)); + } + if i == 0 { + s = s - one; + } + let g = b.main(0, cols::S1) + + b.main(0, cols::S2) + + b.main(0, cols::S3) + + b.main(0, cols::S_CORR); + g * s + Self::rq(b, i, cols::Q3) + } + } + } + + /// `256·c_i − c_{i-1} − S_i`. + fn conv_carry>( + b: &B, + relation: Relation, + i: usize, + ) -> B::Expr { + let c_base = match relation { + Relation::Lambda => cols::C0, + Relation::Xr => cols::C1, + Relation::Yr => cols::C2, + Relation::Dinv => cols::C3, + }; + let c_i = b.main(0, c_base + i); + let c_prev = if i == 0 { + b.zero() + } else { + b.main(0, c_base + i - 1) + }; + let two_pow_8 = b.const_base(256); + two_pow_8 * c_i - c_prev - Self::s_i(b, relation, i) + } +} + +impl ConstraintSet for Ecdas2Constraints { + // The Lambda ConvCarry has the op·(λ·Δx) term, making it degree 3; so are + // the NB and precompute-selector constraints. + fn max_degree(&self) -> usize { + 3 + } + + fn eval>(&self, b: &mut B) { + // idx 0..=10: unconditional IS_BIT `x·(1−x)` on every boolean column. + for (i, col) in [ + cols::MU, + cols::OP, + cols::NB, + cols::D1, + cols::D2, + cols::S1, + cols::S2, + cols::S3, + cols::S_CORR, + cols::PH1, + cols::PH2, + ] + .into_iter() + .enumerate() + { + let x = b.main(0, col); + let one = b.one(); + b.emit_base(i, x.clone() * (one - x)); + } + + // idx 11: PH1·PH2 = 0, so PHASE = PH1 + 2·PH2 ranges over {0, 1, 2}. + let ph1 = b.main(0, cols::PH1); + let ph2 = b.main(0, cols::PH2); + b.emit_base(11, ph1 * ph2); + + // idx 12: OP·NB = 0. An add row never announces another add at its own + // round, so a round is visited by at most one add. + let op = b.main(0, cols::OP); + let nb = b.main(0, cols::NB); + b.emit_base(12, op * nb); + + // idx 13: (1 − OP)·(NB − D1 − D2 + D1·D2) = 0. On a doubling `NB` is the + // OR of that round's two digits, which is exactly "an add follows me". + // Op-gated: an add row carries the same digits but always has NB = 0. + let op = b.main(0, cols::OP); + let nb = b.main(0, cols::NB); + let d1 = b.main(0, cols::D1); + let d2 = b.main(0, cols::D2); + let one = b.one(); + b.emit_base(13, (one - op) * (nb - d1.clone() - d2.clone() + d1 * d2)); + + // idx 14: OP = S1 + S2 + S3 + S_CORR. Adds consume exactly one addend; + // doublings consume none. Without this the double-row addend + // cancellation is real but its *gating* is forgeable — a prover would + // set S2 = 1 on a doubling and mint a spurious Addend receive. + let op = b.main(0, cols::OP); + let s1 = b.main(0, cols::S1); + let s2 = b.main(0, cols::S2); + let s3 = b.main(0, cols::S3); + let s_corr = b.main(0, cols::S_CORR); + b.emit_base(14, op - s1 - s2 - s3 - s_corr); + + // idx 15, 16: (1 − PH1)·D = 0. Digits live only on main-chain rows. + // The precompute and correction rows are both emitted at `round = 0`, so + // without this a prover sets D1 = 1 on both of them and satisfies the + // `2·u1_bit(0)` JointBit receive with no round-0 add at all — u1's low + // bit would be consumed without ever being added. + let one = b.one(); + let ph1 = b.main(0, cols::PH1); + let d1 = b.main(0, cols::D1); + b.emit_base(15, (one - ph1) * d1); + let one = b.one(); + let ph1 = b.main(0, cols::PH1); + let d2 = b.main(0, cols::D2); + b.emit_base(16, (one - ph1) * d2); + + // idx 17: PH1·S_CORR = 0. The T₀ correction constant is not available to + // the main chain. + let ph1 = b.main(0, cols::PH1); + let s_corr = b.main(0, cols::S_CORR); + b.emit_base(17, ph1 * s_corr); + + // idx 18, 19: on the main chain the addend is exactly the one the two + // digits select. Written as the two degree-3 sums + // S1 + S3 = OP·D1 ("the addend includes P1 iff u1's digit is set") + // S2 + S3 = OP·D2 + // rather than the three one-hot products, which would need degree 4 to + // carry the OP gate. Together with idx 14 they force + // (D1,D2) = (1,0) ⇒ S1, (0,1) ⇒ S2, (1,1) ⇒ S3, and make (0,0) with + // OP = 1 unsatisfiable — so no spurious add can be inserted. On a + // doubling OP = 0 makes both sides zero, consistent with idx 14. + let ph1 = b.main(0, cols::PH1); + let s1 = b.main(0, cols::S1); + let s3 = b.main(0, cols::S3); + let op = b.main(0, cols::OP); + let d1 = b.main(0, cols::D1); + b.emit_base(18, ph1 * (s1 + s3 - op * d1)); + let ph1 = b.main(0, cols::PH1); + let s2 = b.main(0, cols::S2); + let s3 = b.main(0, cols::S3); + let op = b.main(0, cols::OP); + let d2 = b.main(0, cols::D2); + b.emit_base(19, ph1 * (s2 + s3 - op * d2)); + + // idx 20: MU·(1 − PH1 − PH2)·(S2 − 1) = 0. The single phase-0 row adds + // P2. Without it a prover could point the precompute at P1, making the + // chord `P1 + P1` — whose λ relation degenerates to 0 = 0 and admits any + // λ, i.e. an arbitrary "P12". MU-gated so all-zero padding rows are free. + let mu = b.main(0, cols::MU); + let one = b.one(); + let ph1 = b.main(0, cols::PH1); + let ph2 = b.main(0, cols::PH2); + let s2 = b.main(0, cols::S2); + let one2 = b.one(); + b.emit_base(20, mu * (one - ph1 - ph2) * (s2 - one2)); + + // idx 21: PH2·(S_CORR − 1) = 0. The single phase-2 row adds the T₀ + // constant. + let ph2 = b.main(0, cols::PH2); + let s_corr = b.main(0, cols::S_CORR); + let one = b.one(); + b.emit_base(21, ph2 * (s_corr - one)); + + // idx 22..=27: (1 − MU)·x = 0 for every column that is a bus + // *multiplicity*. A padding row is inert on the μ-gated interactions by + // construction, but these two are not μ-gated — the digit sends count + // `D1`/`D2` and the Addend receive counts `S1 + S2 + S3 + S_CORR` — so + // without this a padding row still emits. The single-scalar chip carries + // the same defence for its Bit-bus sender (`ecdas.rs`, idx 4: + // `NEXT_OP·(1 − MU)`). + // + // Both holes are live forgeries, not hygiene: + // + // * a `MU = 0, PH1 = 1, NB = 1, D1 = 1, ROUND = r` row satisfies every + // other constraint and emits a real `JointBit[ts, r, 1]`. Two of them + // supply the `2·u1_bit(r)` an honest round pays with its doubling *and* + // its add, so the prover can drop the add at round `r` entirely (with + // `D1 = D2 = 0` the doubling's `NB` is 0 and nothing demands one). The + // chain then computes `(u1 − 2^r)·P1 + u2·P2`; back-solving the + // signature for a chosen target needs one modular inversion and no + // discrete log. + // * a `MU = 0, OP = 1, S2 = 1` row keeps `OP = ΣS` satisfied and mints a + // spurious Addend receive. + // + // `NB` needs no companion: with every selector zero, `OP = ΣS` forces + // `OP = 0`, and idx 13 then reads `NB = D1 ∨ D2 = 0`. + for (i, col) in [ + cols::D1, + cols::D2, + cols::S1, + cols::S2, + cols::S3, + cols::S_CORR, + ] + .into_iter() + .enumerate() + { + let one = b.one(); + let mu = b.main(0, cols::MU); + let x = b.main(0, col); + b.emit_base(22 + i, (one - mu) * x); + } + + // Per relation: 64 ConvCarry (i = 0..64) + 1 ColIsZero(c_63). + let mut idx = 28; + for (relation, c_base) in [ + (Relation::Lambda, cols::C0), + (Relation::Xr, cols::C1), + (Relation::Yr, cols::C2), + (Relation::Dinv, cols::C3), + ] { + for i in 0..64 { + let root = Self::conv_carry(b, relation, i); + b.emit_base(idx, root); + idx += 1; + } + let c_last = b.main(0, c_base + 63); + b.emit_base(idx, c_last); // ColIsZero c_63 + idx += 1; + } + + debug_assert_eq!(idx, 288); + } +} diff --git a/prover/src/tables/ecsm.rs b/prover/src/tables/ecsm.rs index 5d0a9477f..68ba3ede8 100644 --- a/prover/src/tables/ecsm.rs +++ b/prover/src/tables/ecsm.rs @@ -271,6 +271,16 @@ fn register_value(lo_col: usize, hi_col: usize) -> [BusValue; 8] { /// The 32 bytes of a U256BL coordinate as bus elements (shared shape for the ECDAS bus, /// used identically by ECSM and ECDAS). +/// +/// **The one-element-per-byte layout is a soundness property, not a formatting choice.** +/// Because each byte is its own `Packing::Direct` element, tuple equality on this bus is +/// per-limb, so a receiver inherits byte-ness from the sender's `AreBytes`-checked columns +/// without re-checking it. Repacking this (e.g. `Word4L`, 4 bytes per element) to shrink +/// the bus would break that: a receiver could satisfy the same packed value with a +/// different decomposition (`b₀ + 2⁸k`, `b₁ − k`), and its own limbs carry no range check, +/// so reachable limb magnitudes run to ~2^63. The convolution relations have ~2^39 of +/// headroom against honest *byte* limbs but only ~2^29 against malformed ones — a single +/// non-byte limb breaks the integer identity. Do not repack. pub fn point_coord_busvalues(col: usize) -> Vec { (0..32).map(|b| packed(col + b)).collect() } @@ -443,20 +453,30 @@ pub fn bus_interactions() -> Vec { )); } - // IS_BYTE range checks (single byte → AreBytes[x, 0]). - let is_byte = |col: usize, len: usize, out: &mut Vec| { - for i in 0..len { - out.push(BusInteraction::sender( - BusId::AreBytes, - Multiplicity::Column(cols::MU), - vec![packed(col + i), BusValue::constant(0)], - )); - } + // ARE_BYTES range checks, paired: `ARE_BYTES[X, Y]` checks BOTH elements + // (bitwise.rs `generate_bitwise_row` enumerates every (x, y) byte pair), so + // adjacent bytes share one send — 129 single-byte `[b, 0]` sends become 65. + // Layout: X2, Q0, YG and Q1's 32-byte prefix pair internally as (2i, 2i+1); + // the odd 33rd byte q1[32] rides alone as `[q1[32], 0]`. + // `collect_bitwise_from_ecsm` mirrors this layout exactly (sends and + // BITWISE multiplicities must move together). + let pair = |col_x: usize, col_y: usize, out: &mut Vec| { + out.push(BusInteraction::sender( + BusId::AreBytes, + Multiplicity::Column(cols::MU), + vec![packed(col_x), packed(col_y)], + )); }; - is_byte(cols::X2, 32, &mut out); - is_byte(cols::Q0, 32, &mut out); - is_byte(cols::YG, 32, &mut out); - is_byte(cols::Q1, 33, &mut out); // q1[0..=32] (all 33 bytes) + for base in [cols::X2, cols::Q0, cols::YG, cols::Q1] { + for i in 0..16 { + pair(base + 2 * i, base + 2 * i + 1, &mut out); + } + } + out.push(BusInteraction::sender( + BusId::AreBytes, + Multiplicity::Column(cols::MU), + vec![packed(cols::q1(32)), BusValue::constant(0)], + )); // xG and k are byte-checked at memory write time (store.rs AreBytes), not re-checked here. // IS_HALF range checks on shifted carries, then k_sub_N / xR_sub_p. diff --git a/prover/src/tables/ecsm2.rs b/prover/src/tables/ecsm2.rs new file mode 100644 index 000000000..260ca8f5f --- /dev/null +++ b/prover/src/tables/ecsm2.rs @@ -0,0 +1,1257 @@ +//! ECSM2 core chip — orchestrates one `Q = u1·P1 + u2·P2` (lincomb2) evaluation. +//! +//! One row per `ECALL(-12)`. It receives the ECALL, reads the three 64-byte +//! operands and writes the 64-byte result plus the status word, proves `P2` is +//! on the curve and canonical in `y`, proves both scalars are in `[1, N)`, +//! publishes the three addends and the NUMS correction constant on the +//! [`Addend`](BusId::Addend) bus, serves the 512 joint scalar digits on the +//! [`JointBit`](BusId::JointBit) bus, and seeds and drains the three segments of +//! the joint double-add chain that [`ecdas2`](super::ecdas2) executes. +//! +//! The witness is built by `ecsm::witness::lincomb2_witness`, which is the spec: +//! every column block below is one of its fields. +//! +//! # `P1` is pinned to the generator `G` +//! +//! `Lincomb2Witness` carries `mem_p2` but **no `mem_p1`**, so a general `P1` is +//! not provable. Instead the 8 doubleword reads at `a1` carry *constant* values +//! (`GENERATOR_LE`), which asserts "memory at `a1` contains exactly G" at zero +//! columns and zero constraints, and makes `P1`'s on-curve-ness a compile-time +//! fact. The executor agrees by construction: `lincomb2_outcome` returns +//! `LINCOMB2_STATUS_P1_NOT_GENERATOR` when the bytes at `a1` are not `G`, so a +//! non-ecrecover caller degrades to the software fallback instead of making the +//! block unprovable. +//! +//! # Two flags, not one: `MU` and `OK` +//! +//! | flag | meaning | gates | +//! |---|---|---| +//! | `MU` | a real lincomb2 ecall happened at this timestamp | the `Ecall` receive and the `x10` read+write (status) | +//! | `OK` | `status == 0`, i.e. the chain is proven | *everything else* — all operand reads, the result write, every range check, every relation, every chain/addend/digit bus | +//! +//! with `IS_BIT` on both and `OK·(1 − MU) = 0`. +//! +//! Two reasons the split is required rather than stylistic: +//! +//! 1. **Bus 19 must balance on the error path.** The CPU sends on `Ecall` for +//! every ecall, so an unmatched syscall unbalances the bus. There is no chain +//! to prove when `status != 0`, and the padding trick (`μ = 0`, all columns +//! zero) would kill the receive as well. +//! 2. **`status = 7` (`P1 != G`) must stay provable.** If the `a1` reads were +//! `MU`-gated they would assert, on exactly the path where it is false, that +//! memory at `a1` holds `G`. Gating them by `OK` makes the error row claim +//! nothing about memory beyond the status write. +//! +//! Soundness of the converse direction — `status == 0` must *oblige* the proof, +//! or a prover sets `OK = 0`, writes `status = 0`, and the guest reads a +//! fabricated `Q` — is carried by two constraints: +//! +//! ```text +//! OK · STATUS = 0 (OK = 1 ⇒ status is 0) +//! MU · (STATUS · S_INV − (1 − OK)) = 0 (OK = 0 ⇒ status is non-zero) +//! ``` +//! +//! The witnessed inverse `S_INV` keeps the per-variant error codes distinguishable. +//! +//! # Error and padding rows +//! +//! An error row sets `OK = 0` and every math column to zero, so all convolution +//! and carry-chain relations close at zero carries by exactly the argument +//! padding rows already use. It differs from a padding row only in `MU = 1` and +//! in carrying the real `ADDR_Q`/`STATUS` that the `x10` access binds. +//! +//! # What a dead row can still emit +//! +//! "The columns are zero as generated" is **not** an argument: a malicious +//! prover fills padding rows freely, so every interaction has to be inert by +//! *constraint*. The question to ask of each one is not "is it gated?" but +//! "which column supplies its multiplicity, and what forces that column to +//! zero?". `ecdas2` had a live hole of exactly this shape — its digit sends take +//! their multiplicity from raw `D1`/`D2` columns, and a `MU = 0` row could still +//! fire them, which is worth an arbitrary chosen recovered public key. +//! +//! Audited here interaction by interaction: +//! +//! | interaction | multiplicity | what makes a dead row inert | +//! |---|---|---| +//! | `Ecall` receive | `MU` | balance-forced: the CPU sends exactly one per real ecall, so a spurious `MU = 1` has no matching send | +//! | `x10` read+write | `MU` | same | +//! | all other MEMW, `AreBytes`, `IsHalfword`, `Zero`, `EcT0`, the `Ecdas` seeds/drains, the `sel = 4` Addend publish | `OK` | `OK` is `IS_BIT` and `OK·(1 − MU) = 0`, so it inherits the row above | +//! | 512 `JointBit` receives | `2·u1_bit(i)` / `2·u2_bit(i)` — **raw columns, not `OK`** | idx 517, 518: `(Σ u_bit)·(1 − OK) = 0` | +//! | 3 Addend publishes | `N1`/`N2`/`N3` — **raw columns, not `OK`** | idx 519..=521: `N·(1 − OK) = 0` | +//! +//! The last two rows are the ones that would otherwise be live. Recorded here +//! because this reasoning is expensive to reconstruct and cheap to write down — +//! and because the bug in the sibling chip existed precisely because nobody had. +//! +//! # `len` needs no consumer range check +//! +//! `LEN_M1 = len − 1` keys the `EcT0` send as `LEN_M1 + 1`, and that table has +//! exactly 256 unpadded rows spanning `len ∈ [1, 256]`. A send outside that range +//! matches no row and the LogUp argument cannot balance, so the bound holds by +//! construction — see the `ec_t0` module header, which asks consumers *not* to +//! add a redundant check. + +use executor::vm::instruction::execution::{ECSM_LINCOMB2_SYSCALL_NUMBER, GENERATOR_LE}; +use stark::lookup::{BusInteraction, BusValue, LinearTerm, Multiplicity, Packing}; +use stark::trace::TraceTable; + +use super::ecdas2::{addend_tuple, coord, joint_tuple}; +use super::types::{BusId, FE, GoldilocksExtension, GoldilocksField, VmTable}; +use crate::constraints::templates::INV_SHIFT_32; +use ecsm::witness::{JointSel, Lincomb2Witness, T0_X_LE, T0_Y_LE}; +use ecsm::{B, N_BYTES, P_BYTES}; + +// Bias signed convolution carries into IsHalfword [0, 2^16). Same relations as +// the ECSM membership proof, so the same offsets. +pub(crate) use super::ecsm::{CARRY_OFFSET_X2, CARRY_OFFSET_YG}; + +/// Addend-bus selector values. Never 0: a zero element is skipped by the +/// fingerprint, so a `sel = 0` addend would alias a shorter tuple. +pub const SEL_P1: u64 = 1; +pub const SEL_P2: u64 = 2; +pub const SEL_P12: u64 = 3; +pub const SEL_CORRECTION: u64 = 4; + +/// `JointBit` stream tags. Also never 0, for the same reason plus the old-chain +/// `Bit[ts, round]` aliasing described on [`BusId::JointBit`]. +pub const STREAM_U1: u64 = 1; +pub const STREAM_U2: u64 = 2; + +// ========================================================================= +// Column indices (1155 columns; keep in sync with NUM_COLUMNS below) +// ========================================================================= + +pub mod cols { + pub const TIMESTAMP_0: usize = 0; + pub const TIMESTAMP_1: usize = 1; + /// `a0`: where `xQ‖yQ` is written. This is x10's value *before* the ecall — + /// the status clobbers it, so both ride the one `x10` read+write access. + pub const ADDR_Q_0: usize = 2; + pub const ADDR_Q_1: usize = 3; + /// `a1`: address of `xP1‖yP1` (asserted to hold `G`). + pub const ADDR_P1_0: usize = 4; + pub const ADDR_P1_1: usize = 5; + /// `a2`: address of `xP2‖yP2`. + pub const ADDR_P2_0: usize = 6; + pub const ADDR_P2_1: usize = 7; + /// `a3`: address of `u1‖u2`. + pub const ADDR_U_0: usize = 8; + pub const ADDR_U_1: usize = 9; + + pub const X_P2: usize = 10; // U256BL (32) + pub const Y_P2: usize = 42; // U256BL (32) + + // `P2` curve-membership sub-witness — the same two convolutions ECSM proves + // for its generator, applied to the variable point. + /// `x2 = xP2² mod p` + pub const MEM_X2: usize = 74; // U256BL (32) + /// quotient of the `x2` relation + pub const MEM_Q0: usize = 106; // U256BL (32) + pub const MEM_C0: usize = 138; // BaseField[64] + /// quotient of the `y²` relation + pub const MEM_Q1: usize = 202; // Byte[33] + pub const MEM_C1: usize = 235; // BaseField[64] + + /// `yP2 < p` + pub const Y_P2_SUB_P: usize = 299; // U256HL (16 halfwords) + + /// `P12 = P1 + P2`, drained from the phase-0 chain row. + pub const X_P12: usize = 315; // U256BL (32) + pub const Y_P12: usize = 347; // U256BL (32) + + /// `u1` as 256 bits, LSB first. + pub const U1: usize = 379; + /// `u2` as 256 bits, LSB first. + pub const U2: usize = 635; + /// `u1 < N` + pub const U1_SUB_N: usize = 891; // U256HL (16 halfwords) + /// `u2 < N` + pub const U2_SUB_N: usize = 907; // U256HL (16 halfwords) + + /// `len − 1`, the schedule length. Keys the `EcT0` lookup as `LEN_M1 + 1` + /// and seeds the main chain's first round. + pub const LEN_M1: usize = 923; + + /// `−2^len·T₀`, received from the preprocessed `EC_T0` table. This is the + /// NEGATED point, matching both the table and the witness's correction-row + /// addend — never `Lincomb2Witness::x_t0_pow`/`y_t0_pow`, which hold the + /// positive `2^len·T₀` and differ from these by a modular negation of `y`. + pub const X_T0N: usize = 924; // U256BL (32) + pub const Y_T0N: usize = 956; // U256BL (32) + + /// The accumulator handed from chain phase 1 to chain phase 2. ECSM2 + /// receives the phase-1 drain into these columns and re-sends them as the + /// phase-2 seed, so the hand-off is a literal relay. + pub const ACC_X: usize = 988; // U256BL (32) + pub const ACC_Y: usize = 1020; // U256BL (32) + + /// The result, drained from the phase-2 (correction) chain row. + pub const X_Q: usize = 1052; // U256BL (32) + pub const Y_Q: usize = 1084; // U256BL (32) + /// `xQ < p`, `yQ < p` — load-bearing: the guest keccaks these bytes, so a + /// `+p`-shifted coordinate hashes to a different address. + pub const X_Q_SUB_P: usize = 1116; // U256HL (16 halfwords) + pub const Y_Q_SUB_P: usize = 1132; // U256HL (16 halfwords) + + /// Addend publish counts. Needs no range check: an inflated count leaves an + /// unmatched send and a "negative" one is unrepresentable, so LogUp balance + /// pins each to the exact number of receives. + pub const N1: usize = 1148; + pub const N2: usize = 1149; + pub const N3: usize = 1150; + + /// The word written back to `x10`. + pub const STATUS: usize = 1151; + /// Witnessed inverse of `STATUS` on error rows. + pub const S_INV: usize = 1152; + /// `status == 0`: the full chain is proven on this row. + pub const OK: usize = 1153; + /// A real lincomb2 ecall happened at this timestamp. + pub const MU: usize = 1154; + + pub const NUM_COLUMNS: usize = 1155; + + /// Bit `i` of `u1` (0 = LSB, 255 = MSB). + #[inline] + pub const fn u1_bit(i: usize) -> usize { + U1 + i + } + /// Bit `i` of `u2`. + #[inline] + pub const fn u2_bit(i: usize) -> usize { + U2 + i + } + #[inline] + pub const fn mem_c0(i: usize) -> usize { + MEM_C0 + i + } + #[inline] + pub const fn mem_c1(i: usize) -> usize { + MEM_C1 + i + } + #[inline] + pub const fn mem_q1(i: usize) -> usize { + MEM_Q1 + i + } + #[inline] + pub const fn x_q(i: usize) -> usize { + X_Q + i + } + #[inline] + pub const fn y_q(i: usize) -> usize { + Y_Q + i + } +} + +// ========================================================================= +// Operation struct +// ========================================================================= + +/// One lincomb2 ecall: the four operand addresses, the status word written back +/// to `x10`, and — only when the status is `0` — the chip witness. +#[derive(Debug, Clone)] +pub struct Ecsm2Operation { + pub timestamp: u64, + pub addr_q: u64, + pub addr_p1: u64, + pub addr_p2: u64, + pub addr_u: u64, + pub status: u64, + /// `None` exactly when `status != 0`. The row then proves only the `Ecall` + /// receive and the status write. + pub witness: Option>, +} + +/// How many times each of the three point addends is consumed by the chain. +/// +/// The precompute row genuinely adds `P2`, so it counts towards `n2` — the +/// counts are witnessed and balance-forced, so that is not a special case. +pub fn addend_counts(w: &Lincomb2Witness) -> (u64, u64, u64) { + let mut counts = (0u64, 0u64, 0u64); + for step in &w.steps { + match step.sel { + JointSel::AddP1 => counts.0 += 1, + JointSel::AddP2 | JointSel::Precompute => counts.1 += 1, + JointSel::AddP12 => counts.2 += 1, + JointSel::Double | JointSel::Correction => {} + } + } + counts +} + +/// The correction row's addend, i.e. `−2^len·T₀` as the `EC_T0` table stores it. +/// +/// Read off the emitted row rather than reconstructed from +/// `x_t0_pow`/`y_t0_pow`, which hold the *positive* blind: `x` agrees but `y` is +/// a modular negation apart, and mixing the two is a silent sign flip. +pub fn correction_addend(w: &Lincomb2Witness) -> ([u8; 32], [u8; 32]) { + let last = w + .steps + .last() + .expect("lincomb2 witness always emits a correction row"); + debug_assert_eq!(last.sel, JointSel::Correction); + (last.step.x_g, last.step.y_g) +} + +// ========================================================================= +// Trace generation +// ========================================================================= + +/// Converts a signed carry to a field element (negatives wrap to `p − |c|`). +fn fe_from_i64(c: i64) -> FE { + if c >= 0 { + FE::from(c as u64) + } else { + FE::zero() - FE::from((-c) as u64) + } +} + +/// Writes a 32-byte little-endian value as 16 halfwords (U256HL). +fn write_halfwords(table: &mut impl VmTable, row: usize, col: usize, bytes: &[u8; 32]) { + let mut halfwords = [0u16; 16]; + for j in 0..16 { + halfwords[j] = u16::from_le_bytes([bytes[2 * j], bytes[2 * j + 1]]); + } + table.set_halves(row, col, &halfwords); +} + +pub fn generate_ecsm2_trace( + ops: &[Ecsm2Operation], +) -> TraceTable { + let n = ops.len(); + let num_rows = n.next_power_of_two().max(4); + let mut trace = TraceTable::new_main( + crate::tables::types::zeroed_fe_vec(num_rows * cols::NUM_COLUMNS), + cols::NUM_COLUMNS, + 1, + ); + let table = &mut trace.main_table; + + for (row_idx, op) in ops.iter().enumerate() { + // Present on every row, error or not: these are what the MU-gated Ecall + // receive and x10 read+write bind. + table.set_dword_wl(row_idx, cols::TIMESTAMP_0, op.timestamp); + table.set_dword_wl(row_idx, cols::ADDR_Q_0, op.addr_q); + table.set_u64(row_idx, cols::STATUS, op.status); + table.set_fe(row_idx, cols::MU, FE::one()); + + let Some(w) = op.witness.as_deref() else { + // Error row: OK = 0 and every math column stays zero, so all + // relations close at zero carries. Only the status inverse is live. + let inv = FE::from(op.status) + .inv() + .expect("error rows carry a non-zero status by construction"); + table.set_fe(row_idx, cols::S_INV, inv); + continue; + }; + + table.set_fe(row_idx, cols::OK, FE::one()); + table.set_dword_wl(row_idx, cols::ADDR_P1_0, op.addr_p1); + table.set_dword_wl(row_idx, cols::ADDR_P2_0, op.addr_p2); + table.set_dword_wl(row_idx, cols::ADDR_U_0, op.addr_u); + + table.set_bytes(row_idx, cols::X_P2, &w.x_p2); + table.set_bytes(row_idx, cols::Y_P2, &w.y_p2); + table.set_bytes(row_idx, cols::MEM_X2, &w.mem_p2.x2); + table.set_bytes(row_idx, cols::MEM_Q0, &w.mem_p2.q0); + table.set_bytes(row_idx, cols::MEM_Q1, &w.mem_p2.q1); + for i in 0..64 { + debug_assert!((0..1 << 16).contains(&(w.mem_p2.c0[i] + CARRY_OFFSET_X2))); + debug_assert!((0..1 << 16).contains(&(w.mem_p2.c1[i] + CARRY_OFFSET_YG))); + table.set_fe(row_idx, cols::mem_c0(i), fe_from_i64(w.mem_p2.c0[i])); + table.set_fe(row_idx, cols::mem_c1(i), fe_from_i64(w.mem_p2.c1[i])); + } + write_halfwords(table, row_idx, cols::Y_P2_SUB_P, &w.y_p2_sub_p); + + table.set_bytes(row_idx, cols::X_P12, &w.x_p12); + table.set_bytes(row_idx, cols::Y_P12, &w.y_p12); + + for b in 0..256 { + let bit1 = (w.u1[b / 8] >> (b % 8)) & 1; + let bit2 = (w.u2[b / 8] >> (b % 8)) & 1; + table.set_fe(row_idx, cols::u1_bit(b), FE::from(bit1 as u64)); + table.set_fe(row_idx, cols::u2_bit(b), FE::from(bit2 as u64)); + } + write_halfwords(table, row_idx, cols::U1_SUB_N, &w.u1_sub_n); + write_halfwords(table, row_idx, cols::U2_SUB_N, &w.u2_sub_n); + + debug_assert!((1..=256).contains(&w.len), "len out of the EC_T0 range"); + table.set_u64(row_idx, cols::LEN_M1, (w.len - 1) as u64); + + let (x_t0n, y_t0n) = correction_addend(w); + table.set_bytes(row_idx, cols::X_T0N, &x_t0n); + table.set_bytes(row_idx, cols::Y_T0N, &y_t0n); + + // The accumulator entering the correction row: the phase-1 drain that + // ECSM2 relays into the phase-2 seed. + let correction = w.steps.last().expect("correction row"); + table.set_bytes(row_idx, cols::ACC_X, &correction.step.x_a); + table.set_bytes(row_idx, cols::ACC_Y, &correction.step.y_a); + + table.set_bytes(row_idx, cols::X_Q, &w.x_q); + table.set_bytes(row_idx, cols::Y_Q, &w.y_q); + write_halfwords(table, row_idx, cols::X_Q_SUB_P, &w.x_q_sub_p); + write_halfwords(table, row_idx, cols::Y_Q_SUB_P, &w.y_q_sub_p); + + let (n1, n2, n3) = addend_counts(w); + table.set_u64(row_idx, cols::N1, n1); + table.set_u64(row_idx, cols::N2, n2); + table.set_u64(row_idx, cols::N3, n3); + } + + trace +} + +// ========================================================================= +// Bus value helpers +// ========================================================================= + +fn packed(col: usize) -> BusValue { + BusValue::Packed { + start_column: col, + packing: Packing::Direct, + } +} + +/// 32 constant bus elements — a compile-time point coordinate, packed exactly as +/// [`coord`] packs a column-backed one. +fn const_coord(bytes: &[u8]) -> Vec { + debug_assert_eq!(bytes.len(), 32); + bytes + .iter() + .map(|&b| BusValue::constant(b as u64)) + .collect() +} + +/// `[old[8], is_register, base_lo, base_hi, value[8], ts_lo, ts_hi, w2, w4, w8]` +/// — the 24-element MEMW tuple. A plain read passes `old == value`; a combined +/// read+write (the `x10` status access) passes the pre-ecall value as `old`. +#[allow(clippy::too_many_arguments)] +fn memw_read( + old: [BusValue; 8], + value: [BusValue; 8], + is_register: u64, + base_lo: BusValue, + base_hi: BusValue, + ts_lo: BusValue, + ts_hi: BusValue, + w2: u64, + w8: u64, +) -> Vec { + let mut v = Vec::with_capacity(24); + v.extend(old); + v.push(BusValue::constant(is_register)); + v.push(base_lo); + v.push(base_hi); + v.extend(value); + v.push(ts_lo); + v.push(ts_hi); + v.push(BusValue::constant(w2)); + v.push(BusValue::constant(0)); + v.push(BusValue::constant(w8)); + v +} + +/// `[is_register, base_lo, base_hi, value[8], ts_lo, ts_hi, w2, w4, w8]` — the +/// 16-element MEMW **write** tuple (MEMW supplies `old`). +fn memw_write( + value: [BusValue; 8], + base_lo: BusValue, + base_hi: BusValue, + ts_lo: BusValue, + ts_hi: BusValue, +) -> Vec { + let mut v = Vec::with_capacity(16); + v.push(BusValue::constant(0)); // is_register = 0 (memory) + v.push(base_lo); + v.push(base_hi); + v.extend(value); + v.push(ts_lo); + v.push(ts_hi); + v.push(BusValue::constant(0)); // w2 + v.push(BusValue::constant(0)); // w4 + v.push(BusValue::constant(1)); // w8 + v +} + +/// A register value `[lo, hi, 0, 0, 0, 0, 0, 0]` as MEMW value elements. +fn register_value(lo: BusValue, hi: BusValue) -> [BusValue; 8] { + let mut v: [BusValue; 8] = std::array::from_fn(|_| BusValue::constant(0)); + v[0] = lo; + v[1] = hi; + v +} + +/// The eight bytes of a 64-byte operand's doubleword `chunk`, taken from two +/// 32-byte column blocks laid out back to back. +fn operand_dword(lo_col: usize, hi_col: usize, chunk: usize) -> [BusValue; 8] { + std::array::from_fn(|b| { + let byte = 8 * chunk + b; + if byte < 32 { + packed(lo_col + byte) + } else { + packed(hi_col + byte - 32) + } + }) +} + +/// The same, for a compile-time 64-byte constant operand. +fn const_operand_dword(bytes: &[u8; 64], chunk: usize) -> [BusValue; 8] { + std::array::from_fn(|b| BusValue::constant(bytes[8 * chunk + b] as u64)) +} + +/// Byte `byte_idx` of a bit-decomposed 256-bit scalar: `Σ 2^j · bit[8·idx + j]`. +fn scalar_byte(base: usize, byte_idx: usize) -> BusValue { + BusValue::linear( + (0..8) + .map(|j| LinearTerm::Column { + coefficient: 1i64 << j, + column: base + 8 * byte_idx + j, + }) + .collect(), + ) +} + +/// The eight bytes of `u1‖u2`'s doubleword `chunk`, from the bit columns. +fn scalar_dword(chunk: usize) -> [BusValue; 8] { + std::array::from_fn(|b| { + let byte = 8 * chunk + b; + if byte < 32 { + scalar_byte(cols::U1, byte) + } else { + scalar_byte(cols::U2, byte - 32) + } + }) +} + +/// `col + offset` as a bus element (an operand's per-doubleword base address). +fn addr_plus(col: usize, offset: i64) -> BusValue { + BusValue::linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: col, + }, + LinearTerm::Constant(offset), + ]) +} + +// ========================================================================= +// Bus interactions +// ========================================================================= + +pub fn bus_interactions() -> Vec { + let mu = || Multiplicity::Column(cols::MU); + let ok = || Multiplicity::Column(cols::OK); + let ts_lo = || packed(cols::TIMESTAMP_0); + let ts_hi = || packed(cols::TIMESTAMP_1); + let mut out = Vec::new(); + + // --- MU-gated: the ECALL receive and the status write ------------------- + + // ECALL receiver: [ts_lo, ts_hi, syscall_lo32, syscall_hi32]. + out.push(BusInteraction::receiver( + BusId::Ecall, + mu(), + vec![ + ts_lo(), + ts_hi(), + BusValue::constant(ECSM_LINCOMB2_SYSCALL_NUMBER & 0xFFFF_FFFF), + BusValue::constant(ECSM_LINCOMB2_SYSCALL_NUMBER >> 32), + ], + )); + + // Combined read+write of x10: old = the result address `a0`, new = STATUS. + // The COMMIT chip sets the precedent for an accelerator writing a register + // during its ecall (`commit.rs`, "read+write x10"); ECALL decode's + // `write_register = false` governs the CPU row's own write path only. + out.push(BusInteraction::sender( + BusId::Memw, + mu(), + memw_read( + register_value(packed(cols::ADDR_Q_0), packed(cols::ADDR_Q_1)), + register_value(packed(cols::STATUS), BusValue::constant(0)), + 1, + BusValue::constant(2 * 10), + BusValue::constant(0), + ts_lo(), + ts_hi(), + 1, + 0, + ), + )); + + // --- OK-gated: everything else ------------------------------------------ + + // Register reads of a1/a2/a3. + for (reg, lo, hi) in [ + (11usize, cols::ADDR_P1_0, cols::ADDR_P1_1), + (12, cols::ADDR_P2_0, cols::ADDR_P2_1), + (13, cols::ADDR_U_0, cols::ADDR_U_1), + ] { + let value = register_value(packed(lo), packed(hi)); + out.push(BusInteraction::sender( + BusId::Memw, + ok(), + memw_read( + value.clone(), + value, + 1, + BusValue::constant(2 * reg as u64), + BusValue::constant(0), + ts_lo(), + ts_hi(), + 1, + 0, + ), + )); + } + + // Read P1 (8 doublewords at a1 + 8i) with CONSTANT values: this is what + // pins `P1 = G` with zero columns. + for i in 0..8 { + let value = const_operand_dword(&GENERATOR_LE, i); + out.push(BusInteraction::sender( + BusId::Memw, + ok(), + memw_read( + value.clone(), + value, + 0, + addr_plus(cols::ADDR_P1_0, (8 * i) as i64), + packed(cols::ADDR_P1_1), + ts_lo(), + ts_hi(), + 0, + 1, + ), + )); + } + + // Read P2 (8 doublewords at a2 + 8i). + for i in 0..8 { + let value = operand_dword(cols::X_P2, cols::Y_P2, i); + out.push(BusInteraction::sender( + BusId::Memw, + ok(), + memw_read( + value.clone(), + value, + 0, + addr_plus(cols::ADDR_P2_0, (8 * i) as i64), + packed(cols::ADDR_P2_1), + ts_lo(), + ts_hi(), + 0, + 1, + ), + )); + } + + // Read u1‖u2 (8 doublewords at a3 + 8i), reassembled from the bit columns. + for i in 0..8 { + let value = scalar_dword(i); + out.push(BusInteraction::sender( + BusId::Memw, + ok(), + memw_read( + value.clone(), + value, + 0, + addr_plus(cols::ADDR_U_0, (8 * i) as i64), + packed(cols::ADDR_U_1), + ts_lo(), + ts_hi(), + 0, + 1, + ), + )); + } + + // Write xQ‖yQ (8 doublewords at a0 + 8i). OK-gated: the executor writes + // nothing on the error path, so there must be no claimed write either. + for i in 0..8 { + out.push(BusInteraction::sender( + BusId::Memw, + ok(), + memw_write( + operand_dword(cols::X_Q, cols::Y_Q, i), + addr_plus(cols::ADDR_Q_0, (8 * i) as i64), + packed(cols::ADDR_Q_1), + ts_lo(), + ts_hi(), + ), + )); + } + + // ARE_BYTES range checks, paired: one send checks BOTH elements. Only the + // membership sub-witness needs them — `X_P2`/`Y_P2` are byte-checked at + // store time (the authority today's `xG`/`k` also rely on), and every other + // point block is inherited through a keyed tuple. + // `collect_bitwise_from_ecsm2` mirrors this layout exactly. + for base in [cols::MEM_X2, cols::MEM_Q0, cols::MEM_Q1] { + for i in 0..16 { + out.push(BusInteraction::sender( + BusId::AreBytes, + ok(), + vec![packed(base + 2 * i), packed(base + 2 * i + 1)], + )); + } + } + out.push(BusInteraction::sender( + BusId::AreBytes, + ok(), + vec![packed(cols::mem_q1(32)), BusValue::constant(0)], + )); + + // IS_HALF on the shifted membership carries, then the five overflow blocks. + let half_offset = |col: usize, off: i64| { + BusValue::linear(vec![ + LinearTerm::Column { + coefficient: 1, + column: col, + }, + LinearTerm::Constant(off), + ]) + }; + for i in 0..63 { + out.push(BusInteraction::sender( + BusId::IsHalfword, + ok(), + vec![half_offset(cols::mem_c0(i), CARRY_OFFSET_X2)], + )); + } + for i in 0..63 { + out.push(BusInteraction::sender( + BusId::IsHalfword, + ok(), + vec![half_offset(cols::mem_c1(i), CARRY_OFFSET_YG)], + )); + } + for base in [ + cols::Y_P2_SUB_P, + cols::U1_SUB_N, + cols::U2_SUB_N, + cols::X_Q_SUB_P, + cols::Y_Q_SUB_P, + ] { + for i in 0..16 { + out.push(BusInteraction::sender( + BusId::IsHalfword, + ok(), + vec![packed(base + i)], + )); + } + } + + // ZERO bus: assert u1 != 0 and u2 != 0. The `< N` overflow witness admits + // zero (`N + (2^256 − N)` overflows), so this is the check that excludes it. + for base in [cols::U1, cols::U2] { + out.push(BusInteraction::sender( + BusId::Zero, + ok(), + vec![ + BusValue::linear( + (0..256) + .map(|b| LinearTerm::Column { + coefficient: 1i64 << (b % 8), + column: base + b, + }) + .collect(), + ), + BusValue::constant(0), // expected ZERO output = 0 ⇒ input is nonzero + ], + )); + } + + // JointBit receivers, one per (bit position, stream). Multiplicity `2·bit`, + // NOT `bit`: a set digit is carried by both the round's doubling and its + // add, and both send. The 2× is what forces the add to exist at all — with + // only the doubling available the total can never reach 2. + for (base, stream) in [(cols::U1, STREAM_U1), (cols::U2, STREAM_U2)] { + for i in 0..256 { + out.push(BusInteraction::receiver( + BusId::JointBit, + Multiplicity::Linear(vec![LinearTerm::Column { + coefficient: 2, + column: base + i, + }]), + vec![ + ts_lo(), + ts_hi(), + BusValue::constant(i as u64), + BusValue::constant(stream), + ], + )); + } + } + + // Addend publishes. Every coordinate is pinned somewhere else: G is a + // constant, P2 is MEMW-bound, P12 is the phase-0 drain, and the correction + // constant is the EC_T0 lookup. So balance on this bus leaves the chain no + // free addend anywhere. + let g_x = || const_coord(&GENERATOR_LE[..32]); + let g_y = || const_coord(&GENERATOR_LE[32..]); + for (sel, x, y, mult) in [ + (SEL_P1, g_x(), g_y(), Multiplicity::Column(cols::N1)), + ( + SEL_P2, + coord(cols::X_P2), + coord(cols::Y_P2), + Multiplicity::Column(cols::N2), + ), + ( + SEL_P12, + coord(cols::X_P12), + coord(cols::Y_P12), + Multiplicity::Column(cols::N3), + ), + // Exactly one correction row per proven ecall, so its count IS `OK`. + (SEL_CORRECTION, coord(cols::X_T0N), coord(cols::Y_T0N), ok()), + ] { + out.push(BusInteraction::sender( + BusId::Addend, + mult, + addend_tuple(ts_lo(), ts_hi(), BusValue::constant(sel), x, y), + )); + } + + // EC_T0 lookup: send a plain `len`; the table's receive key is `LEN_M1 + 1`, + // so the −1 storage encoding stays entirely on its side. + { + let mut values = vec![addr_plus(cols::LEN_M1, 1)]; + values.extend(coord(cols::X_T0N)); + values.extend(coord(cols::Y_T0N)); + out.push(BusInteraction::sender(BusId::EcT0, ok(), values)); + } + + // The three chain segments, each pinned at both ends at multiplicity OK. + // A chain row can only execute in phase q if some sender published phase q, + // and the drains are received on the very columns the range checks and the + // output write bind — so both telescoping breaks are closed at both ends. + let seed_round = |r: BusValue| r; + let drain_round = || BusValue::linear(vec![LinearTerm::Constant(-1)]); + + // phase 0 — precompute: a = P1 = G, addend = P2, result = P12. + out.push(BusInteraction::sender( + BusId::Ecdas, + ok(), + joint_tuple( + g_x(), + g_y(), + BusValue::constant(0), + seed_round(BusValue::constant(0)), + BusValue::constant(1), // op = add + ts_lo(), + ts_hi(), + ), + )); + out.push(BusInteraction::receiver( + BusId::Ecdas, + ok(), + joint_tuple( + coord(cols::X_P12), + coord(cols::Y_P12), + BusValue::constant(0), + drain_round(), + BusValue::constant(0), + ts_lo(), + ts_hi(), + ), + )); + + // phase 1 — main chain: seeded at the NUMS blind T₀ and round `len − 1`. + out.push(BusInteraction::sender( + BusId::Ecdas, + ok(), + joint_tuple( + const_coord(&T0_X_LE), + const_coord(&T0_Y_LE), + BusValue::constant(1), + seed_round(packed(cols::LEN_M1)), + BusValue::constant(0), // op = double + ts_lo(), + ts_hi(), + ), + )); + out.push(BusInteraction::receiver( + BusId::Ecdas, + ok(), + joint_tuple( + coord(cols::ACC_X), + coord(cols::ACC_Y), + BusValue::constant(1), + drain_round(), + BusValue::constant(0), + ts_lo(), + ts_hi(), + ), + )); + + // phase 2 — correction: the phase-1 drain relayed straight back out. A + // direct chain hand-off is not expressible, because the outgoing tuple pins + // the successor's `op` to `NB`, which is 0 on the last main row while the + // correction row is an add. + out.push(BusInteraction::sender( + BusId::Ecdas, + ok(), + joint_tuple( + coord(cols::ACC_X), + coord(cols::ACC_Y), + BusValue::constant(2), + seed_round(BusValue::constant(0)), + BusValue::constant(1), // op = add + ts_lo(), + ts_hi(), + ), + )); + out.push(BusInteraction::receiver( + BusId::Ecdas, + ok(), + joint_tuple( + coord(cols::X_Q), + coord(cols::Y_Q), + BusValue::constant(2), + drain_round(), + BusValue::constant(0), + ts_lo(), + ts_hi(), + ), + )); + + out +} + +// ========================================================================= +// Constraints +// ========================================================================= + +/// Which membership convolution relation a carry constraint enforces. +#[derive(Clone, Copy)] +pub enum Relation { + /// `xP2² − x2 − q0·p = 0` + X2, + /// `yP2² + OK·p² − xP2·x2 − OK·b − q1·p = 0` + Yg, +} + +/// The addition-overflow range checks, whose 8 word-carries `c` are virtual: +/// `c_i = 2^-32·(addend0_i + addend1_i + c_{i-1} − sum_i)`. The addition must +/// overflow `2^256` (carry-out `c_7 = 1`), which proves the strict inequality. +#[derive(Clone, Copy)] +pub enum OverflowKind { + /// `p + yP2_sub_p = yP2 + 2^256` + Yp2LtP, + /// `N + u1_sub_N = u1 + 2^256` + U1LtN, + U2LtN, + /// `p + xQ_sub_p = xQ + 2^256` + XqLtP, + YqLtP, +} + +impl OverflowKind { + /// The constant addend's 32-bit word `i`. + fn const_word(self, i: usize) -> u64 { + let bytes = match self { + OverflowKind::U1LtN | OverflowKind::U2LtN => &N_BYTES, + _ => &P_BYTES, + }; + let mut w = 0u64; + for b in 0..4 { + w += (bytes[4 * i + b] as u64) << (8 * b); + } + w + } + /// Column base of the witnessed halfword addend. + fn addend_hl_base(self) -> usize { + match self { + OverflowKind::Yp2LtP => cols::Y_P2_SUB_P, + OverflowKind::U1LtN => cols::U1_SUB_N, + OverflowKind::U2LtN => cols::U2_SUB_N, + OverflowKind::XqLtP => cols::X_Q_SUB_P, + OverflowKind::YqLtP => cols::Y_Q_SUB_P, + } + } + /// Column base of the sum. + fn sum_col_base(self) -> usize { + match self { + OverflowKind::Yp2LtP => cols::Y_P2, + OverflowKind::U1LtN => cols::U1, + OverflowKind::U2LtN => cols::U2, + OverflowKind::XqLtP => cols::X_Q, + OverflowKind::YqLtP => cols::Y_Q, + } + } + /// Whether the sum is stored as 256 individual bits rather than 32 bytes. + fn sum_is_bits(self) -> bool { + matches!(self, OverflowKind::U1LtN | OverflowKind::U2LtN) + } +} + +// ========================================================================= +// Single-body constraint set (ConstraintSet front-end) +// ========================================================================= +// +// Constraint indices 0..=692 (693 total): +// 0 : IS_BIT(MU) +// 1 : IS_BIT(OK) +// 2 : OK · (1 − MU) (OK ⇒ MU) +// 3 : OK · STATUS (OK ⇒ status is 0) +// 4 : MU · (STATUS·S_INV − (1 − OK)) (¬OK ⇒ status is non-zero) +// 5..=260 : IS_BIT(u1[i]) +// 261..=516: IS_BIT(u2[i]) +// 517, 518 : (Σ u_bit)·(1 − OK) (no phantom JointBit receives) +// 519..=521: N1/N2/N3 · (1 − OK) (no phantom Addend publishes) +// 522..=586: ConvCarry(X2, 0..64) + ColIsZero(mem_c0(63)) +// 587..=651: ConvCarry(Yg, 0..64) + ColIsZero(mem_c1(63)) +// 652 : IS_BIT(mem_q1(32)) +// 653..=692: 5 × (7 CarryBit + 1 OverflowRequired) + +use stark::constraints::builder::{ConstraintBuilder, ConstraintSet}; + +/// ECSM2 transition constraints as a single-source [`ConstraintSet`] (693 +/// total). No column configuration needed (the layout is fixed via `cols`). +pub struct Ecsm2Constraints; + +impl Ecsm2Constraints { + /// Byte `m` of the field prime `P` (zero beyond 32 bytes). + fn p_byte_expr>( + b: &B, + m: usize, + ) -> B::Expr { + if m < 32 { + b.const_base(P_BYTES[m] as u64) + } else { + b.zero() + } + } + + /// `bytes[base + j]` for `j < len`, else zero. + fn byte_at>( + b: &B, + base: usize, + len: usize, + j: usize, + ) -> B::Expr { + if j < len { + b.main(0, base + j) + } else { + b.zero() + } + } + + /// `S_i` for `relation` at limb `i`. Structurally identical to the ECSM + /// generator-membership body, with `OK` in place of `µ` as the gate for the + /// `p²` and `b` constants — so an error row zeroes to `0 = 0` exactly like a + /// padding row. + fn s_i>( + b: &B, + relation: Relation, + i: usize, + ) -> B::Expr { + let byte = |base: usize, len: usize, j: usize| Self::byte_at(b, base, len, j); + let mut s = b.zero(); + match relation { + Relation::X2 => { + // Σ xP2_j·xP2_{i-j} − x2_i − Σ q0_j·P_{i-j} + for j in 0..=i { + s = s + byte(cols::X_P2, 32, j) * byte(cols::X_P2, 32, i - j); + s = s - byte(cols::MEM_Q0, 32, j) * Self::p_byte_expr(b, i - j); + } + s = s - byte(cols::MEM_X2, 32, i); + } + Relation::Yg => { + // Σ (yP2_j·yP2_{i-j} + OK·P_j·P_{i-j} − x2_j·xP2_{i-j} − q1_j·P_{i-j}) − OK·b_i + let ok = b.main(0, cols::OK); + let mut p2 = b.zero(); + for j in 0..=i { + s = s + byte(cols::Y_P2, 32, j) * byte(cols::Y_P2, 32, i - j); + p2 = p2 + Self::p_byte_expr(b, j) * Self::p_byte_expr(b, i - j); + s = s - byte(cols::MEM_X2, 32, j) * byte(cols::X_P2, 32, i - j); + s = s - byte(cols::MEM_Q1, 33, j) * Self::p_byte_expr(b, i - j); + } + s = s + ok.clone() * p2; + if i == 0 { + let curve_b = b.const_base(B); + s = s - ok * curve_b; + } + } + } + s + } + + /// `256·c_i − c_{i-1} − S_i`. + fn conv_carry>( + b: &B, + relation: Relation, + i: usize, + ) -> B::Expr { + let c_base = match relation { + Relation::X2 => cols::MEM_C0, + Relation::Yg => cols::MEM_C1, + }; + let c_i = b.main(0, c_base + i); + let c_prev = if i == 0 { + b.zero() + } else { + b.main(0, c_base + i - 1) + }; + let two_pow_8 = b.const_base(256); + two_pow_8 * c_i - c_prev - Self::s_i(b, relation, i) + } + + /// The 8 word-carries of the `kind` addition. Scalars are summed from their + /// 256 individual bit columns; coordinates from their 32 byte columns. + fn carry_chain>( + b: &B, + kind: OverflowKind, + ) -> [B::Expr; 8] { + let hl = kind.addend_hl_base(); + let base = kind.sum_col_base(); + let mut c: [B::Expr; 8] = std::array::from_fn(|_| b.zero()); + let mut prev = b.zero(); + for (i, slot) in c.iter_mut().enumerate() { + // addend1 word i (from halfwords): hl[2i] + 2^16·hl[2i+1] + let shift_16 = b.const_base(1u64 << 16); + let addend1 = b.main(0, hl + 2 * i) + b.main(0, hl + 2 * i + 1) * shift_16; + let mut sum = b.zero(); + if kind.sum_is_bits() { + for bit in 0..32 { + let shift = b.const_base(1u64 << bit); + sum = sum + b.main(0, base + 32 * i + bit) * shift; + } + } else { + for byte in 0..4 { + let shift = b.const_base(1u64 << (8 * byte)); + sum = sum + b.main(0, base + 4 * i + byte) * shift; + } + } + let addend0 = b.const_base(kind.const_word(i)); + let inv = b.const_base(INV_SHIFT_32); + let ci = (addend0 + addend1 + prev.clone() - sum) * inv; + *slot = ci.clone(); + prev = ci; + } + c + } +} + +impl ConstraintSet for Ecsm2Constraints { + // The overflow carry-bit constraints (OK·c·(1−c)) and the status-inverse + // binding are degree 3. + fn max_degree(&self) -> usize { + 3 + } + + fn eval>(&self, b: &mut B) { + // idx 0, 1: IS_BIT(MU), IS_BIT(OK). + for (i, col) in [cols::MU, cols::OK].into_iter().enumerate() { + let x = b.main(0, col); + let one = b.one(); + b.emit_base(i, x.clone() * (one - x)); + } + + // idx 2: OK·(1 − MU) = 0. A proven chain implies a real ecall. + let ok = b.main(0, cols::OK); + let mu = b.main(0, cols::MU); + let one = b.one(); + b.emit_base(2, ok * (one - mu)); + + // idx 3: OK·STATUS = 0. Claiming the chain forces the status to 0. + let ok = b.main(0, cols::OK); + let status = b.main(0, cols::STATUS); + b.emit_base(3, ok * status); + + // idx 4: MU·(STATUS·S_INV − (1 − OK)) = 0. On a real ecall that does NOT + // claim the chain, the status must be invertible, i.e. non-zero. This is + // the constraint that makes `status == 0` *oblige* the proof: without it + // a prover sets OK = 0, writes status 0, and the guest reads a fabricated + // Q out of memory. MU-gated so all-zero padding rows are free; the + // witnessed inverse keeps the per-variant error codes distinguishable. + let mu = b.main(0, cols::MU); + let status = b.main(0, cols::STATUS); + let s_inv = b.main(0, cols::S_INV); + let one = b.one(); + let ok = b.main(0, cols::OK); + b.emit_base(4, mu * (status * s_inv - (one - ok))); + + let mut idx = 5; + + // idx 5..=516: IS_BIT on both scalars' 512 bits. + for base in [cols::U1, cols::U2] { + for i in 0..256 { + let x = b.main(0, base + i); + let one = b.one(); + b.emit_base(idx, x.clone() * (one - x)); + idx += 1; + } + } + + // idx 517, 518: (Σ u_bit)·(1 − OK) = 0. Scalar bits are the JointBit + // receive multiplicities, so a non-OK row with live bits would fire + // phantom receives. + for base in [cols::U1, cols::U2] { + let mut sum = b.zero(); + for i in 0..256 { + sum = sum + b.main(0, base + i); + } + let ok = b.main(0, cols::OK); + let one = b.one(); + b.emit_base(idx, sum * (one - ok)); + idx += 1; + } + + // idx 519..=521: the addend publish counts vanish on non-OK rows, for + // the same reason. + for col in [cols::N1, cols::N2, cols::N3] { + let n = b.main(0, col); + let ok = b.main(0, cols::OK); + let one = b.one(); + b.emit_base(idx, n * (one - ok)); + idx += 1; + } + + // P2 membership: x2 convolution (64 carries + closing), then y². + for (relation, c_base) in [(Relation::X2, cols::MEM_C0), (Relation::Yg, cols::MEM_C1)] { + for i in 0..64 { + let root = Self::conv_carry(b, relation, i); + b.emit_base(idx, root); + idx += 1; + } + let c_last = b.main(0, c_base + 63); + b.emit_base(idx, c_last); + idx += 1; + } + + // idx 652: IS_BIT(mem_q1[32]) — the 33rd quotient byte is a single bit. + let q1_32 = b.main(0, cols::mem_q1(32)); + let one = b.one(); + b.emit_base(idx, q1_32.clone() * (one - q1_32)); + idx += 1; + + // The five overflow checks: 7 carry bits (deg 3) + overflow-required + // (deg 2) each, all OK-gated so error and padding rows close at zero. + for kind in [ + OverflowKind::Yp2LtP, + OverflowKind::U1LtN, + OverflowKind::U2LtN, + OverflowKind::XqLtP, + OverflowKind::YqLtP, + ] { + let c = Self::carry_chain(b, kind); + for ci in c.iter().take(7) { + let ok = b.main(0, cols::OK); + let one = b.one(); + b.emit_base(idx, ok * ci.clone() * (one - ci.clone())); + idx += 1; + } + let ok = b.main(0, cols::OK); + let one = b.one(); + b.emit_base(idx, ok * (one - c[7].clone())); + idx += 1; + } + + debug_assert_eq!(idx, 693); + } +} diff --git a/prover/src/tables/mod.rs b/prover/src/tables/mod.rs index 0a86e4149..a053548b1 100644 --- a/prover/src/tables/mod.rs +++ b/prover/src/tables/mod.rs @@ -29,8 +29,11 @@ pub mod cpu; pub mod cpu32; pub mod decode; pub mod dvrm; +pub mod ec_t0; pub mod ecdas; +pub mod ecdas2; pub mod ecsm; +pub mod ecsm2; pub mod eq; pub mod global_memory; pub mod halt; @@ -53,7 +56,7 @@ pub mod trace_builder; pub use types::BusId; /// Blowup factors for which we ship static preprocessed-table commitments -/// (bitwise and keccak_rc), pinned by the `static_commitments_tests` drift +/// (bitwise, keccak_rc and ec_t0), pinned by the `static_commitments_tests` drift /// suite and emitted by the `compute_static_commitments` binary. Shared /// between the generator and the drift tests so adding a blowup here cannot /// silently skip a test. diff --git a/prover/src/tables/trace_builder.rs b/prover/src/tables/trace_builder.rs index 0ba99e619..457b005ed 100644 --- a/prover/src/tables/trace_builder.rs +++ b/prover/src/tables/trace_builder.rs @@ -47,8 +47,11 @@ use super::cpu::{self, CpuOperation}; use super::cpu32; use super::decode; use super::dvrm::{self, DvrmOperation}; +use super::ec_t0; use super::ecdas; +use super::ecdas2; use super::ecsm; +use super::ecsm2; use super::eq; use super::halt; use super::keccak::{self, KeccakOperation}; @@ -532,7 +535,7 @@ fn build_reg_fallback( /// MEMW and LOAD collection requires sequential processing with state tracking. /// /// Returns: (memw_buckets, load_ops, lt_ops, shift_ops, bitwise_ops, commit_ops, -/// keccak_ops, cpu32_ops, ecsm_ops, ecdas_ops) +/// keccak_ops, cpu32_ops, ecsm_ops, ecdas_ops, ecsm2_ops, ecdas2_ops) #[allow(clippy::type_complexity)] fn collect_ops_from_cpu( cpu_ops: &[CpuOperation], @@ -549,6 +552,8 @@ fn collect_ops_from_cpu( Vec, Vec, Vec, + Vec, + Vec, ) { let mut memw = MemwBuckets::with_register_capacity(cpu_ops.len() * 3); let mut load_ops = Vec::with_capacity(cpu_ops.len() / 8 + 1); @@ -560,6 +565,8 @@ fn collect_ops_from_cpu( let mut cpu32_ops = Vec::new(); let mut ecsm_ops = Vec::new(); let mut ecdas_ops = Vec::new(); + let mut ecsm2_ops = Vec::new(); + let mut ecdas2_ops = Vec::new(); // Seed from the carried x254 (0 for a monolithic run or the first epoch) so a // continuation epoch indexes its commits globally, matching the x254 the // register binding transports across epochs. Resetting to 0 here would drift @@ -654,6 +661,17 @@ fn collect_ops_from_cpu( ecdas_ops.extend(ecdas_rows); } + // Collect lincomb2 ecall operations (memory I/O + the two joint-chain + // table row sets). Independent of the single-scalar path above: the two + // accelerators coexist until the guest switches over. + if op.ecall_lincomb2 { + let (lc2_memw, ecsm2_op, ecdas2_rows) = + collect_lincomb2_ops(op, memory_state, register_state); + memw.extend_ops(lc2_memw); + ecsm2_ops.push(ecsm2_op); + ecdas2_ops.extend(ecdas2_rows); + } + // --- ALU chip dispatch (no state tracking) --- // Word (`*W`) instructions are delegated to CPU32 (which itself drives // the ALU chips); the main CPU does not send the ALU bus for them, so we @@ -709,6 +727,8 @@ fn collect_ops_from_cpu( cpu32_ops, ecsm_ops, ecdas_ops, + ecsm2_ops, + ecdas2_ops, ) } @@ -948,6 +968,164 @@ fn collect_ecsm_ops( (memw_ops, ecsm_op, ecdas_ops) } +/// Collects all MEMW ops and the ECSM2 / ECDAS2 table ops for one lincomb2 ecall. +/// +/// Timestamp scheme: **everything at `T`**. The executor's address guards make +/// the four 64-byte operand regions pairwise disjoint and 8-byte aligned, and +/// register addresses live in a separate address space, so no two accesses touch +/// the same byte — the same single-timestamp pattern KECCAK uses for its 25 +/// lanes, rather than ECSM's `T`/`T+1`/`T+2` spread. +/// +/// The executor retains no witness (one is ~820 KiB), so this re-derives the +/// outcome by calling [`lincomb2_outcome`] — the very function the executor arm +/// calls — which is why the two sides cannot disagree about the status or about +/// which rows exist. +/// +/// On the error path (`status != 0`) only the `x10` read+write is emitted: the +/// chip claims nothing else, so nothing else may appear in the access chain. In +/// particular the `a1` reads must NOT be emitted, because the chip asserts they +/// return `G` and `status == 7` is exactly the case where they do not. +fn collect_lincomb2_ops( + op: &CpuOperation, + memory_state: &mut MemoryState, + register_state: &mut RegisterState, +) -> ( + Vec, + ecsm2::Ecsm2Operation, + Vec, +) { + let t = op.timestamp; + // x10 still holds the pre-ecall value here: ECALL decodes with `rs1 = 17` + // and `write_register = false`, so the CPU row never touches x10. + let addr_q = register_state.read(10).0; + debug_assert_eq!( + addr_q, op.lincomb2_addr_q, + "lincomb2: x10 in the register model must match the address the CPU log carried" + ); + let addr_p1 = register_state.read(11).0; + let addr_p2 = register_state.read(12).0; + let addr_u = register_state.read(13).0; + + let read_operand = |memory_state: &MemoryState, addr: u64| { + let mut out = [0u8; 64]; + for (i, byte) in out.iter_mut().enumerate() { + *byte = memory_state.read_byte(addr.wrapping_add(i as u64)).0; + } + out + }; + let p1 = read_operand(memory_state, addr_p1); + let p2 = read_operand(memory_state, addr_p2); + let u = read_operand(memory_state, addr_u); + + let outcome = executor::vm::instruction::execution::lincomb2_outcome(&p1, &p2, &u); + debug_assert_eq!( + outcome.status, op.lincomb2_status, + "lincomb2: the trace builder's replay must reproduce the executor's status" + ); + + let mut memw_ops = Vec::with_capacity(37); + + // Combined read+write of x10: old = the result address, new = the status. + // Emitted on BOTH paths — it is what makes the error row expressible. + { + let old_value = pack_register_value(addr_q); + let new_value = pack_register_value(outcome.status); + let (_old_val, old_ts) = register_state.read(10); + memw_ops.push( + MemwOperation::new(true, 2 * 10, new_value, t, 2, true) + .with_old(old_value, [old_ts, old_ts, 0, 0, 0, 0, 0, 0]), + ); + register_state.write(10, outcome.status, t); + } + + let Some(witness) = outcome.witness else { + let ecsm2_op = ecsm2::Ecsm2Operation { + timestamp: t, + addr_q, + addr_p1, + addr_p2, + addr_u, + status: outcome.status, + witness: None, + }; + return (memw_ops, ecsm2_op, Vec::new()); + }; + + // Register reads of a1/a2/a3. + for (reg, val) in [(11u8, addr_p1), (12, addr_p2), (13, addr_u)] { + let value = pack_register_value(val); + let (_old_val, old_ts) = register_state.read(reg); + memw_ops.push( + MemwOperation::new(true, 2 * reg as u64, value, t, 2, true) + .with_old(value, [old_ts, old_ts, 0, 0, 0, 0, 0, 0]), + ); + register_state.write(reg, val, t); + } + + // The three 64-byte operand reads (8 doublewords each). `p1` is read back + // from memory rather than from the witness because the chip asserts the + // constant `G` there and `lincomb2_outcome` has already established they + // agree (status 7 otherwise) — asserted so a future ABI change that drops + // that guarantee fails here, not as an opaque constraint violation. + debug_assert_eq!( + p1, + executor::vm::instruction::execution::GENERATOR_LE, + "lincomb2: an OK outcome implies the bytes at a1 are the generator, which \ + is what the chip's constant-valued MEMW reads assert", + ); + for (base, bytes) in [(addr_p1, &p1), (addr_p2, &p2), (addr_u, &u)] { + for i in 0..8 { + let addr = base.wrapping_add((8 * i) as u64); + let mut value = [0u32; 8]; + let mut dword = 0u64; + for j in 0..8 { + value[j] = bytes[8 * i + j] as u32; + dword |= (bytes[8 * i + j] as u64) << (8 * j); + } + let (_old, old_ts) = memory_state.read_bytes(addr, 8); + memw_ops + .push(MemwOperation::new(false, addr, value, t, 8, true).with_old(value, old_ts)); + memory_state.write_bytes(addr, dword, 8, t); + } + } + + // The 64-byte result write (8 doublewords), OK path only. + let mut q_bytes = [0u8; 64]; + q_bytes[..32].copy_from_slice(&witness.x_q); + q_bytes[32..].copy_from_slice(&witness.y_q); + for i in 0..8 { + let addr = addr_q.wrapping_add((8 * i) as u64); + let mut value = [0u32; 8]; + let mut dword = 0u64; + for j in 0..8 { + value[j] = q_bytes[8 * i + j] as u32; + dword |= (q_bytes[8 * i + j] as u64) << (8 * j); + } + let (old_vals, old_ts) = memory_state.read_bytes(addr, 8); + memw_ops + .push(MemwOperation::new(false, addr, value, t, 8, false).with_old(old_vals, old_ts)); + memory_state.write_bytes(addr, dword, 8, t); + } + + let ecdas2_ops = witness + .steps + .iter() + .cloned() + .map(|step| ecdas2::Ecdas2Operation { timestamp: t, step }) + .collect(); + let ecsm2_op = ecsm2::Ecsm2Operation { + timestamp: t, + addr_q, + addr_p1, + addr_p2, + addr_u, + status: outcome.status, + witness: Some(witness), + }; + + (memw_ops, ecsm2_op, ecdas2_ops) +} + /// Collects register read/write operations (M1, M3, M5) from CpuOperation, /// pushing them into `memw_ops`. fn collect_register_ops_from_cpu( @@ -2273,6 +2451,12 @@ fn is_byte_op(b: u8) -> BitwiseOperation { BitwiseOperation::byte_op(BitwiseOperationType::AreBytes, b, 0) } +/// Paired ARE_BYTES lookup: one send range-checks BOTH bytes (the BITWISE table +/// enumerates every `(x, y)` byte pair). Tuple order must match the sender's. +fn are_bytes_op(x: u8, y: u8) -> BitwiseOperation { + BitwiseOperation::byte_op(BitwiseOperationType::AreBytes, x, y) +} + /// BITWISE lookups sent by the ECSM core table (range checks + the `k != 0` ZERO check), /// so the BITWISE receiver multiplicities account for them. #[allow(clippy::needless_range_loop)] @@ -2280,17 +2464,16 @@ pub(crate) fn collect_bitwise_from_ecsm(ops: &[ecsm::EcsmOperation]) -> Vec Vec Vec Vec { + let mut out = Vec::new(); + for op in ops { + let Some(w) = op.witness.as_deref() else { + continue; + }; + // Paired ARE_BYTES on the membership sub-witness: (2i, 2i+1) over x2, + // q0 and q1's 32-byte prefix; q1[32] rides alone as [b, 0]. + for i in 0..16 { + out.push(are_bytes_op(w.mem_p2.x2[2 * i], w.mem_p2.x2[2 * i + 1])); + out.push(are_bytes_op(w.mem_p2.q0[2 * i], w.mem_p2.q0[2 * i + 1])); + out.push(are_bytes_op(w.mem_p2.q1[2 * i], w.mem_p2.q1[2 * i + 1])); + } + out.push(is_byte_op(w.mem_p2.q1[32])); + // IS_HALF on the shifted membership carries (i = 0..62). + for i in 0..63 { + out.push(is_half_op((w.mem_p2.c0[i] + ecsm2::CARRY_OFFSET_X2) as u16)); + out.push(is_half_op((w.mem_p2.c1[i] + ecsm2::CARRY_OFFSET_YG) as u16)); + } + // IS_HALF on the U256HL limbs of the five overflow blocks, in the same + // order `ecsm2::bus_interactions()` emits them. + for block in [ + &w.y_p2_sub_p, + &w.u1_sub_n, + &w.u2_sub_n, + &w.x_q_sub_p, + &w.y_q_sub_p, + ] { + for i in 0..16 { + out.push(is_half_op( + block[2 * i] as u16 + ((block[2 * i + 1] as u16) << 8), + )); + } + } + // ZERO: assert u1 != 0 and u2 != 0 (sum of each scalar's bytes). + for scalar in [&w.u1, &w.u2] { + let sum: u32 = scalar.iter().map(|&b| b as u32).sum(); + out.push(BitwiseOperation::zero(sum)); + } + } + out +} + +/// BITWISE lookups sent by every ECDAS2 row. The layout is identical to +/// `collect_bitwise_from_ecdas` — the addend columns `XB`/`YB` are deliberately +/// absent, since they inherit byte-ness through the Addend tuple. +#[allow(clippy::needless_range_loop)] +pub(crate) fn collect_bitwise_from_ecdas2( + ops: &[ecdas2::Ecdas2Operation], +) -> Vec { + let mut out = Vec::new(); + for op in ops { + let s = &op.step.step; + // The non-degeneracy block is derived, not carried by the witness. + let d = ecdas2::dinv_witness(&op.step); + for i in 0..16 { + out.push(are_bytes_op(s.lambda[2 * i], s.lambda[2 * i + 1])); + out.push(are_bytes_op(s.x_r[2 * i], s.x_r[2 * i + 1])); + out.push(are_bytes_op(s.y_r[2 * i], s.y_r[2 * i + 1])); + out.push(are_bytes_op(s.q0[2 * i], s.q0[2 * i + 1])); + out.push(are_bytes_op(s.q1[2 * i], s.q1[2 * i + 1])); + out.push(are_bytes_op(s.q2[2 * i], s.q2[2 * i + 1])); + out.push(are_bytes_op(d.d_inv[2 * i], d.d_inv[2 * i + 1])); + out.push(are_bytes_op(d.q3[2 * i], d.q3[2 * i + 1])); + } + out.push(are_bytes_op(s.round, s.q0[32])); + out.push(are_bytes_op(s.q1[32], s.q2[32])); + out.push(is_byte_op(d.q3[32])); + for i in 0..63 { + out.push(is_half_op((s.c0[i] + ecdas2::CARRY_OFFSET_LAMBDA) as u16)); + out.push(is_half_op((s.c1[i] + ecdas2::CARRY_OFFSET_XR) as u16)); + out.push(is_half_op((s.c2[i] + ecdas2::CARRY_OFFSET_YR) as u16)); + out.push(is_half_op((d.c3[i] + ecdas2::CARRY_OFFSET_DINV) as u16)); + } + } + out +} + /// Collect BITWISE lookups generated by the keccak chips. /// /// The keccak round chip sends BYTE_ALU and ARE_BYTES interactions (the θ/ρ @@ -2714,6 +2984,15 @@ pub struct Traces { /// ECDAS double/add table (variable rows per ecall) pub ecdas: TraceTable, + /// ECSM2 core table (one row per lincomb2 ecall) + pub ecsm2: TraceTable, + + /// ECDAS2 joint double/add table (variable rows per lincomb2 ecall) + pub ecdas2: TraceTable, + + /// EC_T0 preprocessed `−2^len·T₀` correction table (256 rows) + pub ec_t0: TraceTable, + /// MEMW_R register-only fast-path traces (split into chunks of max_rows::MEMW_R) pub memw_registers: Vec>, /// Local-to-global boundary table for continuation epochs. Empty unless the @@ -2756,6 +3035,9 @@ struct CollectedOps { // EC scalar-multiplication accelerator chips. ecsm_ops: Vec, ecdas_ops: Vec, + // EC lincomb2 (joint two-scalar) accelerator chips. + ecsm2_ops: Vec, + ecdas2_ops: Vec, } /// Chunk raw ops and generate one trace table per chunk. When `storage_mode` @@ -2810,6 +3092,8 @@ fn collect_all_ops( cpu32_ops: Vec, ecsm_ops: Vec, ecdas_ops: Vec, + ecsm2_ops: Vec, + ecdas2_ops: Vec, register_state: &mut RegisterState, is_final: bool, ) -> CollectedOps { @@ -2952,6 +3236,8 @@ fn collect_all_ops( cpu32_ops, ecsm_ops, ecdas_ops, + ecsm2_ops, + ecdas2_ops, } } @@ -2995,6 +3281,8 @@ fn build_traces( cpu32_ops, ecsm_ops, ecdas_ops, + ecsm2_ops, + ecdas2_ops, } = ops; // ===================================================================== @@ -3070,6 +3358,8 @@ fn build_traces( Box::new(|h| h.add_ops(&collect_bitwise_from_keccak(&keccak_ops))), Box::new(|h| h.add_ops(&collect_bitwise_from_ecsm(&ecsm_ops))), Box::new(|h| h.add_ops(&collect_bitwise_from_ecdas(&ecdas_ops))), + Box::new(|h| h.add_ops(&collect_bitwise_from_ecsm2(&ecsm2_ops))), + Box::new(|h| h.add_ops(&collect_bitwise_from_ecdas2(&ecdas2_ops))), Box::new(|h| add_padding_byte_checks(h, num_padding_rows)), ]; if let Some(image) = initial_image @@ -3356,6 +3646,24 @@ fn build_traces( // ECSM accelerator traces (empty/all-padding for programs that do not use ECSM). let gen_ecsm = || ecsm::generate_ecsm_trace(&ecsm_ops); let gen_ecdas = || ecdas::generate_ecdas_trace(&ecdas_ops); + // lincomb2 accelerator traces (empty/all-padding for programs that do not + // call the syscall). + let gen_ecsm2 = || ecsm2::generate_ecsm2_trace(&ecsm2_ops); + let gen_ecdas2 = || ecdas2::generate_ecdas2_trace(&ecdas2_ops); + // EC_T0's rows are constants fixed by the preprocessed commitment; only its + // multiplicities vary, one lookup per PROVEN lincomb2 evaluation (error rows + // send nothing, so they must not be counted here either). + let gen_ec_t0 = || { + let mut trace = ec_t0::generate_ec_t0_trace(); + ec_t0::update_multiplicities( + &mut trace, + ecsm2_ops + .iter() + .filter_map(|op| op.witness.as_deref()) + .map(|w| w.len), + ); + trace + }; let (mut cpus_slot, mut memws_slot, mut memw_aligneds_slot, mut memw_registers_slot) = (None, None, None, None); @@ -3367,7 +3675,8 @@ fn build_traces( let (mut pages_slot, mut register_slot, mut halt_slot) = (None, None, None); let (mut eqs_slot, mut bytewises_slot, mut stores_slot, mut cpu32s_slot) = (None, None, None, None); - let (mut ecsm_slot, mut ecdas_slot) = (None, None); + let (mut ecsm_slot, mut ecdas_slot, mut ec_t0_slot) = (None, None, None); + let (mut ecsm2_slot, mut ecdas2_slot) = (None, None); #[cfg(feature = "disk-spill")] let sequential = storage_mode == StorageMode::Disk || cfg!(not(feature = "parallel")); @@ -3409,6 +3718,9 @@ fn build_traces( spawn_into!(cpu32s_slot, gen_cpu32s); spawn_into!(ecsm_slot, gen_ecsm); spawn_into!(ecdas_slot, gen_ecdas); + spawn_into!(ecsm2_slot, gen_ecsm2); + spawn_into!(ecdas2_slot, gen_ecdas2); + spawn_into!(ec_t0_slot, gen_ec_t0); }); } else { cpus_slot = Some(gen_cpus()); @@ -3436,6 +3748,9 @@ fn build_traces( cpu32s_slot = Some(gen_cpu32s()); ecsm_slot = Some(gen_ecsm()); ecdas_slot = Some(gen_ecdas()); + ecsm2_slot = Some(gen_ecsm2()); + ecdas2_slot = Some(gen_ecdas2()); + ec_t0_slot = Some(gen_ec_t0()); } const PHASE5_RAN: &str = "phase 5 generation ran in one of the branches above"; @@ -3470,6 +3785,9 @@ fn build_traces( let mut halt_trace = halt_slot.expect(PHASE5_RAN); let ecsm_trace = ecsm_slot.expect(PHASE5_RAN); let ecdas_trace = ecdas_slot.expect(PHASE5_RAN); + let ecsm2_trace = ecsm2_slot.expect(PHASE5_RAN); + let ecdas2_trace = ecdas2_slot.expect(PHASE5_RAN); + let ec_t0_trace = ec_t0_slot.expect(PHASE5_RAN); // Fixed-size and per-page tables aren't built through `chunk_and_generate`, // so spill them here before returning. @@ -3537,6 +3855,9 @@ fn build_traces( keccak_rc: keccak_rc_trace, ecsm: ecsm_trace, ecdas: ecdas_trace, + ecsm2: ecsm2_trace, + ecdas2: ecdas2_trace, + ec_t0: ec_t0_trace, memw_registers, local_to_global, touched_memory_cells, @@ -3777,14 +4098,23 @@ pub fn count_table_lengths( } impl Traces { - /// Returns the total number of main-trace field elements across all tables. + /// Per-table main- and auxiliary-trace field-element counts, as + /// `(table_name, main_elements, aux_elements)`. /// - /// Counts only the main (base-field) trace columns — equivalent to SP1's - /// `main_area` — for apples-to-apples comparison with other zkVMs. + /// This is the **single source** for the two totals below, which now just + /// sum it — the per-table arithmetic exists once, so a table added to one + /// and forgotten in the other is not a failure mode. /// - /// Preprocessed columns (committed in a separate PCS round during setup, not at - /// proving time) are excluded: BITWISE (11), DECODE (5), REGISTER (2), PAGE (2). - pub fn total_field_elements(&self) -> u64 { + /// Split tables (CPU, MEMW, …) are reported as one entry summed over their + /// chunks: a chunk boundary is an artefact of `MaxRowsConfig` rather than + /// something a caller wants to see. Preprocessed columns are excluded from + /// the main count on the same basis as the totals — they are committed once + /// during setup, not at proving time. + /// + /// Added for the phase-H bench, which needs the EC share of a real block's + /// prover cells: the multiplier that turns a per-ecrecover win into a + /// whole-prover number. + pub fn field_elements_by_table(&self) -> Vec<(&'static str, u64, u64)> { use super::bitwise::NUM_PRECOMPUTED_COLS as BITWISE_PRECOMPUTED; use super::bitwise::cols::NUM_COLUMNS as BITWISE_COLS; use super::branch::cols::NUM_COLUMNS as BRANCH_COLS; @@ -3795,8 +4125,12 @@ impl Traces { use super::decode::NUM_PRECOMPUTED_COLS as DECODE_PRECOMPUTED; use super::decode::cols::NUM_COLUMNS as DECODE_COLS; use super::dvrm::cols::NUM_COLUMNS as DVRM_COLS; + use super::ec_t0::NUM_PRECOMPUTED_COLS as EC_T0_PRECOMPUTED; + use super::ec_t0::cols::NUM_COLUMNS as EC_T0_COLS; use super::ecdas::cols::NUM_COLUMNS as ECDAS_COLS; + use super::ecdas2::cols::NUM_COLUMNS as ECDAS2_COLS; use super::ecsm::cols::NUM_COLUMNS as ECSM_COLS; + use super::ecsm2::cols::NUM_COLUMNS as ECSM2_COLS; use super::eq::cols::NUM_COLUMNS as EQ_COLS; use super::halt::cols::NUM_COLUMNS as HALT_COLS; use super::keccak::cols::NUM_COLUMNS as KECCAK_COLS; @@ -3815,6 +4149,11 @@ impl Traces { use super::register::cols::NUM_COLUMNS as REGISTER_COLS; use super::shift::cols::NUM_COLUMNS as SHIFT_COLS; use super::store::cols::NUM_COLUMNS as STORE_COLS; + // ⌈N/2⌉ aux EF columns for a table with N bus interactions (LogUp packs + // two interactions per committed column). + fn aux_cols(n: usize) -> usize { + n.div_ceil(2) + } let Traces { cpus, @@ -3837,6 +4176,9 @@ impl Traces { keccak_rc, ecsm, ecdas, + ecsm2, + ecdas2, + ec_t0, memw_registers, eqs, bytewises, @@ -3848,193 +4190,204 @@ impl Traces { touched_memory_cells: _, } = self; - let mut total: u64 = 0; - for t in cpus { - total += (t.num_rows() * CPU_COLS) as u64; - } - total += (bitwise.num_rows() * (BITWISE_COLS - BITWISE_PRECOMPUTED)) as u64; - for t in lts { - total += (t.num_rows() * LT_COLS) as u64; - } - for t in shifts { - total += (t.num_rows() * SHIFT_COLS) as u64; - } - for t in memws { - total += (t.num_rows() * MEMW_COLS) as u64; - } - for t in memw_aligneds { - total += (t.num_rows() * MEMW_A_COLS) as u64; - } - for t in loads { - total += (t.num_rows() * LOAD_COLS) as u64; - } - total += (decode.num_rows() * (DECODE_COLS - DECODE_PRECOMPUTED)) as u64; - for t in muls { - total += (t.num_rows() * MUL_COLS) as u64; - } - for t in dvrms { - total += (t.num_rows() * DVRM_COLS) as u64; - } - for t in branches { - total += (t.num_rows() * BRANCH_COLS) as u64; - } - total += (halt.num_rows() * HALT_COLS) as u64; - total += (commit.num_rows() * COMMIT_COLS) as u64; - total += (register.num_rows() * (REGISTER_COLS - REGISTER_PREPROCESSED)) as u64; - for t in pages { - total += (t.num_rows() * (PAGE_COLS - PAGE_PREPROCESSED)) as u64; - } - for t in memw_registers { - total += (t.num_rows() * MEMW_R_COLS) as u64; - } - total += (keccak.num_rows() * KECCAK_COLS) as u64; - total += (keccak_rnd.num_rows() * KECCAK_RND_COLS) as u64; - total += (keccak_rc.num_rows() * (KECCAK_RC_COLS - KECCAK_RC_PRECOMPUTED)) as u64; - for t in eqs { - total += (t.num_rows() * EQ_COLS) as u64; - } - for t in bytewises { - total += (t.num_rows() * BYTEWISE_COLS) as u64; - } - for t in stores { - total += (t.num_rows() * STORE_COLS) as u64; - } - for t in cpu32s { - total += (t.num_rows() * CPU32_COLS) as u64; + let mut out: Vec<(&'static str, u64, u64)> = Vec::new(); + // Macros rather than closures: a closure capturing `out` would hold the + // mutable borrow across every other push. + macro_rules! single { + ($name:expr, $trace:expr, $main_cols:expr, $interactions:expr $(,)?) => {{ + let rows = $trace.num_rows(); + out.push(( + $name, + (rows * $main_cols) as u64, + (rows * aux_cols($interactions)) as u64, + )); + }}; } - total += (ecsm.num_rows() * ECSM_COLS) as u64; - total += (ecdas.num_rows() * ECDAS_COLS) as u64; - total - } - - /// Returns the total number of auxiliary-trace field elements (extension field) - /// across all tables. - /// - /// The LogUp layout packs N bus interactions into ⌈N/2⌉ EF columns - /// (`num_committed_pairs + 1` accumulated column). Each EF column costs one - /// extension-field element per row. - pub fn total_auxiliary_field_elements(&self) -> u64 { - // ⌈N/2⌉ = number of aux EF columns for a table with N bus interactions. - fn aux_cols(n: usize) -> usize { - n.div_ceil(2) + macro_rules! split { + ($name:expr, $traces:expr, $main_cols:expr, $interactions:expr $(,)?) => {{ + let (mut m, mut a) = (0u64, 0u64); + let aux = aux_cols($interactions); + for t in $traces { + m += (t.num_rows() * $main_cols) as u64; + a += (t.num_rows() * aux) as u64; + } + out.push(($name, m, a)); + }}; } - let n_cpu = aux_cols(super::cpu::bus_interactions().len()); - let n_bitwise = aux_cols(super::bitwise::bus_interactions().len()); - let n_lt = aux_cols(super::lt::bus_interactions().len()); - let n_shift = aux_cols(super::shift::bus_interactions().len()); - let n_memw = aux_cols(super::memw::bus_interactions().len()); - let n_memw_a = aux_cols(super::memw_aligned::bus_interactions().len()); - let n_load = aux_cols(super::load::bus_interactions().len()); - let n_decode = aux_cols(super::decode::bus_interactions().len()); - let n_mul = aux_cols(super::mul::bus_interactions().len()); - let n_dvrm = aux_cols(super::dvrm::bus_interactions().len()); - let n_branch = aux_cols(super::branch::bus_interactions().len()); - let n_halt = aux_cols(super::halt::bus_interactions().len()); - let n_commit = aux_cols(super::commit::bus_interactions().len()); - let n_register = aux_cols(super::register::bus_interactions().len()); - // page::bus_interactions count is constant regardless of page_base. - let n_page = aux_cols(super::page::bus_interactions(0).len()); - let n_memw_r = aux_cols(super::memw_register::bus_interactions().len()); - let n_keccak = aux_cols(super::keccak::bus_interactions().len()); - let n_keccak_rnd = aux_cols(super::keccak_rnd::bus_interactions().len()); - let n_keccak_rc = aux_cols(super::keccak_rc::bus_interactions().len()); - let n_eq = aux_cols(super::eq::bus_interactions().len()); - let n_bytewise = aux_cols(super::bytewise::bus_interactions().len()); - let n_store = aux_cols(super::store::bus_interactions().len()); - let n_cpu32 = aux_cols(super::cpu32::bus_interactions().len()); - let n_ecsm = aux_cols(super::ecsm::bus_interactions().len()); - let n_ecdas = aux_cols(super::ecdas::bus_interactions().len()); - - let Traces { - cpus, + split!("CPU", cpus, CPU_COLS, super::cpu::bus_interactions().len()); + single!( + "BITWISE", bitwise, - lts, + BITWISE_COLS - BITWISE_PRECOMPUTED, + super::bitwise::bus_interactions().len(), + ); + split!("LT", lts, LT_COLS, super::lt::bus_interactions().len()); + split!( + "SHIFT", shifts, + SHIFT_COLS, + super::shift::bus_interactions().len() + ); + split!( + "MEMW", memws, + MEMW_COLS, + super::memw::bus_interactions().len() + ); + split!( + "MEMW_ALIGNED", memw_aligneds, + MEMW_A_COLS, + super::memw_aligned::bus_interactions().len() + ); + split!( + "LOAD", loads, + LOAD_COLS, + super::load::bus_interactions().len() + ); + single!( + "DECODE", decode, - muls, + DECODE_COLS - DECODE_PRECOMPUTED, + super::decode::bus_interactions().len(), + ); + split!("MUL", muls, MUL_COLS, super::mul::bus_interactions().len()); + split!( + "DVRM", dvrms, - pages, - register, + DVRM_COLS, + super::dvrm::bus_interactions().len() + ); + split!( + "BRANCH", branches, + BRANCH_COLS, + super::branch::bus_interactions().len() + ); + single!( + "HALT", halt, + HALT_COLS, + super::halt::bus_interactions().len() + ); + single!( + "COMMIT", commit, + COMMIT_COLS, + super::commit::bus_interactions().len() + ); + single!( + "REGISTER", + register, + REGISTER_COLS - REGISTER_PREPROCESSED, + super::register::bus_interactions().len(), + ); + // `page::bus_interactions` has a constant count regardless of page_base. + split!( + "PAGE", + pages, + PAGE_COLS - PAGE_PREPROCESSED, + super::page::bus_interactions(0).len() + ); + split!( + "MEMW_REGISTER", + memw_registers, + MEMW_R_COLS, + super::memw_register::bus_interactions().len() + ); + single!( + "KECCAK", keccak, + KECCAK_COLS, + super::keccak::bus_interactions().len() + ); + single!( + "KECCAK_RND", keccak_rnd, + KECCAK_RND_COLS, + super::keccak_rnd::bus_interactions().len() + ); + single!( + "KECCAK_RC", keccak_rc, - ecsm, - ecdas, - memw_registers, - eqs, + KECCAK_RC_COLS - KECCAK_RC_PRECOMPUTED, + super::keccak_rc::bus_interactions().len(), + ); + split!("EQ", eqs, EQ_COLS, super::eq::bus_interactions().len()); + split!( + "BYTEWISE", bytewises, + BYTEWISE_COLS, + super::bytewise::bus_interactions().len() + ); + split!( + "STORE", stores, + STORE_COLS, + super::store::bus_interactions().len() + ); + split!( + "CPU32", cpu32s, - page_configs: _, - public_output_bytes: _, - local_to_global: _, - touched_memory_cells: _, - } = self; + CPU32_COLS, + super::cpu32::bus_interactions().len() + ); + single!( + "ECSM", + ecsm, + ECSM_COLS, + super::ecsm::bus_interactions().len() + ); + single!( + "ECDAS", + ecdas, + ECDAS_COLS, + super::ecdas::bus_interactions().len() + ); + single!( + "ECSM2", + ecsm2, + ECSM2_COLS, + super::ecsm2::bus_interactions().len() + ); + single!( + "ECDAS2", + ecdas2, + ECDAS2_COLS, + super::ecdas2::bus_interactions().len() + ); + single!( + "EC_T0", + ec_t0, + EC_T0_COLS - EC_T0_PRECOMPUTED, + super::ec_t0::bus_interactions().len(), + ); - let mut total: u64 = 0; - for t in cpus { - total += (t.num_rows() * n_cpu) as u64; - } - total += (bitwise.num_rows() * n_bitwise) as u64; - for t in lts { - total += (t.num_rows() * n_lt) as u64; - } - for t in shifts { - total += (t.num_rows() * n_shift) as u64; - } - for t in memws { - total += (t.num_rows() * n_memw) as u64; - } - for t in memw_aligneds { - total += (t.num_rows() * n_memw_a) as u64; - } - for t in loads { - total += (t.num_rows() * n_load) as u64; - } - total += (decode.num_rows() * n_decode) as u64; - for t in muls { - total += (t.num_rows() * n_mul) as u64; - } - for t in dvrms { - total += (t.num_rows() * n_dvrm) as u64; - } - for t in branches { - total += (t.num_rows() * n_branch) as u64; - } - total += (halt.num_rows() * n_halt) as u64; - total += (commit.num_rows() * n_commit) as u64; - total += (register.num_rows() * n_register) as u64; - for t in pages { - total += (t.num_rows() * n_page) as u64; - } - for t in memw_registers { - total += (t.num_rows() * n_memw_r) as u64; - } - total += (keccak.num_rows() * n_keccak) as u64; - total += (keccak_rnd.num_rows() * n_keccak_rnd) as u64; - total += (keccak_rc.num_rows() * n_keccak_rc) as u64; - for t in eqs { - total += (t.num_rows() * n_eq) as u64; - } - for t in bytewises { - total += (t.num_rows() * n_bytewise) as u64; - } - for t in stores { - total += (t.num_rows() * n_store) as u64; - } - for t in cpu32s { - total += (t.num_rows() * n_cpu32) as u64; - } - total += (ecsm.num_rows() * n_ecsm) as u64; - total += (ecdas.num_rows() * n_ecdas) as u64; - total + out + } + + /// Returns the total number of main-trace field elements across all tables. + /// + /// Counts only the main (base-field) trace columns — equivalent to SP1's + /// `main_area` — for apples-to-apples comparison with other zkVMs. + /// + /// Preprocessed columns (committed in a separate PCS round during setup, not + /// at proving time) are excluded: BITWISE, DECODE, REGISTER, PAGE, KECCAK_RC, + /// EC_T0. + pub fn total_field_elements(&self) -> u64 { + self.field_elements_by_table().iter().map(|t| t.1).sum() + } + + /// Returns the total number of auxiliary-trace field elements (extension + /// field) across all tables. + /// + /// The LogUp layout packs N bus interactions into ⌈N/2⌉ EF columns + /// (`num_committed_pairs + 1` accumulated column). Each EF column costs one + /// extension-field element per row. + pub fn total_auxiliary_field_elements(&self) -> u64 { + self.field_elements_by_table().iter().map(|t| t.2).sum() } /// Returns the number of chunks for each split table. @@ -4256,6 +4609,8 @@ impl Traces { cpu32_ops, ecsm_ops, ecdas_ops, + ecsm2_ops, + ecdas2_ops, ) = collect_ops_from_cpu(&cpu_ops, &mut memory_state, &mut register_state); #[cfg(feature = "instruments")] drop(__sp); @@ -4274,6 +4629,8 @@ impl Traces { cpu32_ops, ecsm_ops, ecdas_ops, + ecsm2_ops, + ecdas2_ops, &mut register_state, is_final, ); @@ -4333,6 +4690,8 @@ impl Traces { cpu32_ops, ecsm_ops, ecdas_ops, + ecsm2_ops, + ecdas2_ops, ) = collect_ops_from_cpu(&cpu_ops, &mut memory_state, &mut register_state); let ops = collect_all_ops( @@ -4347,6 +4706,8 @@ impl Traces { cpu32_ops, ecsm_ops, ecdas_ops, + ecsm2_ops, + ecdas2_ops, &mut register_state, true, ); diff --git a/prover/src/tables/types.rs b/prover/src/tables/types.rs index fab4aabff..acb4aa816 100644 --- a/prover/src/tables/types.rs +++ b/prover/src/tables/types.rs @@ -348,6 +348,13 @@ pub enum BusId { /// ECDAS self-referential double/add sequence bus: /// (timestamp, xA, yA, xG, yG, round, op). ECSM seeds and drains it. Ecdas = 28, + /// lincomb2 addend bus: `Addend[ts, sel, x(32), y(32)]` where + /// `sel ∈ {1 = P1, 2 = P2, 3 = P12, 4 = −2^len·T₀}`. ECSM2 publishes each + /// addend once per use (multiplicity = a witnessed count column); every + /// ECDAS2 add row receives exactly one. `sel` is never 0, so the + /// trailing-zero tuple collapse (`lookup.rs` skips zero elements) can never + /// alias two different addends. + Addend = 29, /// Scalar-bit bus: ECDAS sends Bit[ts, round] per step (mult = next_op); /// ECSM receives Bit[ts, i] for each of the 256 k bits (mult = k[i]), /// and sends Bit[ts, idx_k] for the MSB (mult = μ). @@ -359,6 +366,24 @@ pub enum BusId { /// Cross-epoch memory bus: the local-to-global table's per-cell init/fini /// boundary claims, matched across epochs by the final aggregation LogUp. GlobalMemory = 31, + + /// lincomb2 NUMS correction lookup: `EC_T0[len, x, y]` where `(x, y)` is + /// `−2^len·T₀`, the blind the joint chain's correction row adds. The EC_T0 + /// preprocessed table receives; the lincomb2 chip sends one per evaluation. + EcT0 = 32, + + /// lincomb2 joint scalar-digit bus: `JointBit[ts, round, stream]` with + /// `stream ∈ {1 = u1, 2 = u2}`. ECDAS2 sends one per stream per row + /// (multiplicity = that stream's digit bit); ECSM2 receives 512 times, + /// keyed by bit position, at multiplicity `2·bit` — twice because a set + /// digit is carried by BOTH the round's doubling and its add. + /// + /// Its own id rather than [`Bit`](BusId::Bit): the old ECSM/ECDAS chips are + /// live alongside the new ones until phase G, and a `stream = 0` tag would + /// collapse to an exact alias of an old-ECDAS `Bit[ts, round]` send (zero + /// elements are skipped by the fingerprint, so trailing-zero padding is + /// invisible). The `{1, 2}` tags close the same hole within this bus. + JointBit = 33, } impl BusId { @@ -386,8 +411,11 @@ impl BusId { BusId::MemoryOp => "MemoryOp", BusId::Cpu32 => "Cpu32", BusId::Ecdas => "Ecdas", + BusId::Addend => "Addend", BusId::Bit => "Bit", BusId::GlobalMemory => "GlobalMemory", + BusId::EcT0 => "EcT0", + BusId::JointBit => "JointBit", } } } @@ -418,8 +446,11 @@ impl TryFrom for BusId { 26 => Ok(BusId::MemoryOp), 27 => Ok(BusId::Cpu32), 28 => Ok(BusId::Ecdas), + 29 => Ok(BusId::Addend), 30 => Ok(BusId::Bit), 31 => Ok(BusId::GlobalMemory), + 32 => Ok(BusId::EcT0), + 33 => Ok(BusId::JointBit), other => Err(other), } } diff --git a/prover/src/test_utils.rs b/prover/src/test_utils.rs index 6dd28ce71..af20fab0b 100644 --- a/prover/src/test_utils.rs +++ b/prover/src/test_utils.rs @@ -57,12 +57,19 @@ use crate::tables::decode::{bus_interactions as decode_bus_interactions, cols as use crate::tables::dvrm::{ DvrmConstraints, bus_interactions as dvrm_bus_interactions, cols as dvrm_cols, }; +use crate::tables::ec_t0::{bus_interactions as ec_t0_bus_interactions, cols as ec_t0_cols}; use crate::tables::ecdas::{ EcdasConstraints, bus_interactions as ecdas_bus_interactions, cols as ecdas_cols, }; +use crate::tables::ecdas2::{ + Ecdas2Constraints, bus_interactions as ecdas2_bus_interactions, cols as ecdas2_cols, +}; use crate::tables::ecsm::{ EcsmConstraints, bus_interactions as ecsm_bus_interactions, cols as ecsm_cols, }; +use crate::tables::ecsm2::{ + Ecsm2Constraints, bus_interactions as ecsm2_bus_interactions, cols as ecsm2_cols, +}; use crate::tables::eq::{EqConstraints, bus_interactions as eq_bus_interactions, cols as eq_cols}; use crate::tables::halt::{bus_interactions as halt_bus_interactions, cols as halt_cols}; use crate::tables::keccak::{ @@ -924,6 +931,21 @@ pub fn create_keccak_rc_air(proof_options: &ProofOptions) -> ConcreteVmAir ConcreteVmAir { + build_air( + ec_t0_cols::NUM_COLUMNS, + ec_t0_bus_interactions(), + proof_options, + 1, + EmptyConstraints, + "EC_T0", + ) +} + /// Create ECSM core AIR (secp256k1 scalar-multiplication orchestrator). pub fn create_ecsm_air(proof_options: &ProofOptions) -> ConcreteVmAir { build_air( @@ -947,3 +969,27 @@ pub fn create_ecdas_air(proof_options: &ProofOptions) -> ConcreteVmAir ConcreteVmAir { + build_air( + ecsm2_cols::NUM_COLUMNS, + ecsm2_bus_interactions(), + proof_options, + 1, + Ecsm2Constraints, + "ECSM2", + ) +} + +/// Create ECDAS2 AIR (per-step double/add of the lincomb2 joint chain). +pub fn create_ecdas2_air(proof_options: &ProofOptions) -> ConcreteVmAir { + build_air( + ecdas2_cols::NUM_COLUMNS, + ecdas2_bus_interactions(), + proof_options, + 1, + Ecdas2Constraints, + "ECDAS2", + ) +} diff --git a/prover/src/tests/ec_t0_tests.rs b/prover/src/tests/ec_t0_tests.rs new file mode 100644 index 000000000..be2531ff7 --- /dev/null +++ b/prover/src/tests/ec_t0_tests.rs @@ -0,0 +1,397 @@ +//! Tests for the EC_T0 preprocessed table (`−2^len·T₀`, keyed by `len − 1`). +//! +//! The table's constants come from `ecsm::lincomb2_table`, which doubles the +//! pinned `T₀` in k256 projective coordinates. Everything checked here is +//! recomputed *independently* — an affine `Fp` doubling written in this file, +//! or the byte output of `lincomb2_witness` — so a bug in the k256 path cannot +//! validate itself. + +use num_bigint::BigUint; + +use ecsm::curve::AffinePoint; +use ecsm::witness::{JointSel, lincomb2_witness, t0}; +use ecsm::{B, p, to_le_32}; + +use stark::proof::options::GoldilocksCubicProofOptions; + +use stark::lookup::{BusValue, LinearTerm}; + +use crate::tables::BusId; +use crate::tables::ec_t0::{ + self, MAX_LEN, MIN_LEN, NUM_PRECOMPUTED_COLS, NUM_ROWS, cols, generate_row, +}; +use crate::tables::types::{GoldilocksExtension, GoldilocksField}; +use stark::trace::TraceTable; + +// ---- an independent affine Fp group law (no k256, no BigInt witness code) ---- + +fn inv(a: &BigUint, modulus: &BigUint) -> BigUint { + a.modpow(&(modulus - 2u32), modulus) +} + +/// `2·pt` in affine coordinates: `λ = 3x²/(2y)`, `x₃ = λ² − 2x`, +/// `y₃ = λ(x − x₃) − y`. +fn double(pt: &AffinePoint, modulus: &BigUint) -> AffinePoint { + let lam = (3u32 * &pt.x * &pt.x % modulus) * inv(&(2u32 * &pt.y % modulus), modulus) % modulus; + let x3 = (&lam * &lam + modulus * 2u32 - 2u32 * &pt.x) % modulus; + let y3 = (&lam * ((&pt.x + modulus - &x3) % modulus) + modulus - &pt.y) % modulus; + AffinePoint { x: x3, y: y3 } +} + +/// Reads a 32-byte little-endian coordinate out of one trace row. +fn coord( + trace: &TraceTable, + row: usize, + col: usize, +) -> [u8; 32] { + let mut out = [0u8; 32]; + for (i, byte) in out.iter_mut().enumerate() { + let v = trace.main_table.get(row, col + i).canonical(); + assert!(v < 256, "row {row} col {}: not a byte ({v})", col + i); + *byte = v as u8; + } + out +} + +fn cell(trace: &TraceTable, row: usize, col: usize) -> u64 { + trace.main_table.get(row, col).canonical() +} + +// ---- layout ---- + +#[test] +fn layout_is_as_documented() { + assert_eq!(cols::LEN_M1, 0); + assert_eq!(cols::X, 1); + assert_eq!(cols::Y, 33); + assert_eq!(cols::MU, 65); + assert_eq!(cols::NUM_COLUMNS, 66); + assert_eq!( + NUM_PRECOMPUTED_COLS, 65, + "everything but MU is preprocessed" + ); + assert_eq!(NUM_PRECOMPUTED_COLS, cols::MU, "MU is the only main column"); + assert_eq!( + MIN_LEN, 1, + "len = 0 is unreachable (both scalars are non-zero)" + ); + assert_eq!(MAX_LEN, 256, "len <= 256 (both scalars are < N < 2^256)"); + assert_eq!(NUM_ROWS, 256, "one row per reachable len, no padding"); + assert_eq!( + NUM_ROWS, + MAX_LEN - MIN_LEN + 1, + "every row is real: LEN_M1 fills a byte exactly", + ); + assert!(ec_t0::is_preprocessed()); +} + +// ---- the acceptance gate: recompute the whole table from t0() ---- + +/// Recomputes every row from `ecsm::witness::t0()` by repeated affine doubling +/// (this file's `double`, not the generator's k256 chain), negates each `y`, and +/// compares byte-for-byte against the committed trace columns. Row `j` holds the +/// blind for `len = j + MIN_LEN`, so the chain is advanced `MIN_LEN` times +/// before the first row. +#[test] +fn trace_rows_recompute_from_t0_by_doubling() { + let trace = ec_t0::generate_ec_t0_trace(); + let modulus = p(); + let mut pt = t0(); + for _ in 0..MIN_LEN { + pt = double(&pt, &modulus); + } + + for row in 0..NUM_ROWS { + let len = row + MIN_LEN; + assert_eq!( + cell(&trace, row, cols::LEN_M1), + row as u64, + "row {row}: LEN_M1 key must equal len - 1", + ); + assert_eq!( + coord(&trace, row, cols::X), + to_le_32(&pt.x), + "row {row}: X != x(2^{len}·T0)", + ); + assert_eq!( + coord(&trace, row, cols::Y), + to_le_32(&(&modulus - &pt.y)), + "row {row}: Y != y(-2^{len}·T0); the table must store the NEGATED point", + ); + pt = double(&pt, &modulus); + } +} + +/// Every entry is a canonical on-curve point: `y² ≡ x³ + b (mod p)` with both +/// coordinates in `[0, p)` and `y ≠ 0`. There are no padding rows to skip — +/// this covers the whole table. +#[test] +fn every_entry_is_on_curve_and_canonical() { + let trace = ec_t0::generate_ec_t0_trace(); + let modulus = p(); + + for row in 0..NUM_ROWS { + let x = BigUint::from_bytes_le(&coord(&trace, row, cols::X)); + let y = BigUint::from_bytes_le(&coord(&trace, row, cols::Y)); + assert!(x < modulus, "row {row}: x >= p"); + assert!(y < modulus, "row {row}: y >= p"); + assert!(y > BigUint::ZERO, "row {row}: y = 0"); + let lhs = &y * &y % &modulus; + let rhs = (&x * &x % &modulus * &x + B) % &modulus; + assert_eq!(lhs, rhs, "row {row} is not on the secp256k1 curve"); + } +} + +/// Row 0 holds `−2·T₀`, i.e. the blind for the smallest reachable `len = 1` — +/// NOT `−T₀`. The `len = 0` anchor of the doubling chain is deliberately absent: +/// both scalars are non-zero, so `len = 0` cannot occur. +#[test] +fn row_zero_is_the_blind_for_min_len_not_t0_itself() { + let trace = ec_t0::generate_ec_t0_trace(); + let modulus = p(); + let t = t0(); + + let expected = double(&t, &modulus); + assert_eq!(coord(&trace, 0, cols::X), to_le_32(&expected.x)); + assert_eq!( + coord(&trace, 0, cols::Y), + to_le_32(&(&modulus - &expected.y)) + ); + + // And T0 itself is not in the table under any key. + let t0_x = to_le_32(&t.x); + for row in 0..NUM_ROWS { + assert_ne!( + coord(&trace, row, cols::X), + t0_x, + "row {row} holds T0 itself; len = 0 must have no row", + ); + } +} + +/// No two rows share a lookup key, and the published keys are exactly the +/// reachable `len` range. This is what makes the range bound hold by +/// construction: a send at `len = 0` or `len > MAX_LEN` matches no row. +#[test] +fn keys_cover_the_reachable_len_range_exactly_and_uniquely() { + let trace = ec_t0::generate_ec_t0_trace(); + let mut keys: Vec = (0..NUM_ROWS) + .map(|row| cell(&trace, row, cols::LEN_M1) + 1) + .collect(); + keys.sort_unstable(); + keys.dedup(); + assert_eq!(keys.len(), NUM_ROWS, "duplicate lookup keys"); + assert_eq!(*keys.first().unwrap(), MIN_LEN as u64); + assert_eq!(*keys.last().unwrap(), MAX_LEN as u64); + assert!( + (0..NUM_ROWS).all(|row| cell(&trace, row, cols::LEN_M1) < 256), + "LEN_M1 must fit in a byte", + ); +} + +// ---- multiplicities ---- + +#[test] +fn mu_starts_at_zero_everywhere() { + let trace = ec_t0::generate_ec_t0_trace(); + for row in 0..NUM_ROWS { + assert_eq!(cell(&trace, row, cols::MU), 0, "row {row}: MU"); + } +} + +#[test] +fn update_multiplicities_counts_lookups_per_len() { + let mut trace = ec_t0::generate_ec_t0_trace(); + ec_t0::update_multiplicities(&mut trace, [1u16, 256, 7, 256, 256]); + + // Callers pass `len`; row `len - 1` is written. + assert_eq!(cell(&trace, 0, cols::MU), 1, "len = 1 -> row 0"); + assert_eq!(cell(&trace, 6, cols::MU), 1, "len = 7 -> row 6"); + assert_eq!(cell(&trace, 255, cols::MU), 3, "len = 256 -> row 255"); + for row in [1usize, 2, 5, 7, 254] { + assert_eq!( + cell(&trace, row, cols::MU), + 0, + "row {row} was not looked up" + ); + } +} + +#[test] +#[should_panic(expected = "outside [1, 256]")] +fn update_multiplicities_rejects_len_above_max() { + let mut trace = ec_t0::generate_ec_t0_trace(); + ec_t0::update_multiplicities(&mut trace, [257u16]); +} + +#[test] +#[should_panic(expected = "outside [1, 256]")] +fn update_multiplicities_rejects_len_zero() { + let mut trace = ec_t0::generate_ec_t0_trace(); + ec_t0::update_multiplicities(&mut trace, [0u16]); +} + +// ---- the sign convention, at trace level ---- + +/// The load-bearing convention test: `lincomb2_witness`'s correction row takes +/// its addend from `(x_g, y_g)`, and those bytes must be exactly the committed +/// EC_T0 row `len - MIN_LEN`. If the table ever flips to storing `+2^len·T₀`, +/// or the `LEN_M1` offset goes out of step with the constants, this is what +/// fails. +#[test] +fn table_matches_lincomb2_witness_correction_row() { + let trace = ec_t0::generate_ec_t0_trace(); + + let gx = BigUint::parse_bytes( + b"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + 16, + ) + .expect("generator x"); + let g = AffinePoint { + y: ecsm::curve::recover_y_canonical(&gx).expect("generator y"), + x: gx, + }; + // 2·G — a distinct x, so the `P1 + P2` precompute is a genuine chord. + let p2 = double(&g, &p()); + + // Scalars spanning a range of `len` values, including the 256 top row. + let scalars = [ + BigUint::from(1u8), + BigUint::from(0xFFFFu32), + BigUint::from(1u8) << 200, + ecsm::n() - 1u32, + ]; + + let mut saw_max_len = false; + for u1 in &scalars { + for u2 in &scalars { + let w = lincomb2_witness(&to_le_32(u1), &to_le_32(u2), &g, &p2).expect("witness"); + let len = w.len as usize; + assert!((1..=MAX_LEN).contains(&len), "len {len} out of range"); + saw_max_len |= len == MAX_LEN; + + let corr = w + .steps + .iter() + .find(|s| matches!(s.sel, JointSel::Correction)) + .expect("correction row"); + + let row = len - MIN_LEN; + assert_eq!( + cell(&trace, row, cols::LEN_M1) + 1, + len as u64, + "row {row}: bus key must reconstruct len {len}", + ); + assert_eq!( + corr.step.x_g, + coord(&trace, row, cols::X), + "len {len}: correction addend x != EC_T0 row x", + ); + assert_eq!( + corr.step.y_g, + coord(&trace, row, cols::Y), + "len {len}: correction addend y != EC_T0 row y (sign convention broken)", + ); + + // The witness's `*_t0_pow` fields carry the OPPOSITE convention: + // the positive blind. x matches the table directly; y is its + // negation. Pinned here so a future reader cannot confuse them. + assert_eq!( + w.x_t0_pow, + coord(&trace, row, cols::X), + "len {len}: x_t0_pow != EC_T0 row x", + ); + assert_eq!( + BigUint::from_bytes_le(&w.y_t0_pow) + + BigUint::from_bytes_le(&coord(&trace, row, cols::Y)), + p(), + "len {len}: y_t0_pow must be the negation of EC_T0 row y", + ); + } + } + assert!(saw_max_len, "len = 256 was never exercised"); +} + +// ---- commitment ---- + +/// The same constants every time: `generate_row` and the generated trace agree, +/// and repeated calls are byte-identical (the `LazyLock` cache cannot drift). +#[test] +fn generated_trace_matches_generate_row_and_is_reproducible() { + let a = ec_t0::generate_ec_t0_trace(); + let b = ec_t0::generate_ec_t0_trace(); + for row in 0..NUM_ROWS { + for (col, value) in generate_row(row).iter().enumerate() { + assert_eq!(cell(&a, row, col), *value, "row {row} col {col}"); + assert_eq!( + a.main_table.get(row, col), + b.main_table.get(row, col), + "row {row} col {col} differs between instantiations", + ); + } + } +} + +/// The commitment is stable across runs and instantiations, and equals the +/// static bytes compiled into the verifier for every shipped blowup. +#[test] +fn commitment_is_stable_and_matches_the_shipped_static_bytes() { + for &blowup in crate::tables::STATIC_BLOWUP_FACTORS { + let options = GoldilocksCubicProofOptions::with_blowup(blowup).expect("valid blowup"); + let first = ec_t0::compute_preprocessed_commitment(&options); + let second = ec_t0::compute_preprocessed_commitment(&options); + assert_eq!(first, second, "blowup={blowup}: commitment is not stable"); + assert_eq!( + first, + ec_t0::preprocessed_commitment(&options), + "blowup={blowup}: shipped static commitment != recompute", + ); + } +} + +/// Different blowups must not collide (a smoke check that the commitment +/// actually depends on the LDE parameters). +#[test] +fn commitment_differs_across_blowups() { + let opts_2 = GoldilocksCubicProofOptions::with_blowup(2).expect("valid blowup"); + let opts_4 = GoldilocksCubicProofOptions::with_blowup(4).expect("valid blowup"); + assert_ne!( + ec_t0::preprocessed_commitment(&opts_2), + ec_t0::preprocessed_commitment(&opts_4), + ); +} + +// ---- bus ---- + +/// One receiver on `EcT0`, keyed by `len`, carrying both coordinates as 32 +/// individual byte elements (the shape ECSM/ECDAS use for every point tuple). +#[test] +fn bus_interaction_shape() { + let buses = ec_t0::bus_interactions(); + assert_eq!(buses.len(), 1, "EC_T0: exactly one receiver"); + let bus = &buses[0]; + assert_eq!(bus.bus_id, BusId::EcT0 as u64); + assert_eq!(bus.values.len(), 1 + 32 + 32, "len + x[32] + y[32]"); + + // The key element must be `LEN_M1 + 1`, not a bare column read — that + // `+1` is what confines the published keys to [1, 256]. + match &bus.values[0] { + BusValue::Linear(terms) => { + assert!( + terms.iter().any(|t| matches!( + t, + LinearTerm::Column { + coefficient: 1, + column + } if *column == cols::LEN_M1 + )), + "key must read LEN_M1 with coefficient 1", + ); + assert!( + terms.iter().any(|t| matches!(t, LinearTerm::Constant(1))), + "key must add the +1 that turns LEN_M1 back into len", + ); + } + other => panic!("EC_T0 key must be a linear term, got {other:?}"), + } +} diff --git a/prover/src/tests/ecsm_tests.rs b/prover/src/tests/ecsm_tests.rs index 91956c5ad..9ddbfbd06 100644 --- a/prover/src/tests/ecsm_tests.rs +++ b/prover/src/tests/ecsm_tests.rs @@ -97,6 +97,16 @@ fn constraint_set_count() { assert_eq!(EcsmConstraints.meta().len(), 413); } +/// Pins the bus-interaction counts after the paired-ARE_BYTES rewrite +/// (ECSM 579 → 515: 129 single-byte sends → 64 pairs + lone q1[32]; +/// ECDAS 388 → 290: 196 single-byte sends → 98 pairs). A drift here means the +/// send layout changed — `collect_bitwise_from_*` must be updated in lockstep. +#[test] +fn bus_interaction_counts() { + assert_eq!(crate::tables::ecsm::bus_interactions().len(), 515); + assert_eq!(crate::tables::ecdas::bus_interactions().len(), 290); +} + /// The yG carry recurrence closes on all-zero padding because both the `µ·p²` offset and the /// curve constant `µ·b` are multiplied by `µ`, so they vanish when `µ = 0`. This checks the /// closing argument (Yg limb-0 ConvCarry = constraint `IDX_YG_CONV0`) and its two ingredients. diff --git a/prover/src/tests/lincomb2_tests.rs b/prover/src/tests/lincomb2_tests.rs new file mode 100644 index 000000000..9a028b59d --- /dev/null +++ b/prover/src/tests/lincomb2_tests.rs @@ -0,0 +1,1136 @@ +//! ECSM2 / ECDAS2 (lincomb2) chip tests. +//! +//! The end-to-end gate lives in `prove_elfs_tests` (a real guest proving and +//! verifying). This file is the trace-level gate: over a random corpus it checks +//! that every in-chip transition constraint holds on every emitted row, that the +//! chip's `Q` is the witness's `Q`, and that the four buses the joint chain owns +//! balance exactly. Plus layout/bus-shape pins and negative controls, following +//! the `ec_t0_tests` precedent of pinning a chip's contract in its own file. + +use std::collections::HashMap; + +use math::field::element::FieldElement; +use math::field::traits::IsPrimeField; +use num_bigint::BigUint; +use stark::lookup::{BusValue, LinearTerm, Multiplicity}; +use stark::trace::TraceTable; + +use ecsm::witness::{JointSel, Lincomb2Witness, lincomb2_witness}; +use ecsm::{AffinePoint, n, replay_double_and_add, to_le_32}; + +use crate::tables::types::{BusId, GoldilocksExtension, GoldilocksField}; +use crate::tables::{ecdas2, ecsm2}; +use crate::test_utils::{busless_air, validate_busless}; + +type F = GoldilocksField; +type E = GoldilocksExtension; + +/// Number of random lincomb2 evaluations the corpus tests cover. +const CASES: usize = 100; + +// ============================================================================= +// Corpus helpers +// ============================================================================= + +/// The secp256k1 generator, as the executor pins it. +fn generator() -> AffinePoint { + let g = executor::vm::instruction::execution::GENERATOR_LE; + AffinePoint { + x: BigUint::from_bytes_le(&g[..32]), + y: BigUint::from_bytes_le(&g[32..]), + } +} + +/// Deterministic pseudo-random scalar in `[1, N)` from a seed (the same +/// splitmix64 expansion the phase-A witness corpus uses). +fn scalar(seed: u64) -> BigUint { + let mut s = seed.wrapping_mul(0x9E37_79B9_7F4A_7C15).wrapping_add(1); + let mut bytes = [0u8; 32]; + for chunk in bytes.chunks_mut(8) { + s ^= s >> 30; + s = s.wrapping_mul(0xBF58_476D_1CE4_E5B9); + s ^= s >> 27; + s = s.wrapping_mul(0x94D0_49BB_1331_11EB); + s ^= s >> 31; + chunk.copy_from_slice(&s.to_le_bytes()); + } + BigUint::from_bytes_le(&bytes) % (n() - 1u32) + 1u32 +} + +/// A pseudo-random on-curve point `k·G`, standing in for ecrecover's `R`. +fn random_point(seed: u64) -> AffinePoint { + replay_double_and_add(&scalar(seed), &generator()).1 +} + +/// `CASES` witnesses at the ecrecover shape: `P1 = G`, `P2` a random point, both +/// scalars random in `[1, N)`. +fn corpus() -> Vec { + let g = generator(); + (0..CASES) + .map(|i| { + let i = i as u64; + lincomb2_witness( + &to_le_32(&scalar(2 * i + 1)), + &to_le_32(&scalar(2 * i + 2)), + &g, + &random_point(5000 + i), + ) + .expect("random lincomb2 corpus must be non-degenerate") + }) + .collect() +} + +/// Wraps a witness into the two chips' operation structs at timestamp `ts`. +fn ops_for(ts: u64, w: &Lincomb2Witness) -> (ecsm2::Ecsm2Operation, Vec) { + let ecsm2_op = ecsm2::Ecsm2Operation { + timestamp: ts, + addr_q: 0x1000, + addr_p1: 0x2000, + addr_p2: 0x3000, + addr_u: 0x4000, + status: 0, + witness: Some(Box::new(w.clone())), + }; + let ecdas2_ops = w + .steps + .iter() + .cloned() + .map(|step| ecdas2::Ecdas2Operation { + timestamp: ts, + step, + }) + .collect(); + (ecsm2_op, ecdas2_ops) +} + +/// Canonical `u64` of a Goldilocks trace cell. +fn canonical(x: &FieldElement) -> u64 { + F::canonical(x.value()) +} + +fn read_bytes(trace: &TraceTable, row: usize, col: usize, len: usize) -> Vec { + (0..len) + .map(|i| { + let v = canonical(trace.main_table.get(row, col + i)); + u8::try_from(v).expect("byte column out of range") + }) + .collect() +} + +// ============================================================================= +// Layout and bus-shape pins +// ============================================================================= + +#[test] +fn ecsm2_layout_is_as_documented() { + use ecsm2::cols as c; + assert_eq!(c::TIMESTAMP_0, 0); + assert_eq!(c::ADDR_Q_0, 2); + assert_eq!(c::X_P2, 10); + assert_eq!(c::Y_P2, 42); + assert_eq!(c::MEM_X2, 74); + assert_eq!(c::MEM_Q0, 106); + assert_eq!(c::MEM_C0, 138); + assert_eq!(c::MEM_Q1, 202); + assert_eq!(c::MEM_C1, 235); + assert_eq!(c::Y_P2_SUB_P, 299); + assert_eq!(c::X_P12, 315); + assert_eq!(c::U1, 379); + assert_eq!(c::U2, 635); + assert_eq!(c::U1_SUB_N, 891); + assert_eq!(c::U2_SUB_N, 907); + assert_eq!(c::LEN_M1, 923); + assert_eq!(c::X_T0N, 924); + assert_eq!(c::ACC_X, 988); + assert_eq!(c::X_Q, 1052); + assert_eq!(c::X_Q_SUB_P, 1116); + assert_eq!(c::N1, 1148); + assert_eq!(c::STATUS, 1151); + assert_eq!(c::OK, 1153); + assert_eq!(c::MU, 1154); + assert_eq!(c::NUM_COLUMNS, 1155); +} + +/// Every declared column block, as `(name, offset, width)`. +/// +/// Kept as data so [`assert_layout_is_a_partition`] can check the whole block +/// map at once. Widths are restated here on purpose: this is a pin, and a pin +/// that derived its widths from the thing it pins would assert nothing. +fn ecdas2_blocks() -> Vec<(&'static str, usize, usize)> { + use ecdas2::cols as c; + vec![ + ("TIMESTAMP_0", c::TIMESTAMP_0, 1), + ("TIMESTAMP_1", c::TIMESTAMP_1, 1), + ("XB", c::XB, 32), + ("YB", c::YB, 32), + ("XA", c::XA, 32), + ("YA", c::YA, 32), + ("ROUND", c::ROUND, 1), + ("OP", c::OP, 1), + ("XR", c::XR, 32), + ("YR", c::YR, 32), + ("LAMBDA", c::LAMBDA, 32), + ("Q0", c::Q0, 33), + ("C0", c::C0, 64), + ("Q1", c::Q1, 33), + ("C1", c::C1, 64), + ("Q2", c::Q2, 33), + ("C2", c::C2, 64), + ("NB", c::NB, 1), + ("D1", c::D1, 1), + ("D2", c::D2, 1), + ("S1", c::S1, 1), + ("S2", c::S2, 1), + ("S3", c::S3, 1), + ("S_CORR", c::S_CORR, 1), + ("PH1", c::PH1, 1), + ("PH2", c::PH2, 1), + ("MU", c::MU, 1), + ("D_INV", c::D_INV, 32), + ("Q3", c::Q3, 33), + ("C3", c::C3, 64), + ] +} + +/// The same for ECSM2. +fn ecsm2_blocks() -> Vec<(&'static str, usize, usize)> { + use ecsm2::cols as c; + vec![ + ("TIMESTAMP_0", c::TIMESTAMP_0, 1), + ("TIMESTAMP_1", c::TIMESTAMP_1, 1), + ("ADDR_Q_0", c::ADDR_Q_0, 1), + ("ADDR_Q_1", c::ADDR_Q_1, 1), + ("ADDR_P1_0", c::ADDR_P1_0, 1), + ("ADDR_P1_1", c::ADDR_P1_1, 1), + ("ADDR_P2_0", c::ADDR_P2_0, 1), + ("ADDR_P2_1", c::ADDR_P2_1, 1), + ("ADDR_U_0", c::ADDR_U_0, 1), + ("ADDR_U_1", c::ADDR_U_1, 1), + ("X_P2", c::X_P2, 32), + ("Y_P2", c::Y_P2, 32), + ("MEM_X2", c::MEM_X2, 32), + ("MEM_Q0", c::MEM_Q0, 32), + ("MEM_C0", c::MEM_C0, 64), + ("MEM_Q1", c::MEM_Q1, 33), + ("MEM_C1", c::MEM_C1, 64), + ("Y_P2_SUB_P", c::Y_P2_SUB_P, 16), + ("X_P12", c::X_P12, 32), + ("Y_P12", c::Y_P12, 32), + ("U1", c::U1, 256), + ("U2", c::U2, 256), + ("U1_SUB_N", c::U1_SUB_N, 16), + ("U2_SUB_N", c::U2_SUB_N, 16), + ("LEN_M1", c::LEN_M1, 1), + ("X_T0N", c::X_T0N, 32), + ("Y_T0N", c::Y_T0N, 32), + ("ACC_X", c::ACC_X, 32), + ("ACC_Y", c::ACC_Y, 32), + ("X_Q", c::X_Q, 32), + ("Y_Q", c::Y_Q, 32), + ("X_Q_SUB_P", c::X_Q_SUB_P, 16), + ("Y_Q_SUB_P", c::Y_Q_SUB_P, 16), + ("N1", c::N1, 1), + ("N2", c::N2, 1), + ("N3", c::N3, 1), + ("STATUS", c::STATUS, 1), + ("S_INV", c::S_INV, 1), + ("OK", c::OK, 1), + ("MU", c::MU, 1), + ] +} + +/// Asserts the declared blocks tile `[0, num_columns)` exactly: nothing +/// overlaps, nothing is unclaimed, and the highest block ends at `NUM_COLUMNS`. +/// +/// This is the check that catches the failure mode a hand-maintained `cols` +/// module actually has — a block added at the wrong offset, silently aliasing +/// another and corrupting the trace with no compile error. It caught nothing on +/// the day it was written, which is the point: it is cheap enough to keep +/// standing. +fn assert_layout_is_a_partition( + chip: &str, + blocks: &[(&'static str, usize, usize)], + num_columns: usize, +) { + let mut owner: Vec> = vec![None; num_columns]; + for (name, offset, width) in blocks { + assert!( + offset + width <= num_columns, + "{chip}: block {name} runs past NUM_COLUMNS ({num_columns})", + ); + for (cell, slot) in owner[*offset..*offset + *width].iter_mut().enumerate() { + assert!( + slot.is_none(), + "{chip}: column {} is claimed by both {} and {name}", + offset + cell, + slot.unwrap(), + ); + *slot = Some(name); + } + } + let unclaimed: Vec = (0..num_columns).filter(|c| owner[*c].is_none()).collect(); + assert!( + unclaimed.is_empty(), + "{chip}: {} column(s) belong to no block, first at {}", + unclaimed.len(), + unclaimed[0], + ); +} + +#[test] +fn ecdas2_columns_tile_exactly() { + assert_layout_is_a_partition("ECDAS2", &ecdas2_blocks(), ecdas2::cols::NUM_COLUMNS); +} + +#[test] +fn ecsm2_columns_tile_exactly() { + assert_layout_is_a_partition("ECSM2", &ecsm2_blocks(), ecsm2::cols::NUM_COLUMNS); +} + +/// The worst case is 514 rows, not the ~471 a random corpus reaches — and the +/// chip's constant must say so, since capacity bounds are derived from it. +#[test] +fn worst_case_schedule_is_514_rows() { + assert_eq!(ecdas2::MAX_ROWS_PER_EVALUATION, 514); + + // (2^255, 2^255 − 1): complementary bit patterns, so every round adds. + let mut u1 = [0u8; 32]; + u1[31] = 0x80; + let mut u2 = [0xFFu8; 32]; + u2[31] = 0x7F; + + let w = lincomb2_witness(&u1, &u2, &generator(), &random_point(1234)) + .expect("the worst-case scalars are valid"); + assert_eq!(w.len, 256); + assert_eq!( + w.steps.len(), + ecdas2::MAX_ROWS_PER_EVALUATION, + "1 precompute + 256 doublings + 256 adds + 1 correction", + ); + let adds = w + .steps + .iter() + .filter(|s| s.sel != JointSel::Double && s.sel != JointSel::Precompute) + .count(); + assert_eq!(adds, 257, "256 main-chain adds + the correction row"); + + // And it is genuinely the maximum: identical patterns share their adds. + let all_ones = lincomb2_witness(&u2, &u2, &generator(), &random_point(1234)).unwrap(); + assert!( + all_ones.steps.len() < w.steps.len(), + "complementarity maximises, not popcount: got {} vs {}", + all_ones.steps.len(), + w.steps.len(), + ); +} + +#[test] +fn ecdas2_layout_is_as_documented() { + use ecdas2::cols as c; + // The convolution core sits at the same offsets as the single-scalar chip, + // which is what makes the relation body a rename rather than a rewrite. + assert_eq!(c::XB, crate::tables::ecdas::cols::XG); + assert_eq!(c::YB, crate::tables::ecdas::cols::YG); + assert_eq!(c::XA, crate::tables::ecdas::cols::XA); + assert_eq!(c::ROUND, crate::tables::ecdas::cols::ROUND); + assert_eq!(c::OP, crate::tables::ecdas::cols::OP); + assert_eq!(c::Q0, crate::tables::ecdas::cols::Q0); + assert_eq!(c::C2, crate::tables::ecdas::cols::C2); + // The joint bookkeeping block replaces NEXT_OP. + assert_eq!(c::NB, 519); + assert_eq!(c::D1, 520); + assert_eq!(c::D2, 521); + assert_eq!(c::S1, 522); + assert_eq!(c::S_CORR, 525); + assert_eq!(c::PH1, 526); + assert_eq!(c::PH2, 527); + assert_eq!(c::MU, 528); + // The non-degeneracy block. + assert_eq!(c::D_INV, 529); + assert_eq!(c::Q3, 561); + assert_eq!(c::C3, 594); + assert_eq!(c::NUM_COLUMNS, 658); +} + +#[test] +fn ecdas2_bus_interaction_shape() { + let buses = ecdas2::bus_interactions(); + let count = |id: BusId, sender: bool| { + buses + .iter() + .filter(|b| b.bus_id == id as u64 && b.is_sender == sender) + .count() + }; + assert_eq!(count(BusId::Ecdas, false), 1, "one chain receive"); + assert_eq!(count(BusId::Ecdas, true), 1, "one chain send"); + assert_eq!(count(BusId::Addend, false), 1, "one addend receive"); + assert_eq!( + count(BusId::Addend, true), + 0, + "ECDAS2 never publishes addends" + ); + assert_eq!(count(BusId::JointBit, true), 2, "one send per digit stream"); + assert_eq!( + count(BusId::AreBytes, true), + 8 * 16 + 2 + 1, + "the paired ARE_BYTES layout: 8 blocks of 32, ROUND + three odd quotient \ + bytes paired, and Q3[32] alone", + ); + assert_eq!(count(BusId::IsHalfword, true), 4 * 63, "4 x 63 carries"); + assert_eq!(buses.len(), 388); + + // Every ARE_BYTES / IS_HALF send must be MU-gated, and the only two + // interactions that are NOT are the ones whose multiplicity is a live + // count — the Addend receive and the two digit sends. A MU = 0 row emitting + // on either of those is a forgery, which is why `(1 − MU)·D = 0` and + // `(1 − MU)·S = 0` exist; this pins the set of interactions that argument + // has to cover. + let not_mu_gated: Vec<_> = buses + .iter() + .filter(|b| !matches!(b.multiplicity, Multiplicity::Column(c) if c == ecdas2::cols::MU)) + .map(|b| (b.bus_id, b.is_sender)) + .collect(); + assert_eq!( + not_mu_gated, + vec![ + (BusId::Addend as u64, false), + (BusId::JointBit as u64, true), + (BusId::JointBit as u64, true), + ], + ); + + // The addend receive must be gated by the four selectors, not by MU: it has + // to stay silent on doublings. + let addend = buses + .iter() + .find(|b| b.bus_id == BusId::Addend as u64) + .unwrap(); + match &addend.multiplicity { + Multiplicity::Linear(terms) => { + assert_eq!(terms.len(), 4, "S1 + S2 + S3 + S_CORR"); + let cols: Vec = terms + .iter() + .map(|t| match t { + LinearTerm::Column { + coefficient: 1, + column, + } => *column, + other => panic!("unexpected addend multiplicity term {other:?}"), + }) + .collect(); + assert_eq!( + cols, + vec![ + ecdas2::cols::S1, + ecdas2::cols::S2, + ecdas2::cols::S3, + ecdas2::cols::S_CORR + ] + ); + } + other => panic!("addend multiplicity must be Linear, got {other:?}"), + } + + // The joint chain tuple must lead with a NON-ZERO chain id. That constant is + // the only thing separating it from the single-scalar chain on bus 28: a + // zero would be skipped by the fingerprint and the two chains could alias. + for bus in buses.iter().filter(|b| b.bus_id == BusId::Ecdas as u64) { + match bus.values[0] { + BusValue::Linear(ref terms) => match terms.as_slice() { + [LinearTerm::Constant(v)] => { + assert_eq!(*v, ecdas2::JOINT_CHAIN_ID as i64) + } + other => panic!("chain id must be one constant, got {other:?}"), + }, + ref other => panic!("chain id must be a constant, got {other:?}"), + } + } + assert_ne!(ecdas2::JOINT_CHAIN_ID, 0); +} + +#[test] +fn ecsm2_bus_interaction_shape() { + let buses = ecsm2::bus_interactions(); + let count = |id: BusId, sender: bool| { + buses + .iter() + .filter(|b| b.bus_id == id as u64 && b.is_sender == sender) + .count() + }; + assert_eq!(count(BusId::Ecall, false), 1); + assert_eq!( + count(BusId::Memw, true), + 1 + 3 + 8 + 8 + 8 + 8, + "x10 read+write, three register reads, three operand reads, one result write", + ); + assert_eq!(count(BusId::JointBit, false), 512, "256 bits x 2 streams"); + assert_eq!(count(BusId::Addend, true), 4, "P1, P2, P12, -2^len.T0"); + assert_eq!(count(BusId::EcT0, true), 1); + assert_eq!(count(BusId::Ecdas, true), 3, "three segment seeds"); + assert_eq!(count(BusId::Ecdas, false), 3, "three segment drains"); + assert_eq!(count(BusId::AreBytes, true), 49); + assert_eq!(count(BusId::IsHalfword, true), 63 + 63 + 5 * 16); + assert_eq!(count(BusId::Zero, true), 2, "u1 != 0 and u2 != 0"); + + // Only the ECALL receive and the status write may be MU-gated. Everything + // else — in particular the reads at `a1`, which assert the constant G — must + // be OK-gated, or the `P1 != G` error path becomes unprovable. + let mu_gated: Vec<_> = buses + .iter() + .filter(|b| matches!(b.multiplicity, Multiplicity::Column(c) if c == ecsm2::cols::MU)) + .collect(); + assert_eq!(mu_gated.len(), 2); + assert_eq!(mu_gated[0].bus_id, BusId::Ecall as u64); + assert_eq!(mu_gated[1].bus_id, BusId::Memw as u64); + + // The EC_T0 send must carry a plain `len`, i.e. `LEN_M1 + 1`: the table's + // receive key re-adds the 1 and its 256 unpadded rows are what bound `len`. + let ec_t0 = buses + .iter() + .find(|b| b.bus_id == BusId::EcT0 as u64) + .unwrap(); + match &ec_t0.values[0] { + BusValue::Linear(terms) => { + assert!(terms.iter().any(|t| matches!( + t, + LinearTerm::Column { + coefficient: 1, + column + } if *column == ecsm2::cols::LEN_M1 + ))); + assert!( + terms.iter().any(|t| matches!(t, LinearTerm::Constant(1))), + "the key must add the +1 that turns LEN_M1 back into len", + ); + } + other => panic!("EC_T0 key must be linear, got {other:?}"), + } + + // Digit receives are 2x the bit, because a set digit is carried by BOTH the + // round's doubling and its add and both send. + let jointbit: Vec<_> = buses + .iter() + .filter(|b| b.bus_id == BusId::JointBit as u64) + .collect(); + for bus in &jointbit { + match &bus.multiplicity { + Multiplicity::Linear(terms) => assert!(matches!( + terms.as_slice(), + [LinearTerm::Column { coefficient: 2, .. }] + )), + other => panic!("JointBit multiplicity must be 2*bit, got {other:?}"), + } + } +} + +// ============================================================================= +// The corpus gate: constraints + result +// ============================================================================= + +/// Every emitted row of both chips satisfies every in-chip transition +/// constraint, over `CASES` random ecrecover-shaped evaluations, and the chip's +/// `Q` is the witness's `Q`. +#[test] +fn random_corpus_satisfies_every_constraint() { + let ecsm2_air = busless_air(ecsm2::cols::NUM_COLUMNS, ecsm2::Ecsm2Constraints); + let ecdas2_air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + + let mut rows_sum = 0usize; + let mut rows_max = 0usize; + for (i, w) in corpus().iter().enumerate() { + let (ecsm2_op, ecdas2_ops) = ops_for(4 * i as u64 + 4, w); + rows_sum += ecdas2_ops.len(); + rows_max = rows_max.max(ecdas2_ops.len()); + + let ecsm2_trace = ecsm2::generate_ecsm2_trace(std::slice::from_ref(&ecsm2_op)); + let ecdas2_trace = ecdas2::generate_ecdas2_trace(&ecdas2_ops); + + assert!( + validate_busless(&ecsm2_air, &ecsm2_trace), + "case {i}: an ECSM2 transition constraint failed", + ); + assert!( + validate_busless(&ecdas2_air, &ecdas2_trace), + "case {i}: an ECDAS2 transition constraint failed", + ); + + assert_eq!( + read_bytes(&ecsm2_trace, 0, ecsm2::cols::X_Q, 32), + w.x_q.to_vec(), + "case {i}: chip xQ", + ); + assert_eq!( + read_bytes(&ecsm2_trace, 0, ecsm2::cols::Y_Q, 32), + w.y_q.to_vec(), + "case {i}: chip yQ", + ); + } + println!( + "lincomb2 joint-chain rows: mean {:.1}, max {} over {CASES} cases", + rows_sum as f64 / CASES as f64, + rows_max, + ); +} + +/// The non-degeneracy relation reuses `CARRY_OFFSET_XR`'s window instead of +/// carrying an offset of its own. That is a completeness claim — a carry outside +/// `[-offset, 2^16 − 1 − offset]` costs the *honest* prover a proof — and the +/// generator only checks it under `debug_assert`, so measure it here. +#[test] +fn the_non_degeneracy_carries_fit_the_reused_window() { + let offset = ecdas2::CARRY_OFFSET_DINV; + let (mut lo, mut hi) = (i64::MAX, i64::MIN); + let mut rows = 0usize; + for w in corpus() { + for step in &w.steps { + let d = ecdas2::dinv_witness(step); + rows += 1; + for c in d.c3 { + lo = lo.min(c); + hi = hi.max(c); + assert!( + (0..1 << 16).contains(&(c + offset)), + "carry {c} escapes the window at offset {offset}", + ); + } + } + } + println!( + "d_inv carries over {rows} rows: [{lo}, {hi}], window [{}, {}]", + -offset, + (1 << 16) - 1 - offset, + ); +} + +/// A padding-only trace (no ops) must satisfy every constraint on both chips — +/// the argument that lets error rows zero out and still close at zero carries. +#[test] +fn padding_rows_satisfy_every_constraint() { + let ecsm2_air = busless_air(ecsm2::cols::NUM_COLUMNS, ecsm2::Ecsm2Constraints); + let ecdas2_air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + assert!(validate_busless( + &ecsm2_air, + &ecsm2::generate_ecsm2_trace(&[]) + )); + assert!(validate_busless( + &ecdas2_air, + &ecdas2::generate_ecdas2_trace(&[]) + )); +} + +/// An error row (`status != 0`, no witness) satisfies every constraint: `OK = 0` +/// zeroes every relation, and the witnessed inverse binds the non-zero status. +#[test] +fn error_row_satisfies_every_constraint() { + let air = busless_air(ecsm2::cols::NUM_COLUMNS, ecsm2::Ecsm2Constraints); + for status in 1..=7u64 { + let op = ecsm2::Ecsm2Operation { + timestamp: 4, + addr_q: 0x1000, + addr_p1: 0x2000, + addr_p2: 0x3000, + addr_u: 0x4000, + status, + witness: None, + }; + let trace = ecsm2::generate_ecsm2_trace(&[op]); + assert!( + validate_busless(&air, &trace), + "error row with status {status} must satisfy every constraint", + ); + } +} + +// ============================================================================= +// The corpus gate: bus balance +// ============================================================================= + +/// One row's contribution to a bus: the concrete element vector plus a signed +/// multiplicity. +fn row_contribution( + interaction: &stark::lookup::BusInteraction, + trace: &TraceTable, + row: usize, +) -> (Vec, i128) { + let get = |col: usize| *trace.main_table.get(row, col); + let mult = match &interaction.multiplicity { + Multiplicity::Column(c) => canonical(&get(*c)) as i128, + Multiplicity::Linear(terms) => terms + .iter() + .map(|t| match t { + LinearTerm::Column { + coefficient, + column, + } => *coefficient as i128 * canonical(&get(*column)) as i128, + LinearTerm::ColumnUnsigned { + coefficient, + column, + } => *coefficient as i128 * canonical(&get(*column)) as i128, + LinearTerm::Constant(v) => *v as i128, + }) + .sum(), + other => panic!("unsupported multiplicity in the lincomb2 chips: {other:?}"), + }; + let mut elements = vec![interaction.bus_id]; + for value in &interaction.values { + for element in value.combine_from(get) { + elements.push(canonical(&element)); + } + } + (elements, mult) +} + +/// Accumulates every row of `trace` into `ledger`, signed by sender/receiver, +/// for the interactions whose bus is in `buses`. +fn accumulate( + ledger: &mut HashMap, i128>, + interactions: &[stark::lookup::BusInteraction], + trace: &TraceTable, + buses: &[BusId], +) { + let wanted: Vec = buses.iter().map(|b| *b as u64).collect(); + for interaction in interactions { + if !wanted.contains(&interaction.bus_id) { + continue; + } + for row in 0..trace.num_rows() { + let (key, mult) = row_contribution(interaction, trace, row); + if mult == 0 { + continue; + } + let sign = if interaction.is_sender { 1 } else { -1 }; + *ledger.entry(key).or_insert(0) += sign * mult; + } + } +} + +/// The four buses the joint chain owns balance exactly, over the whole corpus. +/// +/// `Ecdas` (28) is shared with the single-scalar chain but the joint tuples lead +/// with a non-zero chain id, so nothing here can be matched by the old chips. +/// `EcT0` (32) is included with the real preprocessed table on the other side, so +/// this also checks the `LEN_M1 + 1` keying against the table's 256 rows. +#[test] +fn random_corpus_balances_the_joint_buses() { + use crate::tables::ec_t0; + + let ecsm2_buses = ecsm2::bus_interactions(); + let ecdas2_buses = ecdas2::bus_interactions(); + let ec_t0_buses = ec_t0::bus_interactions(); + let tracked = [BusId::Ecdas, BusId::Addend, BusId::EcT0, BusId::JointBit]; + + let witnesses = corpus(); + let mut ecsm2_ops = Vec::new(); + let mut ecdas2_ops = Vec::new(); + for (i, w) in witnesses.iter().enumerate() { + let (op, rows) = ops_for(4 * i as u64 + 4, w); + ecsm2_ops.push(op); + ecdas2_ops.extend(rows); + } + + let ecsm2_trace = ecsm2::generate_ecsm2_trace(&ecsm2_ops); + let ecdas2_trace = ecdas2::generate_ecdas2_trace(&ecdas2_ops); + let mut ec_t0_trace = ec_t0::generate_ec_t0_trace(); + ec_t0::update_multiplicities(&mut ec_t0_trace, witnesses.iter().map(|w| w.len)); + + let mut ledger: HashMap, i128> = HashMap::new(); + accumulate(&mut ledger, &ecsm2_buses, &ecsm2_trace, &tracked); + accumulate(&mut ledger, &ecdas2_buses, &ecdas2_trace, &tracked); + accumulate(&mut ledger, &ec_t0_buses, &ec_t0_trace, &tracked); + + let unbalanced: Vec<_> = ledger.iter().filter(|(_, v)| **v != 0).collect(); + assert!( + unbalanced.is_empty(), + "{} unbalanced tuple(s); first: bus {} net {}", + unbalanced.len(), + unbalanced[0].0[0], + unbalanced[0].1, + ); + assert!(!ledger.is_empty(), "the ledger must not be trivially empty"); +} + +// ============================================================================= +// Negative controls +// ============================================================================= + +/// Helper: build a single-case ECDAS2 trace and return it with its witness. +fn one_case_ecdas2() -> (Lincomb2Witness, TraceTable) { + let w = lincomb2_witness( + &to_le_32(&scalar(11)), + &to_le_32(&scalar(12)), + &generator(), + &random_point(77), + ) + .unwrap(); + let (_, ops) = ops_for(4, &w); + let trace = ecdas2::generate_ecdas2_trace(&ops); + (w, trace) +} + +/// `OP = S1 + S2 + S3 + S_CORR` is what keeps the Addend receive silent on +/// doublings. Setting a selector on a doubling must break a constraint — without +/// it the double-row addend cancellation is real but its gating is forgeable. +#[test] +fn selector_on_a_doubling_is_rejected() { + let air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + let (w, mut trace) = one_case_ecdas2(); + let double_row = w + .steps + .iter() + .position(|s| s.sel == JointSel::Double) + .expect("the corpus always contains a doubling"); + assert!(validate_busless(&air, &trace), "baseline must be valid"); + trace + .main_table + .set(double_row, ecdas2::cols::S2, FieldElement::::one()); + assert!( + !validate_busless(&air, &trace), + "a selector set on a doubling must be rejected", + ); +} + +/// The addend an add row consumes is pinned to the two digits it carries. Moving +/// `S1` to `S2` on a `(d1, d2) = (1, 0)` add must break a constraint — otherwise +/// the chain could add `P2` where the scalar says `P1`. +#[test] +fn addend_not_matching_the_digits_is_rejected() { + let air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + let (w, mut trace) = one_case_ecdas2(); + let add_p1 = w + .steps + .iter() + .position(|s| s.sel == JointSel::AddP1) + .expect("the corpus always contains a P1 add"); + trace + .main_table + .set(add_p1, ecdas2::cols::S1, FieldElement::::zero()); + trace + .main_table + .set(add_p1, ecdas2::cols::S2, FieldElement::::one()); + assert!( + !validate_busless(&air, &trace), + "an addend that disagrees with the digits must be rejected", + ); +} + +/// The precompute row must add `P2`. Pointing it at `P1` makes the chord +/// `P1 + P1`, whose λ relation degenerates to `0 = 0` and would admit an +/// arbitrary "P12". +#[test] +fn precompute_pointed_at_p1_is_rejected() { + let air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + let (w, mut trace) = one_case_ecdas2(); + let pre = w + .steps + .iter() + .position(|s| s.sel == JointSel::Precompute) + .expect("row 0 is the precompute"); + trace + .main_table + .set(pre, ecdas2::cols::S2, FieldElement::::zero()); + trace + .main_table + .set(pre, ecdas2::cols::S1, FieldElement::::one()); + assert!( + !validate_busless(&air, &trace), + "the precompute row must be pinned to P2", + ); +} + +/// Digits may only live on main-chain rows. A digit on the precompute or +/// correction row — both emitted at `round = 0` — would let a prover satisfy the +/// `2·u_bit(0)` receive with no round-0 add at all. +#[test] +fn digits_outside_the_main_chain_are_rejected() { + let air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + let (w, base) = one_case_ecdas2(); + for sel in [JointSel::Precompute, JointSel::Correction] { + let row = w.steps.iter().position(|s| s.sel == sel).unwrap(); + let mut trace = base.clone(); + trace + .main_table + .set(row, ecdas2::cols::D1, FieldElement::::one()); + assert!( + !validate_busless(&air, &trace), + "a digit on the {sel:?} row must be rejected", + ); + } +} + +/// A padding row (`MU = 0`) is inert on every bus *except* the per-stream digit +/// send, whose multiplicity is the raw `D1`/`D2` column. Without `(1 − MU)·D = 0` +/// a prover drops the real add at some round `r` (a doubling with `D1 = D2 = 0` +/// has `NB = 0`, so nothing forces the add to exist) and supplies the required +/// `2·u_bit(r)` JointBit count from two phantom padding rows — the chain then +/// computes `(u1 − 2^r)·P1 + u2·P2` while the proof claims `u1·P1 + u2·P2`, which +/// is an arbitrary chosen recovered key. +#[test] +fn a_digit_on_a_padding_row_is_rejected() { + let air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + let (w, base) = one_case_ecdas2(); + assert!(validate_busless(&air, &base), "baseline must be valid"); + let pad = w.steps.len(); + assert!(pad < base.num_rows(), "the case must leave padding rows"); + + for digit in [ecdas2::cols::D1, ecdas2::cols::D2] { + let mut trace = base.clone(); + let one = FieldElement::::one(); + // The forgery shape, not a random poke: `PH1 = 1` satisfies + // `(1 − PH1)·D = 0`, `NB = 1` satisfies the doubling's `NB = D1 ∨ D2`, + // and every other column stays zero so all three convolution relations + // still close at zero carries. + trace.main_table.set(pad, ecdas2::cols::PH1, one); + trace.main_table.set(pad, ecdas2::cols::NB, one); + trace.main_table.set(pad, digit, one); + trace + .main_table + .set(pad, ecdas2::cols::ROUND, FieldElement::::from(5u64)); + assert!( + !validate_busless(&air, &trace), + "a live digit on a MU = 0 row must be rejected (column {digit})", + ); + } +} + +/// The same hole on the Addend receive: its multiplicity is `S1 + S2 + S3 + +/// S_CORR`, not `MU`. `MU = 0, OP = 1, S2 = 1` keeps `OP = ΣS` satisfied and +/// mints a spurious addend *publish* consumer out of a padding row. +#[test] +fn an_addend_receive_on_a_padding_row_is_rejected() { + let air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + let (w, base) = one_case_ecdas2(); + let pad = w.steps.len(); + assert!(pad < base.num_rows(), "the case must leave padding rows"); + + for sel in [ + ecdas2::cols::S1, + ecdas2::cols::S2, + ecdas2::cols::S3, + ecdas2::cols::S_CORR, + ] { + let mut trace = base.clone(); + let one = FieldElement::::one(); + trace.main_table.set(pad, ecdas2::cols::OP, one); + trace.main_table.set(pad, sel, one); + assert!( + !validate_busless(&air, &trace), + "an addend selector on a MU = 0 row must be rejected (column {sel})", + ); + } +} + +/// Builds the degenerate add row `A + A` out of a real doubling row's witness. +/// +/// With the addend set to the accumulator the chord λ is undefined, so a prover +/// may pick **any** λ; picking the doubling's own λ makes the row's other two +/// relations reuse that row's quotients and carries verbatim: +/// +/// * λ relation, `op = 1`: `Σ λ_j(xB − xA)_{i−j} + (yA_i − yB_i)` is identically +/// zero, so `q0 = 3p` closes it at zero carries — this is exactly the `0 = 0` +/// collapse that leaves λ free. +/// * xR relation: with `xB = xA` the `op = 1` form `λ² − xA − xB − xR` is the +/// same integer expression as the doubling's `λ² − xA − 0 − xR − (xA − 0)`. +/// * yR relation never reads the addend at all. +fn degenerate_add_step(w: &Lincomb2Witness) -> ecsm::EcdasStep { + let double = w + .steps + .iter() + .find(|s| s.sel == JointSel::Double) + .expect("the corpus always contains a doubling"); + let mut s = double.step.clone(); + s.x_g = s.x_a; + s.y_g = s.y_a; + s.op = 1; + s.next_op = 0; + s.q0 = ecsm::R_BYTES; + s.c0 = [0; 64]; + s +} + +/// An add row whose addend equals its accumulator must be rejected. +/// +/// This is the NUMS-blinding forgery: the prover picks `P2 = μ·T₀`, which makes +/// `acc == addend` (with equal `y`) reachable at a chosen round by one modular +/// inversion and no discrete log. The λ relation then collapses to `0 = 0`, λ is +/// unconstrained, and the rest of the chain follows deterministically to a `Q` +/// that is not `u1·P1 + u2·P2`. +#[test] +fn a_degenerate_add_is_rejected() { + let air = busless_air(ecdas2::cols::NUM_COLUMNS, ecdas2::Ecdas2Constraints); + let (w, base) = one_case_ecdas2(); + assert!(validate_busless(&air, &base), "baseline must be valid"); + + // `AddP2` with `(d1, d2) = (0, 1)` on the main chain: every structural + // constraint (`OP = ΣS`, the digit/addend agreement, the phase rules) is + // satisfied, so nothing but the non-degeneracy check can reject this row. + let step = ecsm::witness::JointStep { + step: degenerate_add_step(&w), + sel: JointSel::AddP2, + d1: 0, + d2: 1, + nb: 0, + }; + let trace = ecdas2::generate_ecdas2_trace(&[ecdas2::Ecdas2Operation { + timestamp: 4, + step: step.clone(), + }]); + assert!( + !validate_busless(&air, &trace), + "an add row whose addend equals its accumulator must be rejected", + ); +} + +/// The ablation control for [`a_degenerate_add_is_rejected`]: the same row, +/// checked against the *single-scalar* ECDAS chip — which shares ECDAS2's λ/xR/yR +/// core byte-for-byte at the same column offsets and has no non-degeneracy +/// relation. It **accepts**, which is what makes the test above a test of the new +/// relation rather than of a botched reconstruction. +#[test] +fn the_degenerate_add_passes_the_chip_without_the_non_degeneracy_check() { + use crate::tables::ecdas; + + let air = busless_air(ecdas::cols::NUM_COLUMNS, ecdas::EcdasConstraints); + let (w, _) = one_case_ecdas2(); + let trace = ecdas::generate_ecdas_trace(&[ecdas::EcdasOperation { + timestamp: 4, + step: degenerate_add_step(&w), + }]); + assert!( + validate_busless(&air, &trace), + "the convolution core alone must accept the degenerate add — otherwise \ + `a_degenerate_add_is_rejected` proves nothing about the new relation", + ); +} + +/// `status == 0` must oblige the proof. A row that claims a zero status while +/// `OK = 0` (proving nothing) must be rejected, or the guest reads a fabricated +/// `Q` out of memory. +#[test] +fn zero_status_without_ok_is_rejected() { + let air = busless_air(ecsm2::cols::NUM_COLUMNS, ecsm2::Ecsm2Constraints); + let op = ecsm2::Ecsm2Operation { + timestamp: 4, + addr_q: 0x1000, + addr_p1: 0x2000, + addr_p2: 0x3000, + addr_u: 0x4000, + status: 3, + witness: None, + }; + let mut trace = ecsm2::generate_ecsm2_trace(&[op]); + assert!( + validate_busless(&air, &trace), + "baseline error row is valid" + ); + + // Rewrite the status to 0 while leaving OK = 0. No choice of S_INV can + // satisfy `STATUS·S_INV = 1 − OK`. + trace + .main_table + .set(0, ecsm2::cols::STATUS, FieldElement::::zero()); + assert!( + !validate_busless(&air, &trace), + "status 0 with OK = 0 must be rejected", + ); +} + +/// The converse: `OK = 1` forces the status to 0. +#[test] +fn nonzero_status_with_ok_is_rejected() { + let air = busless_air(ecsm2::cols::NUM_COLUMNS, ecsm2::Ecsm2Constraints); + let w = lincomb2_witness( + &to_le_32(&scalar(3)), + &to_le_32(&scalar(4)), + &generator(), + &random_point(99), + ) + .unwrap(); + let (op, _) = ops_for(4, &w); + let mut trace = ecsm2::generate_ecsm2_trace(&[op]); + assert!(validate_busless(&air, &trace), "baseline OK row is valid"); + trace + .main_table + .set(0, ecsm2::cols::STATUS, FieldElement::::one()); + assert!( + !validate_busless(&air, &trace), + "a non-zero status with OK = 1 must be rejected", + ); +} + +/// Tampering `yP2` breaks the curve-membership convolution. +#[test] +fn off_curve_p2_is_rejected() { + let air = busless_air(ecsm2::cols::NUM_COLUMNS, ecsm2::Ecsm2Constraints); + let w = lincomb2_witness( + &to_le_32(&scalar(5)), + &to_le_32(&scalar(6)), + &generator(), + &random_point(123), + ) + .unwrap(); + let (op, _) = ops_for(4, &w); + let mut trace = ecsm2::generate_ecsm2_trace(&[op]); + let orig = *trace.main_table.get(0, ecsm2::cols::Y_P2); + trace + .main_table + .set(0, ecsm2::cols::Y_P2, orig + FieldElement::::one()); + assert!( + !validate_busless(&air, &trace), + "an off-curve P2 must be rejected", + ); +} + +/// The correction addend must be the negated blind the table stores, never the +/// positive `2^len·T₀` the witness also records — the two differ only in `y`, so +/// mixing them is a silent sign flip. +#[test] +fn correction_addend_is_the_negated_blind() { + use ecsm::p; + for i in 0..8u64 { + let w = lincomb2_witness( + &to_le_32(&scalar(2 * i + 21)), + &to_le_32(&scalar(2 * i + 22)), + &generator(), + &random_point(300 + i), + ) + .unwrap(); + let (x, y) = ecsm2::correction_addend(&w); + assert_eq!(x, w.x_t0_pow, "x is shared: x(-P) = x(P)"); + let y_pos = BigUint::from_bytes_le(&w.y_t0_pow); + assert_eq!( + BigUint::from_bytes_le(&y), + p() - &y_pos, + "y must be the NEGATED blind, not y_t0_pow", + ); + } +} + +/// The witnessed addend counts are exactly the number of Addend receives, per +/// selector — the precompute row counts towards `P2` because it genuinely adds +/// `P2`. +#[test] +fn addend_counts_match_the_emitted_rows() { + for i in 0..8u64 { + let w = lincomb2_witness( + &to_le_32(&scalar(2 * i + 31)), + &to_le_32(&scalar(2 * i + 32)), + &generator(), + &random_point(400 + i), + ) + .unwrap(); + let (n1, n2, n3) = ecsm2::addend_counts(&w); + let count = + |f: &dyn Fn(JointSel) -> bool| w.steps.iter().filter(|s| f(s.sel)).count() as u64; + assert_eq!(n1, count(&|s| s == JointSel::AddP1)); + assert_eq!( + n2, + count(&|s| s == JointSel::AddP2 || s == JointSel::Precompute), + ); + assert_eq!(n3, count(&|s| s == JointSel::AddP12)); + assert_eq!( + n1 + n2 + n3 + 1, + count(&|s| s != JointSel::Double), + "every non-doubling row receives exactly one addend (+1 correction)", + ); + } +} diff --git a/prover/src/tests/mod.rs b/prover/src/tests/mod.rs index 2d66692a9..a7fdb4555 100644 --- a/prover/src/tests/mod.rs +++ b/prover/src/tests/mod.rs @@ -41,6 +41,8 @@ pub mod disk_spill_tests; #[cfg(test)] pub mod dvrm_tests; #[cfg(test)] +pub mod ec_t0_tests; +#[cfg(test)] pub mod ecdas_tests; #[cfg(test)] pub mod ecsm_tests; @@ -49,6 +51,8 @@ pub mod eq_tests; #[cfg(test)] pub mod keccak_rnd_tests; #[cfg(test)] +pub mod lincomb2_tests; +#[cfg(test)] pub mod load_tests; #[cfg(test)] pub mod local_to_global_bus_tests; @@ -71,6 +75,8 @@ pub mod page_tests; #[cfg(test)] pub mod prove_elfs_tests; #[cfg(test)] +pub mod range_check_balance_tests; +#[cfg(test)] pub mod recursion_smoke_test; #[cfg(test)] pub mod recursion_soundness_gap_poc; diff --git a/prover/src/tests/prove_elfs_tests.rs b/prover/src/tests/prove_elfs_tests.rs index ffe9071b2..da0c16319 100644 --- a/prover/src/tests/prove_elfs_tests.rs +++ b/prover/src/tests/prove_elfs_tests.rs @@ -2747,6 +2747,99 @@ fn test_prove_commit_sum() { assert_eq!(proof.public_output, vec![8u8]); } +/// The guest switch took effect: a real ethrex block routes its ecrecovers +/// through the `ecsm_lincomb2` accelerator. +/// +/// This is the test that makes the two block proofs below mean something. The +/// guest's accelerated path ends in +/// `ecsm_lincomb2(..).unwrap_or_else(|| ProjectivePoint::lincomb(..))`, so an +/// accelerator that declines every call — a stale ELF, a marshalling slip that +/// trips the `P1 != G` status, a `None` from any guard — produces exactly the +/// same block output via the software fallback and every other assertion still +/// passes. Counting real ECSM2 rows is what separates "accelerated" from +/// "silently not accelerated". +/// +/// Execution only: no proving, so this stays in the default suite. +#[test] +fn test_ethrex_block_uses_the_lincomb2_accelerator() { + use crate::tables::ecsm2::cols as ecsm2_cols; + + let _ = env_logger::builder().is_test(true).try_init(); + let workspace_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .to_path_buf(); + let elf_bytes = + std::fs::read(workspace_root.join("executor/program_artifacts/rust/ethrex.elf")) + .expect("need ethrex.elf — run `make compile-programs-rust`"); + let input = + std::fs::read(workspace_root.join("executor/tests/ethrex_5_transfers.bin")).unwrap(); + + let elf = Elf::load(&elf_bytes).expect("Failed to load ELF"); + let executor = + executor::vm::execution::Executor::new(&elf, input).expect("Failed to create executor"); + let result = executor.run().expect("Failed to run program"); + let traces = + Traces::from_elf_and_logs_minimal(&elf, &result.logs, &Default::default(), &[]).unwrap(); + + let one = FieldElement::::one(); + let zero = FieldElement::::zero(); + let accelerated = (0..traces.ecsm2.num_rows()) + .filter(|&r| { + *traces.ecsm2.main_table.get(r, ecsm2_cols::MU) == one + && *traces.ecsm2.main_table.get(r, ecsm2_cols::OK) == one + && *traces.ecsm2.main_table.get(r, ecsm2_cols::STATUS) == zero + }) + .count(); + + // Five transfers, each recovering one sender. + assert_eq!( + accelerated, 5, + "expected one proven lincomb2 per transfer; the accelerator is being \ + declined and the guest is silently using the software fallback", + ); +} + +#[test] +#[ignore = "takes too long"] +fn test_prove_ethrex_5_transfers() { + let _ = env_logger::builder().is_test(true).try_init(); + let workspace_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .to_path_buf(); + let elf_bytes = + std::fs::read(workspace_root.join("executor/program_artifacts/rust/ethrex.elf")) + .expect("need ethrex.elf"); + let input = + std::fs::read(workspace_root.join("executor/tests/ethrex_5_transfers.bin")).unwrap(); + let proof = crate::prove_with_inputs(&elf_bytes, &input).expect("prove"); + assert!( + crate::verify(&proof, &elf_bytes).expect("verify"), + "ethrex 5-transfer block should verify" + ); +} + +#[test] +#[ignore = "takes too long"] +fn test_prove_ethrex_20_transfers() { + let _ = env_logger::builder().is_test(true).try_init(); + let workspace_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .to_path_buf(); + let elf_bytes = + std::fs::read(workspace_root.join("executor/program_artifacts/rust/ethrex.elf")) + .expect("need ethrex.elf"); + let input = + std::fs::read(workspace_root.join("executor/tests/ethrex_20_transfers.bin")).unwrap(); + let proof = crate::prove_with_inputs(&elf_bytes, &input).expect("prove"); + assert!( + crate::verify(&proof, &elf_bytes).expect("verify"), + "ethrex 20-transfer block should verify" + ); +} + #[test] #[ignore = "takes too long"] fn test_prove_ethrex_empty_block() { @@ -3526,3 +3619,271 @@ fn test_epoch_memory_bus_with_l2g_bookend() { "epoch Memory bus must balance with L2G bookend + PAGE excluding touched cells" ); } + +// ============================================================================= +// lincomb2 (ECSM2 / ECDAS2 joint chain) +// ============================================================================= + +/// End-to-end proof of the `ecsm_lincomb2` syscall. +/// +/// The asm guest computes `Q = 3·G + 5·(2G) = 13·G` and commits +/// `status(8) ‖ xQ(32) ‖ yQ(32)`. The committed bytes are cross-checked against +/// an independent `lincomb2_witness` evaluation before the proof is attempted, +/// so a mismatch is reported as a wrong result rather than as a proof failure. +#[test] +fn test_prove_elfs_ecsm_lincomb2() { + let _ = env_logger::builder().is_test(true).try_init(); + + let elf_bytes = crate::test_utils::asm_elf_bytes("test_ecsm_lincomb2"); + let elf = Elf::load(&elf_bytes).expect("Failed to load ELF"); + let executor = + executor::vm::execution::Executor::new(&elf, vec![]).expect("Failed to create executor"); + let result = executor.run().expect("Failed to run program"); + + let committed = &result.return_values.memory_values; + assert_eq!(committed.len(), 72, "expected status(8) ‖ xQ(32) ‖ yQ(32)"); + assert_eq!( + &committed[..8], + &[0u8; 8], + "lincomb2 must succeed for 3·G + 5·(2G)" + ); + + let expected = lincomb2_reference_q(3, 5); + assert_eq!(&committed[8..40], &expected.0, "committed xQ"); + assert_eq!(&committed[40..72], &expected.1, "committed yQ"); + + let mut traces = + Traces::from_elf_and_logs_minimal(&elf, &result.logs, &Default::default(), &[]).unwrap(); + assert!( + prove_and_verify_vm_minimal(&elf, &mut traces), + "lincomb2 prove/verify failed" + ); +} + +/// Soundness: the verifier REJECTS a forged lincomb2 result. +/// +/// `xQ` is bound by the phase-2 chain drain, by the `xQ < p` carry chain and by +/// the output MEMW write, so tampering it must break the proof. +#[test] +fn test_prove_elfs_lincomb2_forged_result_rejected() { + use crate::tables::ecsm2::cols as ecsm2_cols; + + let _ = env_logger::builder().is_test(true).try_init(); + + let elf_bytes = crate::test_utils::asm_elf_bytes("test_ecsm_lincomb2"); + let elf = Elf::load(&elf_bytes).expect("Failed to load ELF"); + let executor = + executor::vm::execution::Executor::new(&elf, vec![]).expect("Failed to create executor"); + let result = executor.run().expect("Failed to run program"); + let mut traces = + Traces::from_elf_and_logs_minimal(&elf, &result.logs, &Default::default(), &[]).unwrap(); + + let orig = *traces.ecsm2.main_table.get(0, ecsm2_cols::x_q(0)); + let forged = orig + FieldElement::::one(); + traces.ecsm2.main_table.set(0, ecsm2_cols::x_q(0), forged); + + assert!( + !prove_and_verify_vm_minimal(&elf, &mut traces), + "Verifier must reject a forged lincomb2 result xQ" + ); +} + +/// End-to-end proof of `ecsm_lincomb2` at the ecrecover shape: both scalars +/// have bit 255 set, so the joint chain runs its maximum schedule (`len = 256`, +/// ~450 ECDAS2 rows) rather than the 8-row toy chain. +#[test] +fn test_prove_elfs_ecsm_lincomb2_full_size() { + let _ = env_logger::builder().is_test(true).try_init(); + + let elf_bytes = crate::test_utils::asm_elf_bytes("test_ecsm_lincomb2_full"); + let elf = Elf::load(&elf_bytes).expect("Failed to load ELF"); + let executor = + executor::vm::execution::Executor::new(&elf, vec![]).expect("Failed to create executor"); + let result = executor.run().expect("Failed to run program"); + + let committed = &result.return_values.memory_values; + assert_eq!(committed.len(), 72); + assert_eq!(&committed[..8], &[0u8; 8], "lincomb2 must succeed"); + + // u1 = 2^255, u2 = 2^255 - 1: complementary bit patterns, so every round + // carries an add and the chain hits its domain maximum. + let u1_words = [0u64, 0, 0, 0x8000_0000_0000_0000]; + let u2_words = [ + 0xFFFF_FFFF_FFFF_FFFFu64, + 0xFFFF_FFFF_FFFF_FFFF, + 0xFFFF_FFFF_FFFF_FFFF, + 0x7FFF_FFFF_FFFF_FFFF, + ]; + let (expected, steps) = lincomb2_reference_q_words(&u1_words, &u2_words); + assert_eq!(&committed[8..40], &expected.0, "committed xQ"); + assert_eq!(&committed[40..72], &expected.1, "committed yQ"); + + // The point of this guest: the worst case is 514 rows, not the ~471 a random + // corpus reaches. A submitter can construct it deliberately, so any + // capacity-shaped bound has to survive here. + // + assert_eq!( + steps, + crate::tables::ecdas2::MAX_ROWS_PER_EVALUATION, + "expected the 514-row worst case (1 + 256 doublings + 256 adds + 1)", + ); + + let mut traces = + Traces::from_elf_and_logs_minimal(&elf, &result.logs, &Default::default(), &[]).unwrap(); + let ecdas2_rows = traces.ecdas2.num_rows(); + assert!( + ecdas2_rows >= crate::tables::ecdas2::MAX_ROWS_PER_EVALUATION, + "the joint chain must fit its worst case, got {ecdas2_rows} padded rows" + ); + assert!( + prove_and_verify_vm_minimal(&elf, &mut traces), + "worst-case lincomb2 prove/verify failed" + ); +} + +/// Two lincomb2 ecalls in one program, against the same operand buffers. +/// +/// The chip performs every MEMW access of a call at one timestamp, so repeated +/// calls hitting the same addresses are what would break the access chain if +/// that scheme were wrong — and repetition is the real shape (a block does many +/// ecrecovers). +#[test] +fn test_prove_elfs_ecsm_lincomb2_multi() { + let _ = env_logger::builder().is_test(true).try_init(); + + let elf_bytes = crate::test_utils::asm_elf_bytes("test_ecsm_lincomb2_multi"); + let elf = Elf::load(&elf_bytes).expect("Failed to load ELF"); + let executor = + executor::vm::execution::Executor::new(&elf, vec![]).expect("Failed to create executor"); + let result = executor.run().expect("Failed to run program"); + + let committed = &result.return_values.memory_values; + assert_eq!( + committed.len(), + 144, + "two status(8) + xQ(32) + yQ(32) blocks" + ); + for (i, (u1, u2)) in [(3u64, 5u64), (7, 11)].into_iter().enumerate() { + let block = &committed[72 * i..72 * (i + 1)]; + assert_eq!(&block[..8], &[0u8; 8], "call {i} must succeed"); + let expected = lincomb2_reference_q(u1, u2); + assert_eq!(&block[8..40], &expected.0, "call {i} committed xQ"); + assert_eq!(&block[40..72], &expected.1, "call {i} committed yQ"); + } + + let mut traces = + Traces::from_elf_and_logs_minimal(&elf, &result.logs, &Default::default(), &[]).unwrap(); + assert!( + prove_and_verify_vm_minimal(&elf, &mut traces), + "multi-call lincomb2 prove/verify failed" + ); +} + +/// `Q = u1·G + u2·(2G)` from the phase-A witness, as `(xQ, yQ)` little-endian. +fn lincomb2_reference_q(u1: u64, u2: u64) -> ([u8; 32], [u8; 32]) { + use executor::vm::instruction::execution::GENERATOR_LE; + use num_bigint::BigUint; + + let point = |bytes: &[u8]| ecsm::AffinePoint { + x: BigUint::from_bytes_le(&bytes[..32]), + y: BigUint::from_bytes_le(&bytes[32..]), + }; + let two_g_le = asm_two_g_le(); + + let mut u1_le = [0u8; 32]; + let mut u2_le = [0u8; 32]; + u1_le[..8].copy_from_slice(&u1.to_le_bytes()); + u2_le[..8].copy_from_slice(&u2.to_le_bytes()); + + let w = + ecsm::witness::lincomb2_witness(&u1_le, &u2_le, &point(&GENERATOR_LE), &point(&two_g_le)) + .expect("reference lincomb2 must succeed"); + (w.x_q, w.y_q) +} + +/// The same, for scalars given as four little-endian doublewords each. Also +/// returns the number of joint-chain rows the witness emits, so a test can pin +/// the schedule length as well as the result. +fn lincomb2_reference_q_words(u1: &[u64; 4], u2: &[u64; 4]) -> (([u8; 32], [u8; 32]), usize) { + use executor::vm::instruction::execution::GENERATOR_LE; + use num_bigint::BigUint; + + let point = |bytes: &[u8]| ecsm::AffinePoint { + x: BigUint::from_bytes_le(&bytes[..32]), + y: BigUint::from_bytes_le(&bytes[32..]), + }; + let two_g_le = asm_two_g_le(); + let pack = |words: &[u64; 4]| { + let mut out = [0u8; 32]; + for (i, w) in words.iter().enumerate() { + out[8 * i..8 * i + 8].copy_from_slice(&w.to_le_bytes()); + } + out + }; + + let w = ecsm::witness::lincomb2_witness( + &pack(u1), + &pack(u2), + &point(&GENERATOR_LE), + &point(&two_g_le), + ) + .expect("reference lincomb2 must succeed"); + ((w.x_q, w.y_q), w.steps.len()) +} + +/// `2G` exactly as every lincomb2 asm guest stores it at `sp+64`, so the tests +/// and the guests cannot drift apart. +fn asm_two_g_le() -> [u8; 64] { + const TWO_G_WORDS: [u64; 8] = [ + 0xABAC_09B9_5C70_9EE5, + 0x5C77_8E4B_8CEF_3CA7, + 0x3045_406E_95C0_7CD8, + 0xC604_7F94_41ED_7D6D, + 0x2364_31A9_50CF_E52A, + 0xF7F6_3265_3266_D0E1, + 0xA3C5_8419_466C_EAEE, + 0x1AE1_68FE_A63D_C339, + ]; + let mut out = [0u8; 64]; + for (i, word) in TWO_G_WORDS.iter().enumerate() { + out[8 * i..8 * i + 8].copy_from_slice(&word.to_le_bytes()); + } + out +} + +/// `count_elements_by_table` must agree with `count_elements` exactly — they +/// share one implementation, and this is what keeps that true. +/// +/// Also asserts the breakdown names the lincomb2 chips, since the phase-H bench +/// reads the EC share by table name. +#[test] +fn test_count_elements_by_table_sums_to_the_totals() { + let elf_bytes = crate::test_utils::asm_elf_bytes("test_ecsm_lincomb2"); + + let (main, aux) = crate::count_elements(&elf_bytes, &[]).expect("count_elements"); + let by_table = crate::count_elements_by_table(&elf_bytes, &[]).expect("by_table"); + + assert_eq!(by_table.iter().map(|t| t.1).sum::(), main, "main"); + assert_eq!(by_table.iter().map(|t| t.2).sum::(), aux, "aux"); + + let names: Vec<&str> = by_table.iter().map(|t| t.0).collect(); + for expected in ["CPU", "ECSM", "ECDAS", "ECSM2", "ECDAS2", "EC_T0"] { + assert!(names.contains(&expected), "missing table {expected}"); + } + assert_eq!( + names.len(), + names.iter().collect::>().len(), + "table names must be unique — a split table should appear once, summed", + ); + + // The EC share this guest actually spends, which is what phase H measures. + let ec: u64 = by_table + .iter() + .filter(|(n, _, _)| n.starts_with("EC")) + .map(|t| t.1 + t.2) + .sum(); + assert!( + ec > 0, + "the lincomb2 guest must spend cells on the EC tables" + ); +} diff --git a/prover/src/tests/range_check_balance_tests.rs b/prover/src/tests/range_check_balance_tests.rs new file mode 100644 index 000000000..f39cf304c --- /dev/null +++ b/prover/src/tests/range_check_balance_tests.rs @@ -0,0 +1,191 @@ +//! Direct balance check on the **range-check buses** (`AreBytes`, `IsHalfword`, +//! `IsB20`, `Msb8`, `Msb16`, `Zero`, `Hwsl`). +//! +//! # Why this exists +//! +//! Every chip that range-checks a column sends on one of these buses, and the +//! BITWISE table's receive multiplicities come from a *separate* hand-written +//! collector (`collect_bitwise_from_*` in `trace_builder.rs`). The two must +//! agree send-for-send; several of those collectors carry a comment saying so. +//! Nothing enforced it: +//! +//! * the `debug-checks` bus tracker reports buses 14..33 only — the range-check +//! buses are **not** in its report at all; +//! * a mismatch surfaces as a whole-proof "LogUp bus does not balance" with no +//! indication of which bus, which table, or which tuple. +//! +//! This test closes that. It evaluates every table's declared interactions +//! against its generated trace and asserts the signed multiplicities cancel per +//! tuple, so a drifted mirror names the offending bus and value immediately. +//! +//! It is cheap (a small guest, well under a second) and it is a pure +//! cross-check: it re-derives nothing, it only reads what the chips declare. + +use std::collections::HashMap; + +use math::field::element::FieldElement; +use math::field::traits::IsPrimeField; +use stark::lookup::{BusInteraction, LinearTerm, Multiplicity}; +use stark::trace::TraceTable; + +use crate::tables::trace_builder::Traces; +use crate::tables::types::{BusId, GoldilocksExtension, GoldilocksField}; + +use executor::elf::Elf; + +type F = GoldilocksField; +type E = GoldilocksExtension; + +/// The buses the BITWISE table serves. These are exactly the ones the +/// `debug-checks` tracker leaves out. +const RANGE_CHECK_BUSES: [BusId; 7] = [ + BusId::AreBytes, + BusId::IsHalfword, + BusId::IsB20, + BusId::Msb8, + BusId::Msb16, + BusId::Zero, + BusId::Hwsl, +]; + +fn canonical(x: &FieldElement) -> u64 { + F::canonical(x.value()) +} + +/// Accumulates one table's range-check interactions into `ledger`, signed by +/// sender/receiver. +fn accumulate( + ledger: &mut HashMap, i128>, + interactions: &[BusInteraction], + trace: &TraceTable, +) { + let wanted: Vec = RANGE_CHECK_BUSES.iter().map(|b| *b as u64).collect(); + for interaction in interactions { + if !wanted.contains(&interaction.bus_id) { + continue; + } + for row in 0..trace.num_rows() { + let get = |col: usize| *trace.main_table.get(row, col); + let value = |col: usize| canonical(&get(col)) as i128; + let multiplicity: i128 = match &interaction.multiplicity { + Multiplicity::One => 1, + Multiplicity::Column(c) => value(*c), + Multiplicity::Negated(c) => 1 - value(*c), + Multiplicity::Sum(a, b) => value(*a) + value(*b), + Multiplicity::Diff(a, b) => value(*a) - value(*b), + Multiplicity::Sum3(a, b, c) => value(*a) + value(*b) + value(*c), + Multiplicity::Linear(terms) => terms + .iter() + .map(|term| match term { + LinearTerm::Column { + coefficient, + column, + } => *coefficient as i128 * value(*column), + LinearTerm::ColumnUnsigned { + coefficient, + column, + } => *coefficient as i128 * value(*column), + LinearTerm::Constant(v) => *v as i128, + }) + .sum(), + }; + if multiplicity == 0 { + continue; + } + let mut key = vec![interaction.bus_id]; + for bus_value in &interaction.values { + for element in bus_value.combine_from(get) { + key.push(canonical(&element)); + } + } + let sign = if interaction.is_sender { 1 } else { -1 }; + *ledger.entry(key).or_insert(0) += sign * multiplicity; + } + } +} + +/// Every range-check bus balances tuple-for-tuple across every table. +/// +/// The guest is the lincomb2 one because that is the newest set of mirrors, but +/// the check is whole-machine: it covers all 30-odd tables, so it also guards +/// the pre-existing collectors against drift. +#[test] +fn range_check_buses_balance_across_every_table() { + let _ = env_logger::builder().is_test(true).try_init(); + + let elf_bytes = crate::test_utils::asm_elf_bytes("test_ecsm_lincomb2"); + let elf = Elf::load(&elf_bytes).expect("Failed to load ELF"); + let executor = + executor::vm::execution::Executor::new(&elf, vec![]).expect("Failed to create executor"); + let result = executor.run().expect("Failed to run program"); + let traces = + Traces::from_elf_and_logs_minimal(&elf, &result.logs, &Default::default(), &[]).unwrap(); + + let mut ledger: HashMap, i128> = HashMap::new(); + + macro_rules! table { + ($module:path, $trace:expr) => {{ + use $module as m; + accumulate(&mut ledger, &m::bus_interactions(), $trace); + }}; + } + macro_rules! tables { + ($module:path, $traces:expr) => {{ + for t in $traces { + table!($module, t); + } + }}; + } + + table!(crate::tables::bitwise, &traces.bitwise); + table!(crate::tables::decode, &traces.decode); + table!(crate::tables::register, &traces.register); + table!(crate::tables::halt, &traces.halt); + table!(crate::tables::commit, &traces.commit); + table!(crate::tables::keccak, &traces.keccak); + table!(crate::tables::keccak_rnd, &traces.keccak_rnd); + table!(crate::tables::keccak_rc, &traces.keccak_rc); + table!(crate::tables::ecsm, &traces.ecsm); + table!(crate::tables::ecdas, &traces.ecdas); + table!(crate::tables::ecsm2, &traces.ecsm2); + table!(crate::tables::ecdas2, &traces.ecdas2); + table!(crate::tables::ec_t0, &traces.ec_t0); + tables!(crate::tables::cpu, &traces.cpus); + tables!(crate::tables::cpu32, &traces.cpu32s); + tables!(crate::tables::lt, &traces.lts); + tables!(crate::tables::shift, &traces.shifts); + tables!(crate::tables::mul, &traces.muls); + tables!(crate::tables::dvrm, &traces.dvrms); + tables!(crate::tables::branch, &traces.branches); + tables!(crate::tables::load, &traces.loads); + tables!(crate::tables::memw, &traces.memws); + tables!(crate::tables::memw_aligned, &traces.memw_aligneds); + tables!(crate::tables::memw_register, &traces.memw_registers); + tables!(crate::tables::eq, &traces.eqs); + tables!(crate::tables::bytewise, &traces.bytewises); + tables!(crate::tables::store, &traces.stores); + for (trace, config) in traces.pages.iter().zip(traces.page_configs.iter()) { + accumulate( + &mut ledger, + &crate::tables::page::bus_interactions(config.page_base), + trace, + ); + } + + assert!( + !ledger.is_empty(), + "the ledger must not be trivially empty — no range-check sends were seen" + ); + let mut unbalanced: Vec<_> = ledger.iter().filter(|(_, net)| **net != 0).collect(); + unbalanced.sort(); + for (key, net) in unbalanced.iter().take(10) { + let bus = BusId::try_from(key[0]).map(|b| b.name()).unwrap_or("?"); + eprintln!(" {bus}{:?} net {net}", &key[1..]); + } + assert!( + unbalanced.is_empty(), + "{} range-check tuple(s) do not balance — a `collect_bitwise_from_*` \ + mirror has drifted from its chip's `bus_interactions()`", + unbalanced.len(), + ); +} diff --git a/prover/src/tests/static_commitments_tests.rs b/prover/src/tests/static_commitments_tests.rs index 01d9817e8..5b6d4b4ce 100644 --- a/prover/src/tests/static_commitments_tests.rs +++ b/prover/src/tests/static_commitments_tests.rs @@ -1,11 +1,11 @@ //! Drift-detection and lookup-dispatch tests for the static preprocessed-table -//! commitments shipped in `bitwise`, `keccak_rc`, and `page` (the shared -//! zero-init page commitment). +//! commitments shipped in `bitwise`, `keccak_rc`, `ec_t0`, and `page` (the +//! shared zero-init page commitment). //! //! - The drift tests recompute the commitment for every blowup in //! `STATIC_BLOWUP_FACTORS` (the list shared with the generator binary) and //! compare against the value the table-module's wrapper returns -//! (`preprocessed_commitment` for `bitwise`/`keccak_rc`, +//! (`preprocessed_commitment` for `bitwise`/`keccak_rc`/`ec_t0`, //! `zero_init_preprocessed_commitment` for `page`). This catches AIR or //! FFT-pipeline drift; the page test additionally pins the static bytes //! against the recompute directly. @@ -22,7 +22,7 @@ use stark::proof::options::GoldilocksCubicProofOptions; -use crate::tables::{STATIC_BLOWUP_FACTORS, bitwise, keccak_rc, page}; +use crate::tables::{STATIC_BLOWUP_FACTORS, bitwise, ec_t0, keccak_rc, page}; fn options_for(blowup: u8) -> stark::proof::options::ProofOptions { GoldilocksCubicProofOptions::with_blowup(blowup).expect("blowup must be a valid power of 2") @@ -76,6 +76,66 @@ fn keccak_rc_static_matches_recompute_for_all_blowups() { } } +/// Drift test for the EC_T0 static commitments. The table's content is a pure +/// function of the pinned NUMS point `T₀`, so this also pins `T₀` itself: any +/// change to `ecsm::witness::t0`, to the doubling chain, or to the column +/// layout moves these bytes. +#[test] +fn ec_t0_static_matches_recompute_for_all_blowups() { + for &blowup in STATIC_BLOWUP_FACTORS { + let options = options_for(blowup); + let from_wrapper = ec_t0::preprocessed_commitment(&options); + let recomputed = ec_t0::compute_preprocessed_commitment(&options); + assert_eq!( + from_wrapper, recomputed, + "ec_t0 commitment drifted (or wrapper dispatch broke) for blowup={blowup}; \ + regenerate constants via `cargo run --bin compute_static_commitments --release`", + ); + } +} + +/// EC_T0 counterpart of `keccak_rc_non_static_blowup_recomputes_via_fallback`. +/// Cheap: the table is 512 rows × 65 preprocessed columns. +#[test] +fn ec_t0_non_static_blowup_recomputes_via_fallback() { + assert!( + !STATIC_BLOWUP_FACTORS.contains(&NON_STATIC_BLOWUP), + "test relies on NON_STATIC_BLOWUP not being in STATIC_BLOWUP_FACTORS", + ); + let options = options_for(NON_STATIC_BLOWUP); + let from_wrapper = ec_t0::preprocessed_commitment(&options); + let recomputed = ec_t0::compute_preprocessed_commitment(&options); + assert_eq!( + from_wrapper, recomputed, + "ec_t0 fallback returned a wrong value at blowup={NON_STATIC_BLOWUP}", + ); +} + +/// Regression test for the `options.coset_offset == 3` gate in +/// `ec_t0::preprocessed_commitment`. +#[test] +fn ec_t0_non_three_coset_recomputes_and_differs_from_static() { + for &blowup in STATIC_BLOWUP_FACTORS { + let opts_coset3 = options_with_coset(blowup, STANDARD_COSET); + let opts_coset7 = options_with_coset(blowup, NON_STANDARD_COSET); + + let from_wrapper_7 = ec_t0::preprocessed_commitment(&opts_coset7); + let recomputed_7 = ec_t0::compute_preprocessed_commitment(&opts_coset7); + let from_wrapper_3 = ec_t0::preprocessed_commitment(&opts_coset3); + + assert_eq!( + from_wrapper_7, recomputed_7, + "ec_t0 wrapper at coset {NON_STANDARD_COSET} must take the recompute path \ + (blowup={blowup})", + ); + assert_ne!( + from_wrapper_7, from_wrapper_3, + "ec_t0 commitment at coset {NON_STANDARD_COSET} must differ from coset \ + {STANDARD_COSET} static value (blowup={blowup})", + ); + } +} + /// Drift / dispatch test for the zero-init PAGE static commitments. For every /// blowup in `STATIC_BLOWUP_FACTORS`, builds a synthetic zero-init page at /// `DEFAULT_PAGE_SIZE` (page_base = 0 — the value doesn't affect the diff --git a/spec/README.md b/spec/README.md index da844e801..b8ea479b9 100644 --- a/spec/README.md +++ b/spec/README.md @@ -1,6 +1,6 @@ # Lambda VM Specification -Formal specification of the Lambda VM. Covers the per-chip AIR constraints (CPU, decode, bitwise, branch, LT, shift, MUL, DVRM, MEMW, LOAD, page, register, halt, commit, keccak), the memory argument, and the LogUp lookup framework that links the tables. +Formal specification of the Lambda VM. Covers the per-chip AIR constraints (CPU, decode, bitwise, branch, LT, shift, MUL, DVRM, MEMW, LOAD, page, register, halt, commit, keccak, ECSM/ECDAS), the memory argument, and the LogUp lookup framework that links the tables. The specification is written in [Typst](https://typst.app/) and rendered as either a PDF or a browsable HTML wiki using [shiroa](https://myriad-dreamin.github.io/shiroa/). diff --git a/spec/about_ecalls.typ b/spec/about_ecalls.typ index 9b37d5f21..4622f8f21 100644 --- a/spec/about_ecalls.typ +++ b/spec/about_ecalls.typ @@ -31,4 +31,5 @@ Negative numbers (represented as 2s complement 64-bit numbers), are used for our / 64: `write` (@commit) / 93: `exit` (@halt) / -1: `SHA256` (@sha256) -/ -2: `KECCAK` (@keccak) \ No newline at end of file +/ -2: `KECCAK` (@keccak) +/ -11: `ECSM` (@ecsm) \ No newline at end of file diff --git a/spec/book.typ b/spec/book.typ index 8bf8612af..21c635351 100644 --- a/spec/book.typ +++ b/spec/book.typ @@ -49,6 +49,7 @@ ("commit.typ", [`COMMIT` chip], ), ("sha256.typ", [`SHA256` accelerator], ), ("keccak.typ", [`KECCAK` accelerator], ), + ("ecsm.typ", [`ECSM` accelerator], ), )) ) ) diff --git a/spec/ecsm.typ b/spec/ecsm.typ new file mode 100644 index 000000000..7e89f7b88 --- /dev/null +++ b/spec/ecsm.typ @@ -0,0 +1,743 @@ +#import "/book.typ": book-page, aside, todo + +#show: book-page("ecsm.typ") + +#let ecsm = raw("ECSM") +#let ecdas = raw("ECDAS") +#let ecsm2 = raw("ECSM2") +#let ecdas2 = raw("ECDAS2") +#let ect0 = raw("EC_T0") +#let lincomb = raw("LINCOMB2") + +The elliptic-curve accelerator computes scalar multiples on the secp256k1 +curve. Its purpose is Ethereum's `ecrecover`: given a signature, recover the +public key that produced it, which for a real block is the single most +expensive operation the guest performs. + +*Two implementations ship side by side.* The _single-scalar path_ proves one +$k dot P$ per call: #ecsm owns the inputs and outputs of a scalar +multiplication and #ecdas proves one step of its double-and-add chain. The +_joint-chain path_ proves a whole two-term linear combination +$Q = u_1 P_1 + u_2 P_2$ in one call: #ecsm2 owns the call and #ecdas2 proves one +step of a joint Shamir--Straus chain. Both pairs are joined by the same +`Ecdas` bus, which telescopes a chain from a core chip's seed to its drain. + +`ecrecover` uses the joint-chain path. The single-scalar path remains live and +is the general-purpose $x$-only accelerator; it is also the chip family the +joint chain was derived from, and every argument in this chapter that is not +explicitly marked as new is shared by both. + +#todo[ + The machine-rendered variable and constraint tables that every other chip + chapter carries (`render_chip_variable_table`, `render_constraint_table`) are + missing here: there is no `src/ecsm.toml`, `ecdas.toml`, `ecsm2.toml` or + `ecdas2.toml` yet, so the column and constraint listings below are prose. + Several doc comments in the prover (`prover/src/tables/ecsm.rs`, `ecdas.rs`, + `crypto/ecsm/src/*.rs`) already point at `spec/src/ecsm.toml` and `ecsm.typ`; + those references were dead until this chapter, and the `.toml` half is still + outstanding. +] + += The curve + +secp256k1 is $y^2 = x^3 + b$ over $FF_p$ with +#footnote([Standards for Efficient Cryptography 2 (SEC 2), version 2.0, section 2.4.1, Certicom Research.]) + +$ p = 2^256 - 2^32 - 977, quad b = 7, $ + +of prime order $N$, with generator $G$. Three properties of these constants are +load-bearing and are used without further comment below: + ++ $p equiv 3 mod 4$, so square roots are $a^((p+1)\/4)$ and a coordinate lift + needs no Tonelli--Shanks; ++ $N$ is prime, so every nonzero residue mod $N$ is invertible; ++ $N$ is odd and $-7$ is not a cube mod $p$, so the curve has no point of order + two: there is no on-curve point with $y equiv 0$. Every doubling in the chain + therefore has a well-defined tangent slope. + +All values crossing the `ECALL` boundary are 32-byte *little-endian* integers. +Inside the chips every 256-bit quantity is carried as 32 range-checked `Byte` +variables, least significant first. + += Byte range checks are paired + +All four chips obtain their byte bounds from the `AreBytes` lookup, and an +`AreBytes` send carries *two* elements, both of which the `BITWISE` receiver +matches against the precomputed table's `X` and `Y` columns. That table +enumerates the full byte-pair space, so a send $[a, b]$ matches a row if and +only if $a$ *and* $b$ are bytes. + +Every byte range check originally shipped as its own send shaped $[b, 0]$, +which is the $y = 0$ special case of that same contract and wastes the second +slot. Adjacent bytes now share one send: + +/ #ecdas: the 32-byte prefixes of `LAMBDA`, `XR`, `YR`, `Q0`, `Q1`, `Q2` pair + internally as $(2i, 2i+1)$, giving 96 sends; of the four remaining odd bytes, + two pairs are formed across blocks --- `(ROUND, Q0[32])` and + `(Q1[32], Q2[32])`. 196 sends become 98, and interactions per row fall from + 388 to *290*. +/ #ecsm: `X2`, `Q0`, `YG` and `Q1`'s 32-byte prefix pair the same way, giving + 64 sends; the odd 33rd quotient byte rides alone as `[q1[32], 0]`. 129 sends + become 65, and interactions per row fall from 579 to *515*. + +#ecdas2 and #ecsm2 use the identical layout from the start. + +*This is a bus repacking and nothing else.* No witness value, column count +(667 for #ecsm, 521 for #ecdas), constraint count (413 and 200) or maximum +degree changes; only `bus_interactions()` and the trace builder's mirrored +multiplicity collectors move, and they move together. + +The saving is in the `LogUp` auxiliary trace, which costs one cubic-extension +column per two interactions --- $1.5$ committed base cells per interaction. For +#ecdas that is 194 auxiliary extension columns down to 145, i.e. 147 fewer +committed base cells against a row of 1,103: *$-13.3%$ of the table's committed +footprint*, on the table that carries the volume. + +Soundness is preserved verbatim, with no lemma re-run. Every lemma of the +machine-checked gate consumes the byte contract *per column*, never per send, +and the set of columns covered is identical before and after --- each +previously-checked byte appears in exactly one paired send. Pairing bytes from +different logical operands is equally sound: an `AreBytes` row asserts no +relation between its two elements, since every combination exists in the table, +so pairing unrelated bytes adds no coupling. The argument is recorded in +`thoughts/ec-recover-opt/gate/pairing-equivalence.md`. + += #ecsm chip + +#ecsm answers system call number $-11$ and contributes one row of 667 columns +per call. Like every accelerator it must place a receiver on the `Ecall` bus, +or that bus does not balance. + +== Interface + +/ `A0` #h(0.6em) `= x10`: address to which the result $x_R$ is written +/ `A1` #h(0.6em) `= x11`: address of the input $x$-coordinate $x_G$ +/ `A2` #h(0.6em) `= x12`: address of the scalar $k$ + +The accelerator is *$x$-only*: it takes an $x$-coordinate, lifts it to the +point with *even* $y$, and returns only the $x$-coordinate of the product. This +is sound because $x(k dot P) = x(k dot (-P))$, so the choice of lift cannot +change the answer. Parity is therefore not this chip's business, and the guest +that needs a signed point recovers the sign itself. + +The executor rejects the call outright --- it does not produce a row --- when +$k = 0$, $k >= N$, $x_G >= p$, or $x_G^3 + b$ is a non-residue. Execution fails +before anything is written, so invalid inputs are *unexecutable* rather than +wrong: no trace containing them exists. The chip nevertheless enforces its own +range checks rather than inheriting them from the executor, because soundness +must not depend on the prover having run the executor honestly. + +== What the row proves + +Writing $mu in {0, 1}$ for the row-live flag, one #ecsm row witnesses $y_G$ and +establishes: + ++ *Curve membership.* $y_G^2 equiv x_G^3 + b mod p$, via two byte-limb + convolution relations with quotients $q_0, q_1$: first $x_2 = x_G^2 - q_0 p$, + then $y_G^2 + mu p^2 - x_G x_2 - mu b - q_1 p = 0$. ++ *Canonical input.* $x_G < p$, as a $2^256$-overflow witness in 16 halfwords. ++ *Scalar range.* $0 < k < N$, likewise. ++ *Canonical output.* $x_R < p$. This one is genuinely load-bearing rather than + hygiene: without it a result $v < 2^32 + 977$ also admits the non-canonical + representation $v + p$, and the guest would receive a different 32-byte + string for the same field element. ++ *Bit decomposition.* $k$ is spread over 256 boolean columns, served to #ecdas + on the `Bit` bus. + +== Limb arithmetic + +Every relation above is a polynomial identity between 256-bit values, proved +one byte-limb at a time. For a relation whose signed limb sequence is $S_i$, +the chip witnesses a carry sequence $c_i$ satisfying + +$ 2^8 dot c_i = c_(i-1) + S_i, quad c_(-1) = 0, quad c_63 = 0. $ + +Telescoping gives $sum_i 2^(8i) S_i = 0$ over the integers, which is the +intended identity. Two details make it work over a 64-bit base field: + +- *Carry offsets.* The $c_i$ are signed; each is range-checked as a `Half` + after adding a per-relation constant, so the shifted value lands in + $[0, 2^16)$. The constants differ per relation because the limb sums do. +- *The closing check $c_63 = 0$.* This is what forbids an unconstrained + overflow at the top limb, and it is not redundant: dropping it admits a + decoded value that is nonzero mod $p$. + +Intermediate quantities are only byte-bounded, i.e. $< 2^256 approx 5.4 p$, not +reduced. That is deliberate --- the relations are mod-$p$ identities and the +quotient absorbs the slack --- and it is why the canonicalisation checks sit at +the boundaries rather than on every row. + +The same machinery, with the same carry offsets, is reused unchanged by +#ecdas, #ecsm2 and #ecdas2; it is described once here. + += #ecdas chip + +#ecdas contributes one row of 521 columns per double-or-add step. A row receives an +accumulator $A$, a fixed addend $G$, a round index and an operation flag from +the `Ecdas` bus; proves $R = 2A$ (when $op = 0$) or $R = A + G$ (when +$op = 1$); and sends $R$ onward with the next round's bookkeeping. Three +convolution relations of the shape described above do the work: + +$ &"slope:" && op dot (lambda (x_G - x_A) + y_A - y_G) + (1 - op) dot (2 lambda y_A - 3 x_A^2) equiv 0 \ + &x_R":" && lambda^2 - x_A - x_G - x_R - (1 - op)(x_A - x_G) equiv 0 \ + &y_R":" && lambda (x_A - x_R) - y_A - y_R equiv 0 $ + +all mod $p$. The single $lambda$ column carries the tangent slope on a doubling +and the chord slope on an addition; the $op$ selector picks the branch. + +== The chain + +Soundness of a scalar multiplication is not a per-row property; it lives in two +bus arguments. + +*Telescoping.* #ecsm sends a seed tuple and receives a drain tuple keyed by the +call's timestamp; each #ecdas row receives a state and sends its successor. +Exact multiset balance then forces the live rows to form disjoint paths from +seeds to drains. The round index never increases and cannot be $-1$ (it is +byte-checked), so no path can cycle, and distinct calls have distinct +timestamps, so no two calls can share a path. For $k = 1$ the seed is drained +immediately and the chip echoes its input. + +*Bit counting.* #ecsm receives one `Bit` tuple per set bit of $k$; the senders +are the one #ecsm send at $"len"_k$ plus one send per #ecdas row that is about +to perform an addition. Balance forces $"len"_k$ to name a set bit, forces an +addition to occur at exactly the set bits below it, and forbids additions at +zero bits. Together with the seed's constants this pins the path's $("round", op)$ +sequence to the reference MSB-first double-and-add schedule of $k$. + +== The incomplete-addition edge + +The chord formula is only valid for $A != plus.minus G$. If $A = G$ the slope +relation degenerates to $0 = 0$ and $lambda$ is *unconstrained*, which would let +a prover choose the result; if $A = -G$ the relation becomes $-2 y_G equiv 0$, +which no on-curve point satisfies, so that case merely rejects. + +For the single-scalar chain the dangerous case is *unreachable*, and +unconditionally so. At an addition the accumulator is $c dot P$ for $c$ the +binary prefix of $k$ consumed so far, and reaching $A = plus.minus G$ needs +$c equiv plus.minus 1 mod N$. After the first doubling $c >= 2$, and $c <= k < N$ +throughout, so $c equiv 1$ is impossible; $c equiv -1$ needs $c = N - 1 >= 2^255$, +which forces $k >= 2N - 2 > N$ and contradicts the range check on $k$. The +argument consumes the $k < N$ check and the prefix structure, and nothing else. + +This paragraph is the one that does *not* survive the joint chain, whose +scalars, points and message are all attacker-supplied. #ecdas2 closes the same +edge a different way --- with a witnessed inverse, and equally unconditionally. + +== Verification status + +The constraint systems of #ecsm and #ecdas have been machine-checked with an +SMT solver: the limb/carry lifting, the mod-$p$ step lemmas and their side +conditions, the chain argument, and an end-to-end pin against an independent +reference are recorded as lemmas L1--L8 in `thoughts/ec-recover-opt/gate/`, with +the transcription anchored by evaluating the model on real prover witnesses +(872k checks). +Two checks were confirmed load-bearing by exhibiting the forgery that appears +when they are removed ($c_63 = 0$ and the $x_R < p$ canonicalisation); four +others are individually redundant but retained. The results rest on stated +contracts for the range-check tables, the `LogUp` multiset argument, `ECALL` +binding and timestamp uniqueness, plus the primality of $p$ and $N$. + += The joint-chain chips + +#ecsm2 and #ecdas2 evaluate $Q = u_1 P_1 + u_2 P_2$ over one joint chain and +return *both* coordinates. They are what `ecrecover` calls. + +== Why the joint chain exists + +`ecrecover` evaluates $Q = u_1 G + u_2 R$. With an $x$-only accelerator the +guest cannot get that in one piece: the old path issued *four* scalar +multiplications --- $x(u_1 G)$, $x((u_1 + 1)G)$, $x(u_2 R)$, $x((u_2 + 1)R)$ +--- and then reconstructed the two missing $y$ coordinates in software, because +the $+1$ queries are the only way to recover a $y$ from an $x$-only oracle. One +joint chain replaces all four chains and the reconstruction. + +== Interface + +The call takes system call number $-12$, the slot directly below #ecsm's, so +that the elliptic-curve accelerators stay contiguous. + +/ `A0` #h(0.6em) `= x10`: address to which $x_Q parallel y_Q$ (64 bytes) is written; on return, a status word +/ `A1` #h(0.6em) `= x11`: address of $x_(P_1) parallel y_(P_1)$ +/ `A2` #h(0.6em) `= x12`: address of $x_(P_2) parallel y_(P_2)$ +/ `A3` #h(0.6em) `= x13`: address of $u_1 parallel u_2$ + +*$P_1$ is pinned to the generator.* The chip has no membership sub-witness for +an arbitrary first point, so instead of proving $P_1$ on-curve it asserts that +memory at `A1` holds exactly $G$, by giving the eight doubleword reads +*constant* values. That costs zero columns and zero constraints and makes +$P_1$'s curve membership a compile-time fact. The executor agrees by +construction: any other bytes at `A1` return status $7$, which is the software +fallback rather than an unprovable block. Generalising later means adding a +membership block and its witness, not reworking the ABI. + +The status word is returned *in a register* rather than as a byte of the result +buffer, so the guest can branch before it reads memory at all and the result +region stays a clean aligned 64 bytes. Status $0$ means success; each rejection +class --- a zero scalar, an out-of-range scalar, an off-curve point, a +non-canonical point, $P_1 = plus.minus P_2$, $Q$ at infinity, and +$P_1 != G$ --- has its own nonzero value, so a debugging or benchmarking path +can tell them apart while the guest only tests against zero. + +== The status contract + +Unlike #ecsm, this call *does not trap* on degenerate input, and that choice is +about availability: a trap would let one crafted transaction make an entire +block unprovable. A nonzero status makes the guest run +`ProjectivePoint::lincomb` in software, which is ordinary proven CPU execution, +so a status that lies in that direction can only waste cycles. + +The converse direction has to be *enforced*, or a prover simply declines to +prove anything, writes status $0$, and the guest reads a fabricated $Q$ out of +memory. #ecsm2 therefore carries two flags rather than one: + +/ `MU`: a real lincomb2 ecall happened at this timestamp. Gates the `Ecall` + receive and the combined `x10` read+write that binds the status. +/ `OK`: the status is $0$, i.e. the chain is proven. Gates *everything else* --- + every operand read, the result write, every range check, every relation, and + every chain, addend and digit bus. + +both `IS_BIT`, with the three constraints + +$ &"OK" dot (1 - "MU") = 0 \ + &"OK" dot "STATUS" = 0 \ + &"MU" dot ("STATUS" dot "S"_"INV" - (1 - "OK")) = 0. $ + +The first says a proven chain implies a real ecall; the second says claiming +the chain forces the status to zero; the third says a real ecall that does not +claim the chain must carry an *invertible*, i.e. nonzero, status. The witnessed +inverse is what keeps the per-variant error codes distinguishable --- a boolean +status would work too, and would lose them. + +An error row is therefore not the same thing as a padding row. It sets +$"OK" = 0$ with every math column zero, so all convolution and carry relations +close at zero carries by exactly the argument padding rows already use, but it +keeps $"MU" = 1$ and carries the real result address and status that the `x10` +access binds. The split is not stylistic. The CPU sends on `Ecall` for every +ecall, so an unmatched syscall unbalances that bus and the all-zero padding +trick is unavailable; and the $P_1 != G$ status must stay provable, which it +would not be if the `A1` reads --- which assert that memory there holds $G$ --- +were gated by `MU` instead of `OK`. + +== Schedule + +The chain is a joint (Shamir--Straus) double-and-add over both scalars at once, +MSB-first, with one doubling per round regardless of the digits: + +#raw( +" precompute : P12 = P1 + P2 (a standalone chord add) + for round = len-1 .. 0: + double : acc = 2*acc + if the joint digit is nonzero: + add : acc = acc + addend, addend in {P1, P2, P12} + correction : Q = acc + (-2^len * T0)", + block: true, +) + +with $"len" = max(op("msb")(u_1), op("msb")(u_2)) + 1$, and the accumulator +seeded at the blinding point $T_0$ below rather than at infinity. + +Two rows break the otherwise uniform telescoping, and they are the places the +implementation had to work hardest: the *precompute* row sits off the +accumulator line entirely (its left operand is $P_1$, not the previous row's +result), and the *correction* row consumes the last accumulator against a +constant addend. Every other row's left operand is its predecessor's result. + +Neither break can be distinguished by the round index --- both special rows are +emitted at $"round" = 0$, and the main loop's last iteration also produces +genuine round-$0$ rows. The chain is instead split into three separately keyed +*phases*, carried as $"PHASE" = "PH"_1 + 2 "PH"_2$ with $"PH"_1 dot "PH"_2 = 0$ +inside the `Ecdas` tuple: + +/ phase 0 --- precompute: exactly one row, seeded with $a = P_1 = G$ and addend + $P_2$, drained into #ecsm2's $P_(12)$ columns. +/ phase 1 --- main chain: seeded with $a = T_0$ at round $"len" - 1$; $"len"$ + doublings and their adds. +/ phase 2 --- correction: exactly one row, seeded with the last accumulator and + addend $-2^"len" dot T_0$, drained into #ecsm2's $Q$ columns. + +#ecsm2 pins every segment at *both* ends at multiplicity `OK`, so a row can +execute in a phase only if #ecsm2 published that phase, and exactly one phase-0 +and one phase-2 row can exist per proven call. + +The phase-1 to phase-2 hand-off deliberately goes *through* #ecsm2 --- the +phase-1 drain is received into accumulator columns and re-sent as the phase-2 +seed --- rather than along the chain. A direct hand-off is not expressible: a +row's outgoing tuple pins its successor's $op$ to its own $"NB"$ flag, and the +last main-chain row has $"NB" = 0$ while the correction row is an addition. + +*Round bookkeeping.* A doubling and its optional add share a round, so the +successor round is $"round" - 1 + "NB"$ and the successor $op$ is $"NB"$ --- +exactly the mechanism the single-scalar chain uses, under the joint name "an +add follows me at this round". On a doubling $"NB"$ is the OR of that round's +two digits; the defining constraint is $op$-gated, because an add row carries +the same digits (it needs them to select its addend) but always has $"NB" = 0$. + +*Doubling rows carry no addend.* On $op = 0$ no relation reads the addend: the +slope's $op = 0$ branch mentions neither coordinate, $x_R$'s $-x_G$ term +cancels exactly against $(1 - op)(x_G - x_A)$, $y_R$ uses neither, and the +non-degeneracy relation below sits entirely inside its own gate. So doubling +rows carry the addend $(0, 0)$ and stay silent on the addend bus --- but only +because $op = S_1 + S_2 + S_3 + S_"CORR"$ forces every selector to zero there. +Without that one degree-1 constraint the cancellation is still real and the +*gating* is forgeable: a prover would set a selector on a doubling and mint a +spurious addend receive. + +== Shape and cost + +#ecsm2 contributes one row of 1,155 columns and 817 interactions per ecall; +#ecdas2 one row of 658 columns, 288 constraints and 388 interactions per joint +step. At $1.5$ committed base cells per interaction that is about 2,380 cells +for the #ecsm2 row and *1,240* cells per #ecdas2 row. + +The chain is $449.1$ rows per `ecrecover` on average. *Capacity must be +budgeted at 514*, which is $1 + 256 + 256 + 1$: the worst case over the valid +input domain is $(u_1, u_2) = (2^255, 2^255 - 1)$, both in $[1, N)$ with +*complementary* bit patterns, so every one of the 256 rounds carries a nonzero +joint digit and therefore an addition. It is complementarity that maximises, +not popcount --- $(N-1, N-1)$ shares every addition and reaches only 449. A +submitter can construct the worst case deliberately and cheaply, so no bound +may be read off a random sample; the mean governs the cost model and nothing +else. + +Against the live post-pairing baseline of $1.467"M"$ committed base cells per +`ecrecover` (four chains of 382 #ecdas rows plus four #ecsm rows), the joint +chain costs $0.559"M"$ at the mean and $0.640"M"$ at the 514-row worst case: + +#figure(table( + columns: 4, + align: (left, right, right, right), + table.header([], [rows], [cells per `ecrecover`], [vs. baseline]), + [baseline (4 $times$ #ecsm)], [4 $times$ 382], [1.467M], [---], + [joint chain, mean], [449.1], [0.559M], [$-61.9%$], + [joint chain, worst case], [514], [0.640M], [$-56.4%$], +)) + +The design document's headline of $-74.3%$ should *not* be quoted: it is +denominated against the pre-pairing baseline of $1.69"M"$, so it re-banks the +paired-range-check win described above on top of this one. The +non-degeneracy relation, which is what makes the chain unconditionally sound, +also costs roughly 129 columns and 96 interactions per #ecdas2 row --- so part +of the gap between the two figures was spent buying soundness, and that is +worth stating alongside the number. + +The secondary win is guest cycles: $approx 78.5"k"$ fewer per `ecrecover`, +measured on two ethrex blocks that agree to $0.4%$. The design document +predicted 100--150k, so the measurement is below the low end of the estimate. + +== The blinding point $T_0$ + +$T_0$ is a nothing-up-my-sleeve point: it must be *verifiably not chosen*. It +is derived by SHA-256 try-and-increment from a fixed tag: + +#raw( +"tag = \"lambdavm/ecsm/lincomb2/T0/v1\" (28 ASCII bytes) +for counter = 0, 1, 2, ...: + x = int_be( SHA-256( tag || counter_be32 ) ) + if x < p and x^3 + 7 is a square mod p: + y = the EVEN square root of x^3 + 7 mod p + return (x, y)", + block: true, +) + +Counter $0$ yields no valid $x$; counter $1$ succeeds: + +$ &x(T_0) = "0xaf319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864" \ + &y(T_0) = "0x1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0" $ + +The even root is taken for determinism; either root would serve. + +*What the blind buys is one simplification, and nothing else.* Because the +accumulator starts at $T_0$ and the correction is keyed by $"len"$, any +$"len"$ at least as large as the true one yields the same $Q$: the extra +leading doublings only double $T_0$, and the keyed correction absorbs them. So +$"len"$ never has to be pinned to the exact MSB, and the sub-lemma that would +have done so is dropped outright. The blind was *also* intended to close the +incomplete-addition edge; it does not, and "Security assumptions" below says +why. It is a convenience, not a defence. + +== The #ect0 table + +The correction row subtracts $2^"len" dot T_0$, supplied from a preprocessed +table of 66 columns and exactly 256 rows, every one of them real. Row $j$ holds +the key $"len" - 1 = j$ and the point for $"len" = j + 1$. + +The table stores the *negation* $-2^"len" dot T_0$ directly. That is not a +preference: it is what the witness generator emits as the correction row's +addend, so the lookup wires straight into #ecdas2's addend columns with no +in-circuit modular negation. Only $y$ differs from the positive blind, since +$x(-P) = x(P)$, which makes mixing the two conventions a silent sign flip that +still type-checks. + +Keying by $"len" - 1$ rather than $"len"$ makes the bound $"len" <= 256$ +*structural*. The consumer sends a plain $"len"$ and the table's receive key +re-adds the $1$, so the published key range is exactly $[1, 256]$ with one row +per value and nothing else in the table --- a send outside it matches no row, +`LogUp` cannot balance, and the proof is rejected. No consumer-side check is +needed, and none should be added. An earlier design keyed by $"len"$ directly +over 257 rows padded to 512, and *did* need one: a send at $"len" > 256$ would +have resolved to a zeroed padding row holding the off-curve point $(0, 0)$, +which the correction row would then have added. + +The contents are a deterministic doubling chain off the pinned $T_0$, so the +table is constant in every sense that matters and needs no separate trust. + +== Buses + +Beyond `Ecall`, `Memw`, `AreBytes`, `IsHalfword` and `Zero`, the joint chain +uses: + +/ `Addend` (29): $["ts"_"lo", "ts"_"hi", "sel", x(32), y(32)]$. #ecsm2 publishes + the three point addends at witnessed counts and the correction constant at + multiplicity `OK`; #ecdas2 receives once per addend-consuming row at + multiplicity $S_1 + S_2 + S_3 + S_"CORR"$, with + $"sel" = S_1 + 2 S_2 + 3 S_3 + 4 S_"CORR" in {1, 2, 3, 4}$. The multiplicity + is linear in four terms rather than the three-term form, because the + correction row is the fourth. $"sel"$ is *never* $0$: a bus element that is + zero on a row contributes nothing to the fingerprint, so a $"sel" = 0$ addend + would alias a shorter tuple. +/ `EcT0` (32): the #ect0 lookup described above. +/ `JointBit` (33): $["ts"_"lo", "ts"_"hi", "round", "stream"]$ with + $"stream" in {1, 2}$, one stream per scalar. #ecdas2 sends at multiplicity + $D_1$ or $D_2$; #ecsm2 receives at $2 dot "bit"$. + +The factor of $2$ on the `JointBit` receive is load-bearing, not bookkeeping. A +set digit is carried by *both* the round's doubling and its add, and both send, +so a $2 times$ receive is what forces the add to exist at all --- with only the +doubling available the total can never reach two. At $1 times$ there is a +concrete counterexample: at a round where both digits are set, a prover splits +them across the two rows and the add then selects $P_2$ where the schedule +calls for $P_(12)$. + +The `Ecdas` bus (28) is *shared* with the single-scalar chain. What separates +them is the first tuple element, a constant $0$ for the old chain and $1$ for +the joint one, so the difference of the two fingerprint polynomials has a +nonzero coefficient at a fixed power of the challenge. Differing arity would +*not* have sufficed: the fingerprint's positional weights advance +unconditionally and trailing zeros never re-align a tuple, but zero-padding a +tuple to a common width is a designed-in feature, so arity alone never +separates two chips on one bus. + +== The non-degeneracy relation + +#ecdas2 carries a *fourth* convolution relation beside the three of #ecdas: + +$ D_"INV" dot (x_B - x_A) equiv 1 mod p. $ + +*This is the check that makes the joint chain sound, and it rests on no +computational assumption.* When $x_B = x_A$ the slope relation degenerates: +with $y_B = y_A$ it reads $0 = 0$ for *every* $lambda$, and $x_R$ and $y_R$ +then produce a point of the prover's choosing which the rest of the chain +accepts --- the addend balance, the digit counting and the phase pinning are +all still satisfied. The row proves nothing. A witnessed inverse of +$x_B - x_A$ exists exactly when $x_B equiv.not x_A mod p$, so imposing it costs +no completeness and closes the case outright. + +It is gated by $S_1 + S_2 + S_3 + S_"CORR"$ --- the same sum that receives the +addend --- so it covers every row that consumes one, including the precompute +and correction rows (both chord adds), and never covers doublings. Gating by +that sum rather than by $op$ is deliberate even though a constraint makes the +two equal: it ties the check to the very expression that counts the addend +receive, so it cannot drift away from the rows that consume one. + +A gated-off row is not a hole. With the gate at zero only the shifted-quotient +term survives, and the limb-lifting argument turns that into +$p dot (mu dot R - q_3) = 0$ --- so the quotient is *pinned* to $3p$ on a live +doubling and to $0$ on a padding row, not left free. Gating at all is a cost +choice rather than a correctness one: $x = 0$ is not on secp256k1, so +$x_B - x_A = -x_A$ would be invertible on doublings too, but there is no addend +there and the cells would be wasted. + +One more degeneracy is closed by its own constraint: the phase-0 row must add +$P_2$. Without that, a prover points the precompute at $P_1$, making the chord +$P_1 + P_1$, whose slope relation degenerates the same way and admits an +arbitrary $P_(12)$. + +== Padding rows must be inert + +"The columns are zero as generated" is *not* an argument --- a malicious prover +fills padding rows freely. Every interaction has to be inert by *constraint*, +and the question to ask of each one is not "is it gated?" but "which column +supplies its multiplicity, and what forces that column to zero?". + +Most interactions in both chips take their multiplicity from `MU` or `OK` and +are inert for free. Two families do not: #ecdas2's digit sends count the raw +digit columns, and its addend receive counts the raw selector sum. The family + +$ (1 - "MU") dot {D_1, D_2, S_1, S_2, S_3, S_"CORR"} = 0 $ + +is what closes them, and both were live forgeries before it was added: + ++ A row with $"MU" = 0$, $"PH"_1 = 1$, $"NB" = 1$, $D_1 = 1$ at any round $r$ + satisfies every other constraint and emits a real `JointBit` digit. *Two* such + rows supply the $2 times$ receive that an honest round pays with its doubling + and its add, so the prover can drop the round-$r$ addition entirely --- with + both digits zero on the real doubling, nothing demands one. The chain then + computes $(u_1 - 2^r) P_1 + u_2 P_2$, and back-solving the signature for a + chosen target needs one modular inversion and no discrete logarithm. The + result is an *arbitrary chosen recovered public key*. ++ A row with $"MU" = 0$, $op = 1$, $S_2 = 1$ keeps $op = sum S$ satisfied and + mints a spurious addend receive. + +$"NB"$ needs no companion: with every selector zero, $op = sum S$ forces +$op = 0$, and the round-bookkeeping constraint then reads $"NB" = D_1 or D_2 = 0$. + +#ecsm2 carries the same discipline for its own two ungated families --- the +scalar bit columns, which are the `JointBit` receive multiplicities, and the +addend publish counts --- with $(sum "bit") dot (1 - "OK") = 0$ and +$N_j dot (1 - "OK") = 0$. + +== Canonicalisation obligations + +The joint chain handles a point whose *sign* matters, which #ecsm never did: +an $x$-only chip is free to lift to whichever $y$ it likes, because +$x(k P) = x(k(-P))$, and that symmetry is exactly what a linear combination +gives up. The two ends of the call are not symmetric, and it is worth being +precise about which is which. + +*The inputs are already bound.* The guest decompresses $R$ from the signature's +$(r, v)$ in software and writes both coordinates to memory; that is proven CPU +execution, and `MEMW` binds what the chip reads to what the guest wrote. The +guest is therefore the parity authority, and the prover has no freedom to +substitute $-P_2$ for $P_2$: doing so would require the guest's own proven +execution to have written different bytes. + +In particular a $y_(P_2) < p$ check does *not* separate a point from its +negation, and must not be described as doing so. Negation is +$(x, y) |-> (x, p - y)$, and both $y$ and $p - y$ are already below $p$; the +non-canonical encoding $y + p$ (which fits in 32 bytes only for the vanishingly +rare $y < 2^32 + 977$) is congruent to $y$, i.e. the *same* point, and changes +no result. The witness carries a $y_(P_2) < p$ column, and it is worth keeping +so that the chip's soundness argument stands on its own constraints rather than +on the correctness of guest code --- the same reason #ecsm re-checks ranges the +executor has already enforced --- but it is *defence in depth, not a forgery +closed*. Removing it is the one negative control in the suite that comes back +with no forgery, and that is the expected result. + +*The output is not bound by anything else,* and here the checks are genuinely +load-bearing: + +/ $x_Q < p$ #h(0.3em) and #h(0.3em) $y_Q < p$: the chip *writes* these bytes, so + the prover chooses them, and `MEMW` then faithfully binds memory to whatever + was written. The relations pin $Q$ only modulo $p$, so a coordinate $v$ below + $2^32 + 977$ also admits the encoding $v + p$: the same field element, a + different 32-byte string. The guest hashes those bytes to form an address, so + the two encodings recover *different addresses*. This is the same finding as + $x_R < p$ for #ecsm, where removing the check was shown to produce a concrete + forgery. + +== Verification status + +The joint-chain chips have their own machine-checked board, recorded in +`thoughts/ec-recover-opt/gate/RESULTS-lincomb2.md`. *Every lemma is discharged +and no lemma is open.* + +The three relation arms #ecdas2 shares with #ecdas were shown textually +identical per arm, modulo the rename of the fixed generator to the per-row +addend. Every lemma quantified over those three relations --- the limb lifting, +the value lemmas, the step lemmas and the no-$y equiv 0$ side condition, L1 +through L5a --- therefore transfers verbatim rather than being re-proved. What +was genuinely redone: + +- *The width audit*, because the addend now varies per row and one of its + values ($P_(12)$) is an interior chip output that is byte-bounded but never + proven $< p$. The existing carry windows still bound it with about $2^39$ of + headroom. The argument never depended on the addend being *canonical*, only + on its limbs being *bytes* --- which is inherited through the keyed addend + tuple, and which would silently break if that tuple were ever repacked to + carry more than one byte per element. +- *The step lemma's side condition*, now discharged unconditionally by the + non-degeneracy relation rather than by any assumption. +- *The counting argument*, over two interleaved digit streams, three phases and + a per-row addend selection. +- *The exact-MSB sub-lemma*, dropped: the blind makes any + $"len" in ["msb" + 1, 256]$ yield the same $Q$, and $"len" <= 256$ is + structural. + +The battery of negative controls produced *seven constructive forgeries* and +zero live holes. Two of the seven were live holes in the chips when the gate +began --- the padding-row digit sends and the missing non-degeneracy relation +--- which is the strongest available evidence that the gate can see real bugs. +Two controls came back redundant and are recorded as such rather than papered +over. + +Before any result was trusted, the transcribed model was evaluated on real +prover witnesses: 265 cases, *5,960 #ecdas2 rows and about 3.3 million +individual checks*, every constraint value zero, every carry inside its window, +every quotient inside 33 bytes, and the prover's own non-degeneracy columns +equal to an independent group-law derivation. + +The standing residual risk is the same one the keccak chapter names: the model +is transcribed by hand from the chips, mitigated but not eliminated by that +anchor. The durable fix is to generate the SMT problem from the constraint IR. + += Security assumptions + +== What is unconditional + +*Everything.* Both chip families follow from their constraint systems alone, +given the range-check contracts, the `LogUp` multiset argument, `ECALL` binding +and timestamp uniqueness, and the primality of $p$ and $N$. + +For the single-scalar chain the incomplete-addition edge is closed outright by +the $k < N$ check. For the joint chain it is closed outright by the witnessed +inverse $D_"INV" dot (x_B - x_A) equiv 1 mod p$. *The joint-chain path rests on +no cryptographic assumption that the single-scalar path did not.* + +== The assumption that was proposed, and why it is not used + +The joint chain was originally designed to close the incomplete-addition edge +by blinding: seed the accumulator at $T_0$, so that every intermediate +accumulator is $2^j T_0 + (c_1 P_1 + c_2 P_2)$ and a collision appears to +require a known linear relation on $log(T_0)$ --- a discrete logarithm nobody +has. That would have named an assumption: + +#aside("Assumption T0-DL (blinding-point discrete log) --- NOT USED, DO NOT SIGN")[ + No efficient prover can produce a known linear relation on $log(T_0)$: no + probabilistic polynomial-time algorithm, given the public description of + secp256k1 and the point $T_0$, outputs integers $(alpha, beta)$ with + $alpha equiv.not 0 mod N$ and $alpha T_0 = beta G$. + + Because $N$ is prime this is *equivalent* to computing $log_G (T_0)$, i.e. it + is exactly the discrete-logarithm problem instantiated at one fixed, + verifiably-unchosen point. As an assumption it is unobjectionable and + introduces no new hardness class. + + *The problem is not the assumption. It is that the reduction to it does not + close* --- so assuming it would buy nothing. +] + +The reduction assumes the prover cannot relate $P_1$ and $P_2$ to $T_0$. It +can. For `ecrecover`, $P_2 = R = "lift"_x (r)$ and $r$ is a signature component +the submitter chooses freely, so the prover may set $P_2 = mu T_0$ for a $mu$ +it picks, and the $T_0$ coefficient of the collision equation cancels against +$P_2$'s. Writing the accumulator entering the addition at round $j$ as +$"acc" = alpha T_0 + beta_1 G + beta_2 P_2$, with $alpha, beta_1, beta_2$ +public functions of the schedule and the scalar bits, and taking +$u_1 < 2^j$ so that $beta_1 = 0$, the collision +$"acc" = "addend" = P_2$ reduces to a single scalar equation + +$ alpha + mu (beta_2 - 1) equiv 0 mod N quad ==> quad mu = -alpha \/ (beta_2 - 1), $ + +one modular inversion. With $P_1 = G$ and $u_1 = 1$ it takes the concrete form +$mu (c_2 - 1) equiv -2^j mod N$. The construction costs one scalar +multiplication and no search at all --- *cheaper* than the corresponding attack +on the unblinded chain, which the blind was introduced to prevent. It was +verified 5 out of 5 over a range of schedule lengths, each instance packaged as +a well-formed $(z, v, r, s)$, corroborated by the Python reference, the Rust +witness and an independent Jacobian implementation. +#footnote([`thoughts/ec-recover-opt/oracle/nums_blinding_probe.py`; writeup in `thoughts/ec-recover-opt/lincomb2/FINDING-nums-blinding.log`.]) + +The witness generator rejects all of these with a nonzero status, so the +honest path never reaches them; the forgery lives entirely on the +malicious-prover side, where a row never passes through the witness generator +at all. *Only a constraint can catch it*, which is what the non-degeneracy +relation is. + +== What the blinding is retained for + +The blind survives for a reason that has nothing to do with soundness: it lets +any $"len"$ at least as large as the true MSB yield the correct $Q$, which +drops the exact-MSB sub-lemma from the counting argument and lets $"len" <= 256$ +be structural in the #ect0 table. That is a convenience. It should not be +described as a defence, and no part of the soundness argument may appeal to it. diff --git a/syscalls/src/syscalls.rs b/syscalls/src/syscalls.rs index 7165dff81..e4e91a8f3 100644 --- a/syscalls/src/syscalls.rs +++ b/syscalls/src/syscalls.rs @@ -33,6 +33,16 @@ const KECCAK_SYSCALL_NUMBER: usize = usize::MAX - 1; #[cfg(target_arch = "riscv64")] const ECSM_SYSCALL_NUMBER: usize = usize::MAX - 10; +/// Syscall number for the ECSM secp256k1 `lincomb2` accelerator (-12 as usize). +/// Must match `executor::vm::instruction::execution::ECSM_LINCOMB2_SYSCALL_NUMBER`. +#[cfg(target_arch = "riscv64")] +const ECSM_LINCOMB2_SYSCALL_NUMBER: usize = usize::MAX - 11; + +/// `ecsm_lincomb2` succeeded and wrote `Q`. Every other status means the accelerator +/// produced nothing and the caller must fall back to software. +/// Must match `executor::vm::instruction::execution::LINCOMB2_STATUS_OK`. +pub const ECSM_LINCOMB2_OK: u64 = 0; + /// No-op. The `Print` ecall (a7=1) has no receiver on the Ecall bus, so emitting /// it makes the LogUp bus unbalance and the proof fail to verify. Printing isn't /// needed in provable programs, so `print_string` does nothing on every target. @@ -187,6 +197,46 @@ pub fn ecsm_mul(_xr: &mut [u8; 32], _xg: &[u8; 32], _k: &[u8; 32]) { unimplemented!("syscalls are only implemented for riscv64 targets"); } +#[cfg(target_arch = "riscv64")] +/// Compute `Q = u1·P1 + u2·P2` on secp256k1 via the ECSM `lincomb2` accelerator. +/// +/// Every operand is 64 bytes: two 32-byte little-endian values back to back — +/// `q = xQ‖yQ`, `p1 = xP1‖yP1`, `p2 = xP2‖yP2`, `u = u1‖u2`. All four buffers must be +/// 8-byte aligned and pairwise non-overlapping, including `q` against the inputs. +/// +/// `p1` must be the secp256k1 generator `G`: the accelerator has no membership witness +/// for an arbitrary first point, so it reports a non-zero status for any other `P1` +/// rather than returning a result it cannot prove. +/// +/// Returns the status word. [`ECSM_LINCOMB2_OK`] means `q` now holds `Q`. **Any other +/// value means `q` was left untouched** and the caller must compute the linear +/// combination in software; the accelerator returns a status rather than trapping so +/// that degenerate inputs (`u = 0`, `u >= N`, an off-curve or non-canonical point, +/// `P1 ≠ G`, `P1 = ±P2`, `Q = ∞`) can never abort the proof. Falling back is always +/// sound: the software path is proven guest execution, so a wrong status only costs +/// cycles. +pub fn ecsm_lincomb2(q: &mut [u8; 64], p1: &[u8; 64], p2: &[u8; 64], u: &[u8; 64]) -> u64 { + let mut status = q.as_mut_ptr() as usize; + unsafe { + asm!( + "ecall", + inlateout("a0") status, // x10 = address to write Q, status on return + in("a1") p1.as_ptr(), // x11 = address of xP1‖yP1 + in("a2") p2.as_ptr(), // x12 = address of xP2‖yP2 + in("a3") u.as_ptr(), // x13 = address of u1‖u2 + in("a7") ECSM_LINCOMB2_SYSCALL_NUMBER, + ) + } + status as u64 +} + +#[cfg(not(target_arch = "riscv64"))] +/// Compute `Q = u1·P1 + u2·P2` on secp256k1 via the ECSM `lincomb2` accelerator +/// (64-byte operands, each two 32-byte little-endian values). +pub fn ecsm_lincomb2(_q: &mut [u8; 64], _p1: &[u8; 64], _p2: &[u8; 64], _u: &[u8; 64]) -> u64 { + unimplemented!("syscalls are only implemented for riscv64 targets"); +} + // ============================================================================= // Stub implementations for unsupported std functions // These functions are required by Rust's std zkvm module but are not supported diff --git a/thoughts/ec-recover-opt/bench-harness/Cargo.lock b/thoughts/ec-recover-opt/bench-harness/Cargo.lock new file mode 100644 index 000000000..e9e68cfb5 --- /dev/null +++ b/thoughts/ec-recover-opt/bench-harness/Cargo.lock @@ -0,0 +1,1226 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytecheck" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0caa33a2c0edca0419d15ac723dff03f1956f7978329b1e3b5fdaaaed9d3ca8b" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "rancor", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crypto" +version = "0.1.0" +dependencies = [ + "digest", + "lambda-vm-syscalls", + "math", + "rand 0.8.7", + "rand_chacha 0.3.1", + "rayon", + "rkyv", + "serde", + "sha3", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "ec-bench-harness" +version = "0.1.0" +dependencies = [ + "lambda-vm-prover", +] + +[[package]] +name = "ecsm" +version = "0.1.0" +dependencies = [ + "k256", + "num-bigint", + "num-traits", +] + +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "ff", + "generic-array", + "group", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "embedded-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "executor" +version = "0.1.0" +dependencies = [ + "ecsm", + "num-bigint", + "rustc-demangle", + "thiserror", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "futures-core" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" + +[[package]] +name = "futures-task" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" + +[[package]] +name = "futures-util" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "elliptic-curve", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lambda-vm-prover" +version = "0.1.0" +dependencies = [ + "crypto", + "digest", + "ecsm", + "executor", + "log", + "math", + "num-bigint", + "rayon", + "rkyv", + "stark", + "sysinfo", +] + +[[package]] +name = "lambda-vm-syscalls" +version = "0.1.0" +dependencies = [ + "embedded-alloc", + "getrandom 0.2.17", + "getrandom 0.3.4", + "lazy_static", + "rand 0.9.5", + "riscv", + "thiserror", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "linked_list_allocator" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897" + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "math" +version = "0.1.0" +dependencies = [ + "getrandom 0.2.17", + "num-bigint", + "num-traits", + "rand 0.8.7", + "rayon", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "munge" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptr_meta" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rancor" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daff8b7b3ccf5f7ba270b3e7a0a4d4c701c5797e38dec27c7e2c3dbb830fed1c" +dependencies = [ + "ptr_meta", +] + +[[package]] +name = "rand" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rend" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "663ba70707f96e871406fe10d68128412e619b06d1d47cb91c3a4c6501176240" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "riscv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "rkyv" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "815cc8a37159a463064825246cadb07961e25cd9885908606f6d08a98d8f8874" +dependencies = [ + "bytecheck", + "hashbrown", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ed1a78a1b19d184b0daa629dd9a024573173ec7d485b287cb369fb3607cc1c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "rlsf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "rustversion", + "svgbobdoc", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha3" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "stark" +version = "0.1.0" +dependencies = [ + "crypto", + "digest", + "itertools", + "log", + "math", + "rayon", + "rkyv", + "serde", + "serde_cbor", + "thiserror", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sysinfo" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "windows", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/thoughts/ec-recover-opt/bench-harness/Cargo.toml b/thoughts/ec-recover-opt/bench-harness/Cargo.toml new file mode 100644 index 000000000..d7760f12f --- /dev/null +++ b/thoughts/ec-recover-opt/bench-harness/Cargo.toml @@ -0,0 +1,16 @@ +# Standalone (like oracle/repo-harness): kept out of the lambda_vm workspace so +# nothing shared has to change. Exists only because +# `prover::count_elements_by_table` is a library function with no CLI +# subcommand — see BENCH.md section 6. +[workspace] + +[package] +name = "ec-bench-harness" +version = "0.1.0" +edition = "2021" + +[dependencies] +prover = { path = "/Users/maurofab/workspace/lambda_vm/prover", package = "lambda-vm-prover" } + +[profile.release] +debug = false diff --git a/thoughts/ec-recover-opt/bench-harness/src/main.rs b/thoughts/ec-recover-opt/bench-harness/src/main.rs new file mode 100644 index 000000000..298b4e68b --- /dev/null +++ b/thoughts/ec-recover-opt/bench-harness/src/main.rs @@ -0,0 +1,86 @@ +//! Per-table cell breakdown for the phase-H EC-share measurement. +//! +//! `prover::count_elements_by_table` is a library function with no CLI +//! subcommand, so this thin binary exposes it. Prints every table's committed +//! base cells (`main + 3·aux`, one extension element being 3 base elements) and +//! the EC share, sorted by cost. +//! +//! Usage: ec-bench-harness [private_input_file] + +use std::process::ExitCode; + +/// Tables that constitute the elliptic-curve accelerator. +const EC_TABLES: &[&str] = &["ECSM", "ECDAS", "ECSM2", "ECDAS2", "EC_T0"]; + +fn main() -> ExitCode { + let mut args = std::env::args().skip(1); + let Some(elf_path) = args.next() else { + eprintln!("usage: ec-bench-harness [private_input_file]"); + return ExitCode::FAILURE; + }; + let elf = match std::fs::read(&elf_path) { + Ok(b) => b, + Err(e) => { + eprintln!("cannot read {elf_path}: {e}"); + return ExitCode::FAILURE; + } + }; + let input = match args.next() { + Some(p) => match std::fs::read(&p) { + Ok(b) => b, + Err(e) => { + eprintln!("cannot read {p}: {e}"); + return ExitCode::FAILURE; + } + }, + None => Vec::new(), + }; + + let rows = match prover::count_elements_by_table(&elf, &input) { + Ok(r) => r, + Err(e) => { + eprintln!("count_elements_by_table failed: {e:?}"); + return ExitCode::FAILURE; + } + }; + + // committed base cells = main + 3 * aux (aux is counted in EF columns) + let mut table: Vec<(&str, u64)> = rows + .iter() + .map(|(name, main, aux)| (*name, main + 3 * aux)) + .collect(); + let total: u64 = table.iter().map(|(_, c)| *c).sum(); + let ec: u64 = table + .iter() + .filter(|(n, _)| EC_TABLES.contains(n)) + .map(|(_, c)| *c) + .sum(); + + table.sort_by_key(|(_, c)| std::cmp::Reverse(*c)); + println!("{:<24} {:>16} {:>8}", "table", "base cells", "share"); + for (name, cells) in &table { + if *cells == 0 { + continue; + } + let mark = if EC_TABLES.contains(name) { " <- EC" } else { "" }; + println!( + "{:<24} {:>16} {:>7.2}%{}", + name, + cells, + 100.0 * *cells as f64 / total as f64, + mark + ); + } + println!(); + println!("total base cells : {total}"); + println!("EC base cells : {ec}"); + println!( + "EC SHARE : {:.2}%", + 100.0 * ec as f64 / total as f64 + ); + println!(); + println!("NOTE: only meaningful on a REAL ethrex block. On small guests the"); + println!("fixed-size tables (BITWISE is a fixed 2^16 rows, PAGE is fixed per"); + println!("page) dominate and the share is an artefact. See BENCH.md section 4.1."); + ExitCode::SUCCESS +} diff --git a/thoughts/ec-recover-opt/chips-map.md b/thoughts/ec-recover-opt/chips-map.md new file mode 100644 index 000000000..009d3dc75 --- /dev/null +++ b/thoughts/ec-recover-opt/chips-map.md @@ -0,0 +1,145 @@ +# ECSM / ECDAS chip map — z3 gate input + cost census + +> **UPDATE (feat/ec-arebytes-pairing):** candidate A1/A2 below LANDED — the +> single-byte AreBytes sends are now paired (ECDAS 388→290, ECSM 579→515 +> interactions/row, ≈ −13.3% ECDAS committed cells). The census tables below +> describe the PRE-pairing layout the gate verified; see +> `gate/pairing-equivalence.md` for the rewrite argument and new counts. + +Working doc for the EC RECOVER optimization campaign (keccak-hwsl-inline playbook: +oracle → verify existing → gate-proved rewrite → bench). Status: mapping done +2026-07-24; oracle agent running; z3 gate not started. + +## The ecrecover pipeline (who does what) + +1. **Guest** (`crypto/ethrex-crypto/src/lib.rs`): parses sig, computes + `u1 = −z/r, u2 = s/r`; evaluates `pk = u1·G + u2·R` via **4 x-only ECSM + syscalls** (`x(k·P)`, `x((k+1)·P)` for each of the two terms — the +1 query + exists only to recover y from an x-only oracle, `solve_y` λ-linear trick at + lib.rs:252) + one affine add. Plain RV64 guest code, proven by CPU tables. +2. **ECSM chip** (`prover/src/tables/ecsm.rs`, 667 cols, 413 constraints, + **1 row per ecall**): reads (xG, k) from memory via MEMW, witnesses yG, + proves curve membership `yG² ≡ xG³ + 7 mod p` (two byte-convolutions: + `x2 = xG² − q0·p`, `yG² + µp² − xG·x2 − µ·b − q1·p = 0`), range-proves + `xG < p`, `0 < k < N`, `xR < p` (2^256-overflow carry chains + Zero bus), + bit-decomposes k (256 bit cols), seeds/drains the Ecdas bus, serves scalar + bits on the Bit bus. +3. **ECDAS chip** (`prover/src/tables/ecdas.rs`, 521 cols, 200 constraints, + **1 row per double/add step**): receives `(A, G, round, op)` on Ecdas bus, + proves `R = 2A` (op=0) or `R = A + G` (op=1) via 3 byte-convolution mod-p + relations (λ, xR, yR), sends `(R, round−1+next_op, next_op)` back. Rows + telescope; ~len_k doubles + (popcount−1) adds per scalar mul ≈ 382 rows for + a random 256-bit scalar. + +Witness: `crypto/ecsm/src/witness.rs` replays double-and-add over k256 +(untrusted — the chip re-proves every step). + +## Column-role map + +### ECSM (cols module, ecsm.rs:34) +| Cols | Role | Range authority | +|---|---|---| +| 0..8 | ts, addr_xG/k/xR (lo/hi) | MEMW consistency | +| XR 8, YR 40 (32B each) | result point | XR: bytes @store-time? NO — xR is WRITTEN, byte-checked implicitly by MEMW write path? xR_sub_p gives xR N ⇒ unreachable. + **Gate must formalize this side condition** (needs k < N which IS checked). +4. **Non-canonical reps mid-chain**: xR/yR/λ only byte-checked (< 2^256 ≈ + 5.4p). Relations are mod-p (quotient absorbs), so values ≡ correct mod p; + curve membership propagates by induction from the ECSM-checked seed. Final + xR < p checked in ECSM. Gate: prove step lemma modulo p over Z (not BV!) + + quotient-range/no-wrap audit: max |integer LHS| vs q ≤ (2^264−1), r = 3p + headroom, carry bounds ±~32k vs offsets, all ≪ Goldilocks wraparound — + **the width-audit equivalent**. Keccak lesson applies: bound-necessity + proofs need Int-mod-p, not BV (2^k invertible mod p). +5. **Splicing**: two ecalls same ts impossible (ts unique per ecall — verify + in executor). Cross-curve id byte constant 0 today. + +## Cost census (rule: every interaction ≈ 1.5 base cells of LogUp aux; split_interactions = 2 interactions/ext aux col, ext = 3 base) + +### ECDAS per row — THE volume table +- Logic cells: 521 +- Interactions: 1 Ecdas recv + 196 AreBytes (**all sent as [byte, 0]!**) + + 189 IsHalfword (63×3 carries) + 1 Bit + 1 Ecdas send = **388** +- Aux ≈ 582 base cells ⇒ **~1,103 committed base cells/row; bus = 53%** +- Carry machinery alone: 192 cells + 189 sends(≈284 aux) ≈ **476 cells/row = 43%** + +### ECSM per row (few rows — 4/ecrecover; not the bottleneck) +- Logic 667; interactions ≈ 579 (129 AreBytes[b,0] + 174 IsHalfword + 256 Bit + receivers + 15 MEMW + ecall + Zero + 2 Ecdas) ⇒ ~1,537 cells/row + +### Per ecrecover (4 x-only scalar muls, random ~256-bit scalars) +- ECDAS rows ≈ 4 × (255 D + ~127 A) ≈ **1,528 rows ≈ 1.69M base cells** +- ECSM ≈ 4 rows ≈ 6k cells. Guest cycles for lincomb algebra + keccak(pk) extra. +- At ethrex scale (2857 tx / 60M gas block): ~4.4M ECDAS rows — dominates keccak + by a wide margin. EC RECOVER = top bottleneck confirmed by census. + +## Optimization candidates (validate AFTER gate; keccak cost rules: cells ≫ all, deg ≤ 3 hard, clean constraints > cleverness) + +| # | Candidate | Mechanism | Est. win | Blast radius | +|---|---|---|---|---| +| A1 | **AreBytes pairing** | send [b_2i, b_2i+1] instead of 2× [b, 0] (contract checks both — bitwise.rs:646 ✓) | ECDAS −98 sends ⇒ −147 cells/row ≈ **−13%**; ECSM −96/row | bus repacking only; zero witness/col/constraint change; BITWISE µ recount | +| A2 | Same pairing in ECSM (yG/x2/q0/q1) | same | small (few rows) | same PR as A1 | +| B | Fuse D+A rows (add always follows double; OP·NEXT_OP=0 already forbids AA) | one row does R=2A then R'=R+G; kills per-row header dup + 2 Ecdas tuples per pair | ~−7% ECDAS cells net | new layout, witness change, moderate | +| C | GLV (secp256k1 endomorphism) | k = k1+λk2, 2-scalar Shamir, half-length scalars | ~−40% ECDAS rows | new mod-N decomposition proof in ECSM + β·x relation; crypto-design review | +| D | **lincomb2 precompile** (u1·G+u2·R in one chip pass, return x AND y) | kills the 4-query x-only dance: 1528 → ~450 rows/ecrecover | **~−70% EC cells** | new syscall + guest + executor + witness + ECSM 2-scalar redesign; the "Tier 2 representation change" of this campaign | +| E | 16-bit convolution limbs | 64→32 carries ×3 | unclear (carry range grows past IS_HALF/IS_B20) | needs paper cost model first; likely wash | + +Recommended sequence: gate existing chips → A1+A2 (trivial, gate-provable, +ship like hwsl-inline) → quantify D properly (paper cost model + interface +design), C optionally folded into D (4-scalar Shamir). B only if D stalls. + +## Open questions for the gate / oracle agent +- Executor semantics on invalid ECSM inputs (k=0, k≥N, xG≥p, non-residue): + trap vs unprovable? (oracle agent pinning this) +- Is xR byte-range authority the MEMW write path (like xG/k at store time)? + Verify — matters for the width audit. (xr_sub_p gives < p regardless, but + the carry-chain word recomposition assumes byte-bounded xR cols.) +- ts uniqueness per ecall (splicing argument) — cite executor. +- keccak_rnd also sends AreBytes as [b, 0]? If so A1 generalizes (follow-up PR). diff --git a/thoughts/ec-recover-opt/gate/.gitignore b/thoughts/ec-recover-opt/gate/.gitignore new file mode 100644 index 000000000..9280984ee --- /dev/null +++ b/thoughts/ec-recover-opt/gate/.gitignore @@ -0,0 +1,2 @@ +target/ +__pycache__/ diff --git a/thoughts/ec-recover-opt/gate/CONTRACT-BOUNDARY.md b/thoughts/ec-recover-opt/gate/CONTRACT-BOUNDARY.md new file mode 100644 index 000000000..667e082df --- /dev/null +++ b/thoughts/ec-recover-opt/gate/CONTRACT-BOUNDARY.md @@ -0,0 +1,427 @@ +# The assume-guarantee boundary, re-derived for the joint chain + +`RESULTS-lincomb2.md` §5 states the lincomb2 soundness theorem "under contracts +C1–C7 + A-PRIME (**unchanged from `RESULTS.md`**)" and §5's status line says the +board "rests on the same eight contracts as the original chips plus nothing +else". This pass re-derived each of the eight against the way `ecsm2.rs` / +`ecdas2.rs` / `ec_t0.rs` actually use them. + +**Verdict: no contract is false, but the boundary as written is wrong in three +ways.** Two contracts are used well outside their own wording, one cites an +argument that does not exist in the document it points at, and the joint chain +depends on **three** properties no contract names at all — one of which is +demonstrably load-bearing (a working construction is included). "Plus nothing +else" should be withdrawn. + +Nothing here is a chip bug. Every extension I could evaluate turns out to +*hold*; the problem is that the boundary does not say what is being relied on, +which is the failure mode that lets a later change quietly invalidate the board. + +--- + +## 1. Lead findings + +### 1.1 [NAME IT] C9 — the joint chain's compile-time curve constants are load-bearing and nothing in the proof checks them + +The single-scalar chips have **no** compile-time curve point. `xG` arrives from +memory and is *proven* on-curve by the membership convolutions +(`ecsm.rs` `Relation::X2`/`Relation::Yg`, `:628-638`). The joint chain introduces three constant sources: + +| constant | where | anchored to anything outside the AIR? | +|---|---|---| +| `G` = `GENERATOR_LE` | `ecsm2.rs:612-629` (P1 read), `:793-794` (P1 addend) | **yes** — the P1 read is a MEMW access, so the constant must equal the memory token the guest wrote at `a1` | +| `T₀` = `T0_X_LE`/`T0_Y_LE` | `ecsm2.rs:868-869` (phase-1 seed) | **no** | +| 256 × `−2^(j+1)·T₀` | `ec_t0.rs:131-153`, committed via `ec_t0.rs:190-209` + `prover/src/lib.rs:777-780` | **no** | + +`G` is self-checking: a wrong `GENERATOR_LE` unbalances the Memw bus +(rejection), and executor-side it returns status 7 → software fallback → +correct answer. ✓ VERIFIED by reading the read at `ecsm2.rs:612-629` — the value +elements are `BusValue::constant`, so they are compared against the token. + +`T₀` and the `EC_T0` rows have no such anchor. No guest write, no executor read, +no in-circuit curve check, no membership witness. They enter the proof as an AIR +constant and a preprocessed Merkle root the verifier compiles in. **If the +generator that produced them is wrong, every constraint and every bus still +balances and the chip returns a wrong `Q`.** + +`c9_constants_probe.py` builds the construction, in the style of +`l6_joint_counting.py`: rebuild the full joint chain, re-derive the correction +row from a tampered addend by the group law, then *check* — not assert — all +four ECDAS2 convolution relations mod p on every row, all of idx 11..=27 on +every row, and all five buses (Ecdas telescoping, Addend, JointBit, EcT0 against +the tampered table, the result write). Two plausible generator bugs, both of +which the source itself warns about: + +``` +A. SIGN FLIP table stores +2^len·T₀ (ec_t0.rs:28-41 warns: "reading y_t0_pow + where you meant Y is a silent sign flip that still type-checks") +B. OFF-BY-ONE row for len holds −2^(len+1)·T₀ (the ec_t0.rs:143 index) + + baseline (honest table) 61 rows, all relations + all buses OK, Q correct + A 61 rows, all relations + all buses OK, Q_chain ≠ Q_true, canonical on-curve + B 61 rows, all relations + all buses OK, Q_chain ≠ Q_true, canonical on-curve + + RESULT: 2/2 tampered constant sets produce an accepted, wrong Q. +``` +(`logs/c9_constants.log`.) + +The constants **are** correct today, and well covered: +`t0_is_on_curve_and_pinned` and `t0_derivation_matches` +(`crypto/ecsm/src/tests/lincomb2_tests.rs:316, 464`) re-run the +NUMS SHA-256 search; `every_entry_is_on_curve_and_canonical`, +`trace_rows_recompute_from_t0_by_doubling`, +`table_matches_lincomb2_witness_correction_row` and +`commitment_is_stable_and_matches_the_shipped_static_bytes` +(`prover/src/tests/ec_t0_tests.rs:96, 129, 242, 338`) check the table +independently and pin the shipped commitment. ✓ VERIFIED (test names read from +the file). Consistency between the seed and the table is *structural*, not a +coincidence: `neg_t0_pow2_points()` derives from `witness::t0()`, which is +`T0_X_LE`/`T0_Y_LE` — one source (`crypto/ecsm/src/lincomb2_table.rs:50-52`). + +So this is not a live bug. The finding is that the board's contract list does +not say those tests are part of the *soundness argument*, so nothing tells a +future reader that regenerating the static commitment on a drift failure — which +`ec_t0.rs:185-189` already warns against — would launder a wrong-answer bug into +the verifier's trust anchor. + +### 1.2 [NAME IT] C8 — byte-ness inheritance across a bus, and the layout that makes it valid + +`WIDTH-AUDIT.md` finding #3 is right and is now bigger than it looks. Byte-ness +of the addend limbs is what the whole integer-lifting argument (L1/L2a) rests +on, and for three of the four addends it is *inherited* through tuple equality +rather than checked: + +- `XB`/`YB` are deliberately not `AreBytes`-checked (`ecdas2.rs:543-544`); +- `X_P12`/`Y_P12`, `ACC_X`/`ACC_Y`, `X_Q`/`Y_Q` are not checked in ECSM2 either + — the only `AreBytes` sends there are the membership sub-witness + (`ecsm2.rs:692-705`). + +The inheritance is valid **only** because every point tuple carries one bus +element per byte (`point_coord_busvalues`, `ecsm.rs:272-286` — 32 × +`Packing::Direct`) so tuple equality is per-limb. ✓ VERIFIED. That function now +carries a strong "do not repack" comment (WIDTH-AUDIT finding #3 was actioned), +but it is a *comment*: nothing mechanical stops a future "shrink the Addend bus +with `Word4L`" change, and the gate's contract list does not mention it. Under +`Word4L` a receiver could satisfy the same packed value with a different +decomposition and reachable limb magnitudes run to ~2^63, against a ~2^29 +breaking threshold (`WIDTH-AUDIT.md` §3.1). + +There is a **second, entirely unstated invariant in the same family**: per-bus +tuple-length discipline. A shorter tuple's fingerprint equals that of a longer +tuple on the same bus whose extra *trailing* elements are all zero — the +fingerprint is `bus_id + Σ_l v_l·α^{l+1}` and the shorter tuple simply +contributes no terms past its length. Bus 28 carries two chip families with +different tuple lengths (133 old, 70 new), and what separates them is the +chain-id constant at position 0 (`ecsm.rs:616` `constant(0)` vs +`ecdas2.rs:411` `constant(1)`). ✓ VERIFIED by reading both tuple builders. That +is a real property and it holds — but it is exactly the sort of thing a length +change would break silently. + +⚠ Three source comments justify the related `sel ≠ 0` / `stream ≠ 0` conventions +with a **false mechanism**: `types.rs:351-357` (`BusId::Addend`), +`types.rs:375-386` (`BusId::JointBit`) and `ecsm2.rs:110-119` all say zero +elements are "skipped by the fingerprint" so trailing-zero padding shifts +positions. It does not. ✓ VERIFIED at `lookup.rs:1655` — `alpha_offset += ...` +unconditionally — and `lookup.rs:679`, where the Linear arm returns `1` even +when it skips the multiply for a zero value. Interior zeros consume their α slot +and change nothing. `L6-COUNTING.md` §5.2 already flagged this for +`JOINT_CHAIN_ID`; the same wrong model is in two more places, and +`BusId::JointBit`'s version is doubly wrong — a `stream = 0` tag could not alias +an old-chain `Bit` send anyway, because `Bit` is bus 30 and `JointBit` is bus 33, +and the bus id enters the fingerprint at α⁰. + +### 1.3 [FIX THE CITATION] C5 points at a document that contains no soundness argument + +C5 reads: "*LogUp multiset soundness: exact signed balance per bus (generic +argument, `spec/logup.typ`)*." + +✓ VERIFIED by reading all 146 lines of `spec/logup.typ`: it is a **protocol +description**. Notation, the four-step protocol, and three "running sum +constraint choices" with one `#aside("Justification")` — which justifies the +*bookkeeping* of choice 3, not the multiset argument. There is no theorem, no +Schwartz–Zippel step, no statement of what balance implies. Grepping the whole +of `spec/` and `crypto/stark/src/` for `Schwartz|multiset|log-derivative|Haböck` +returns exactly one file: `spec/ecsm.typ`, the EC chapter, which *cites* "the +`LogUp` multiset argument" as a contract (`:238`, `:679`). The argument is not +written down anywhere in the repo that I could find. ✗ UNCERTAIN whether it +exists outside the repo. + +That matters here because the joint chain uses three forms the original chips +did not, and the lead's question — "does the argument cover them?" — cannot be +answered against the cited text at all. Against the *implementation* and the +standard log-derivative lemma, all three are fine: + +| new form | where | verdict | +|---|---|---| +| `Multiplicity::Linear([{coefficient: 2, column: u_bit(i)}])` | `ecsm2.rs:775-778` | ✓ fine. Multiplicities are arbitrary base-field expressions; `emit_multiplicity` (`lookup.rs:1925-1941`) mirrors `evaluate_with` (`lookup.rs:1369-1399`) arm for arm, including `Linear`, so prover and AIR agree by construction | +| `Multiplicity::Linear` with four terms for the Addend receive | `ecdas2.rs:486-504` | ✓ fine, same reason. `Sum3` could not cover `S_CORR`; the `Linear` fallback is not a weaker object | +| key `Linear([Column{LEN_M1}, Constant(1)])` | `ecsm2.rs:822`, table side `ec_t0.rs:354-360` | ✓ fine. A key is an arbitrary linear form; both sides compute `len` and the 256 unpadded rows publish exactly `[1, 256]`, so balance forces `LEN_M1 ∈ [0, 255]` with no consumer-side range check | +| unconstrained count columns `N1`/`N2`/`N3` | `ecsm2.rs:196-202`, `:795-808` | ✓ fine **with a side condition**, below | + +The count-column claim in the source ("an inflated count leaves an unmatched +send and a 'negative' one is unrepresentable") is right in substance but the +reasoning needs one more step, and that step is a **side condition C5 does not +state**: balance is an equality *in `F_p`*, not over the integers. `N2` is pinned +to `#receives mod p`; a prover setting `N2 = p − 1` would need `p − 1` receives, +impossible only because the trace has far fewer than `p` rows. The same lifting +is what makes the L6 counting argument work — `#{rows at round i with D = 1} = +2·u_bit(i)` is an `F_p` identity, and it forces the *integer* count into `{0, 2}` +only because each row contributes 0 or 1 (IS_BIT) and the total row count is +`≪ p`. Both uses are safe by an enormous margin (Goldilocks `p ≈ 1.8·10^19` vs +`≤ 2^30` rows), but the restated C5 should say so, because it is the hypothesis +that "2 = 1 + 1 is the only decomposition" leans on. + +### 1.4 [RESTATE] C4 is invoked well outside its own text — and the extension holds by a mechanism C4 does not name + +Confirmed, as suspected. C4's text is about `xG`/`k`/`xR` and ends with an +ECSM-specific clause ("*ECSM's YR inherits byte-ness from tuple equality with +ECDAS's byte-checked yR (or YG for k=1)*"). The joint board invokes it for +`P2`, `P12`, `xQ`, `yQ` and the T₀ constants, which fall into three different +classes: + +| value | how byte-ness is really obtained | C4 covers it? | +|---|---|---| +| `X_P2`/`Y_P2` | the MEMW read binds them per byte to a memory token; every writer of a token range-checks its bytes (STORE `store.rs:235-247`, PAGE `page.rs:462-475`, L2G `local_to_global.rs:430`) | in spirit (same class as `xG`) | +| `X_P12`/`Y_P12`, `ACC_X`/`ACC_Y`, `X_Q`/`Y_Q` | inherited from the ECDAS2 row's `AreBytes`-checked `XR`/`YR` (`ecdas2.rs:552-565`) through Ecdas tuple equality — an **interior chip output**, never a memory value | **no** | +| `X_T0N`/`Y_T0N` | the `EC_T0` preprocessed table's committed byte columns | **no** — that is C9 | + +The `P12` chain does discharge, and I re-verified it end to end rather than +inheriting WIDTH-AUDIT's trace: ECSM2's phase-0 drain receive is at multiplicity +`OK` (`ecsm2.rs:849-861`), so it must be matched. The only senders on bus 28 with +`chain_id = 1, phase = 0, round = −1, op = 0` are ECDAS2 sends at multiplicity +`MU` (`ecdas2.rs:616-638`) — the ECSM2 seeds carry `phase ∈ {0,1,2}` with +`round ∈ {0, LEN_M1, 0}` and `LEN_M1 ≠ −1` is forced by the `EcT0` lookup, and +across ECSM2 rows `ts` differs. So the matching row has `MU = 1`, hence its +`AreBytes` sends fire, hence its `XR`/`YR` are bytes, hence `X_P12`/`Y_P12` are. +✓ VERIFIED. `X_Q`/`Y_Q` follow the same path through the phase-2 drain, which +matters twice over: their byte-ness is what makes the `X_Q_SUB_P` word packing +(`ecsm2.rs:1119-1129`) a genuine `< p` proof, and they are the bytes the guest +keccaks. + +C4 should therefore be **split**, not stretched: a global memory-token invariant +(C4) plus the inheritance rule (the new C8). As written it names neither. + +**And two of C4's three clauses are wrong about the mechanism even for the old +chips**, which is why the joint chain had nothing accurate to inherit: + +- "*`k` bytes are range-checked at memory-write time*" — no. `k` never rides the + Memw bus as columns: `k_byte_busvalue` (`ecsm.rs:290-300`) reconstructs each + byte as `Σ 2^j·k_bit`, so byte-ness is in-chip IS_BIT (C3), not C4. Identical + for `u1`/`u2` via `scalar_byte` (`ecsm2.rs:505-514`). Harmless, but it means + C4 has been over-claiming its own scope from the start. +- "*and `xR` bytes at the ECSM MEMW write*" — no. ✓ VERIFIED: **not one of the + three MEMW variants contains an `AreBytes` send** (`grep -c AreBytes` over + `memw.rs`, `memw_aligned.rs`, `memw_register.rs` → `0, 0, 0`). A MEMW write + range-checks nothing; it transports whatever the sender supplies. ECSM's own + `AreBytes` sends cover `X2`, `Q0`, `YG`, `Q1` only (`ecsm.rs:470-478`) — `XR` + is not among them. So `xR` inherits byte-ness by *exactly* the mechanism C4's + next clause grants only to `yR`: tuple equality with the ECDAS drain. + +So C4's only true content, in either chip family, is the memory-token invariant +applied to one value — `xG` then, `P2` now. Everything else it claims belongs to +C3 (in-chip IS_BIT) or C8 (inheritance). + +**On the transcription audit's flag** (`ecsm2.rs:631-649`, `P2` from the 8 MEMW +dword reads): agreed that it is an unstated instance, with one refinement. The +*mechanism* is not new — `operand_dword` (`ecsm2.rs:488-497`) emits 8 +`Packing::Direct` elements per doubleword, byte for byte, exactly as the old +chip's `dword_bytes` (`ecsm.rs:259-262`) does for `xG`. What is new is only the +value. The defect is structural: C4 is written as an **enumeration of values** +rather than as an invariant, so every value the next chip binds is "unstated" by +construction. Restating it as the invariant fixes this instance and all future +ones at once. + +### 1.5 [RESTATE — it is stronger than "assumed"] C7 carries four buses now, and for ECSM2 it is discharged in-chip + +Every joint bus is keyed by `ts`: `Ecdas` (28), `Addend` (29), `EcT0` — no, that +one is keyed by `len` only, correctly, since it is a pure function lookup — +`JointBit` (33). So `ts` really is doing the cross-call separation for three +buses instead of two. + +**But C7 need not be assumed for these chips.** Every ECSM2 row that +participates in anything has `MU = 1` (`OK·(1 − MU) = 0`, idx 2, plus idx +517..=521 killing the raw-column multiplicities on `OK = 0` rows), and every +`MU = 1` row performs a combined read+write of register `x10` at its own `ts` +(`ecsm2.rs:568-582`). Two ECSM2 rows sharing a `ts` would be two accesses to the +same address at the same timestamp; the memory token chain at that address is a +total order with strictly increasing timestamps, enforced by +`old_timestamp[i] < timestamp` (`memw.rs:757-830`, ALU LT) or +`IS_HALF[ts − old_ts − 1]` (`memw_register.rs:286-301`). ✓ VERIFIED. So +`ts`-uniqueness *for lincomb2 ecalls* follows from the memory argument, and C7 +degrades from an assumption to a consequence. + +Independently, C6 alone already forces it: the CPU sends exactly one `Ecall` +tuple `[ts, 0, rv1]` per ecall (`cpu.rs:982-998`) and ECSM2 receives one at +multiplicity `MU` with the syscall constant (`ecsm2.rs:553-562`), so two `MU = 1` +rows at one `ts` mean two receives against one send. + +Two problems with the *evidence* C7 cites: + +- ✓ VERIFIED **`trace_builder.rs:341-347` is the honest builder, not a + constraint.** It is `let timestamp = (i as u64) * 4 + 4;` — it says the prover + *chooses* distinct timestamps, which proves nothing against a malicious + prover. Citing it alongside the in-proof mechanism blurs the two. +- ✓ VERIFIED **`cpu.rs:541-542` has drifted.** Those lines are now a blank line + and a comment about `rv1/rv2/arg2`. The PC-token cadence actually lives at + `cpu.rs:822-892` (the inline-PC `Memory` sender/receiver pair: consume at + `ts − 3`, emit at `ts + 1`, forcing `ts' = ts + 4` along the chain) and + `cpu.rs:560-574` (the padding-row comment). Worth noting that the cadence + comment at `cpu.rs:827` cites `docs/cpu-rework-deviations.md`, **which does not + exist anywhere in the repo** — I searched for it by name. So the C7 evidence + trail has one stale line reference and one dangling document. +- `spec/memory.typ` does contain the load-bearing part — temporal integrity, + "the newly emitted token must have a strictly greater timestamp than the + consumed token" (`:102-110`), plus the design note that same-timestamp accesses + to the same address are impossible (`:57-58`, `:67-75`). ✓ VERIFIED. It does + *not* contain a PC-cadence argument; that is a chip property, not a spec one. + +**On `PHASE` and the chain id: they do real work, `ts` is not doing it alone.** +`ts` separates *calls*; within one call `phase` (constant `0/1/2` in every seed +and drain, relayed unchanged along every ECDAS2 row) is what stops the three +segments merging — notably the phase-1 drain and the phase-2 seed are sent from +the *same* `ACC_X`/`ACC_Y` columns (`ecsm2.rs:877-907`) and would cancel each +other outright if `phase` were not in the tuple. The chain id separates the two +chip families sharing bus 28. ✓ VERIFIED by reading both tuple builders. + +--- + +## 2. The board + +| # | restated for the joint chain | status | evidence | verdict | +|---|---|---|---|---| +| **C1** AreBytes | every element of an `AreBytes[x, y]` send is in `[0,256)`, for **both** slots, over the paired layout | **assumed** (preprocessed table) — and it holds in the stronger usage | table is 2^20 rows indexed `x + 256y + 65536z` with `X`/`Y` columns equal to those bytes (`bitwise.rs:98, 117-152`); receiver keys on `(X, Y)` (`bitwise.rs:783-796`) — every byte pair exists, no non-byte does | ✓ holds. Pairing changed the number of sends, not the per-element guarantee | +| **C2** IsHalfword | sent value ∈ `[0, 2^16)` | **assumed** (same table) | receiver `[X + 256·Y]` (`bitwise.rs:797-810`) over all byte pairs = exactly `[0, 2^16)` | ✓ holds | +| **C3** IS_BIT/booleans | now: ECSM2 `MU`, `OK`, 512 scalar bits, `mem_q1[32]`, 35 overflow carry bits; ECDAS2 `MU`, `OP`, `NB`, `D1`, `D2`, `S1..S3`, `S_CORR`, `PH1`, `PH2` | **discharged** in-chip, list extended | `ecsm2.rs:1148-1153, 1181-1189, 1227-1231, 1243-1247`; `ecdas2.rs:850-870` | ✓ holds; C3 is a note about in-chip constraints, not an external assumption — say so | +| **C4** MEMW byte authority | **global**: every value element of a memory token is in `[0,256)`, maintained by every writer | **assumed** (whole-VM invariant) | STORE `store.rs:235-247`; PAGE `page.rs:462-475`; L2G `local_to_global.rs:430`; MEMW binds per byte via `Packing::Direct` (`memw.rs:567-590`) | ✓ holds for `P2`. **Text does not cover** `P12`/`xQ`/`yQ`/T₀ — see §1.4 | +| **C5** LogUp multiset soundness | balance **in `F_p`** per distinct fingerprint, w.h.p. over the two challenges; integer conclusions need contributing totals `≪ p` | **assumed**, and the **cited argument does not exist in the cited file** | `spec/logup.typ` is protocol-only (§1.3); implementation supports every new form (`lookup.rs:1328-1362, 1369-1399, 1925-1959`) | ✓ the three new forms are within it; ✗ the citation is empty; side condition unstated | +| **C6** Ecall binding | each `MU = 1` ECSM2 row ↔ exactly one executed lincomb2 ecall, both directions | **discharged** by balance | CPU send `cpu.rs:982-998`; ECSM2 receive `ecsm2.rs:553-562`; syscall numbers differ from ECSM (`execution.rs:39, 47`) | ✓ holds, and is now bidirectional (an unmatched CPU send would also reject) | +| **C7** Timestamp uniqueness | distinct lincomb2 ecalls have distinct `ts`; `ts` + `phase` + chain id separate the four keyed buses | **discharged** for ECSM2 (was: assumed) | x10 access `ecsm2.rs:568-582` + temporal integrity `memw.rs:757-830`, `memw_register.rs:286-301`, `spec/memory.typ:102-110`; and C6 independently | ✓ holds, **stronger than stated**; two of its three citations are stale/misleading (§1.5) | +| **A-PRIME** | `p`, `N` prime; `N` odd | **assumed** (sympy-certified) | unchanged | ✓ holds. Still load-bearing: L4a needs `p` prime; L5a (no `y ≡ 0` point) still discharges the doubling side condition and still consumes `N` odd. L5c is no longer used — L5b′ replaced it | +| **C8** *(new)* byte-ness inheritance | a receiver inherits limb range checks from a sender **only** while every point coordinate rides as 32 × `Packing::Direct`, and tuples on one bus never differ by trailing zeros | **assumed**, unstated | `ecsm.rs:272-286`; `lookup.rs:1655, 679`; bus-28 length 133 vs 70 separated by the chain-id constant | ✓ holds today; **must be named** (§1.2) | +| **C9** *(new)* EC constants | `T₀` is the intended on-curve NUMS point, and the 256 `EC_T0` rows are `−2^(j+1)·T₀`, bound by the verifier's compiled-in preprocessed commitment | **assumed**, unstated, **demonstrably load-bearing** | probe: 2/2 tampered tables accepted with a wrong `Q` (`c9_constants_probe.py`, `logs/c9_constants.log`); discharge is test-time only (§1.1) | ✓ holds today; **must be named** | +| **C10** *(new)* caller status discipline | the caller treats **every** non-zero status identically (full software fallback), so the prover's free choice of `STATUS` cannot change the program's output | **discharged** by the caller | `crypto/ethrex-crypto/src/lib.rs:172-178` (`if status != OK { return None }` → `unwrap_or_else(ProjectivePoint::lincomb)`), documented at `:146-162` and `syscalls.rs:41-44` | ✓ holds; worth naming because it is chip-external and a future caller could break it | + +--- + +## 3. Proposed restatements + +Replacements for the contract block at `RESULTS.md:164-181`, to be referenced +(not re-copied) from `RESULTS-lincomb2.md`: + +- **C1 AreBytes** — every element of an `AreBytes[x, y]` send lies in `[0,256)`. + Both slots; single-byte checks pass `y = 0`. Rests on the BITWISE preprocessed + table being committed and containing all `(x, y)` byte pairs + (`bitwise.rs:98, 117-152`, receiver `:783-796`). +- **C2 IsHalfword** — a sent value lies in `[0, 2^16)` (`bitwise.rs:797-810`), + same table. +- **C3 IS_BIT/booleans** — *(not an assumption; a pointer.)* Every column used as + a bus multiplicity or a one-hot selector carries an in-table `x·(1−x)`. + Joint-chain list: ECSM2 `MU`, `OK`, `u1[0..256]`, `u2[0..256]`, `mem_q1[32]`, + the 35 overflow carry bits; ECDAS2 `MU`, `OP`, `NB`, `D1`, `D2`, `S1`, `S2`, + `S3`, `S_CORR`, `PH1`, `PH2`. +- **C4 Memory-token byte authority** — every *value* element carried on the + memory-token bus is in `[0,256)`, because every chip that emits a token + range-checks the bytes it writes (STORE, PAGE, L2G, and each accelerator for + its own output). Consumers therefore inherit byte-ness for anything they bind + to a token per byte. **This covers memory-resident operands only** — for the + joint chain, `X_P2`/`Y_P2`. Interior values (`P12`, `ACC`, `xQ`/`yQ`) are + covered by C8, not by this. +- **C5 LogUp multiset soundness** — for random challenges sampled after the + trace commitment, per-bus balance implies, with probability + `1 − O(max tuple length / |𝔾|)`, that for **each distinct fingerprint** the + signed sum of multiplicities is zero **in `F_p`**, and that two interactions + with equal fingerprints have equal `(bus_id, value-vector)`. Multiplicities and + tuple elements may be arbitrary linear forms over columns and constants; + coefficient-2 multiplicities, four-term sums and constant-offset keys are + covered. *Side condition, used by every counting argument:* an `F_p` balance + lifts to an integer statement only when the total contribution to a single + fingerprint is bounded well below `p` — here by (rows in the table) × (max + per-row multiplicity), i.e. `≤ 2^31 ≪ 2^64`. **The generic argument is not + written down in `spec/logup.typ`, which is a protocol description; this + contract currently has no citable proof in-tree.** +- **C6 Ecall binding** — the CPU sends exactly one `Ecall[ts, 0, syscall]` per + executed ecall, so a chip's `MU`-gated receive at a given syscall constant + corresponds one-to-one with real ecalls of that kind, in both directions. +- **C7 Timestamp uniqueness** — *(now derived, for these chips.)* Distinct + accesses to one address carry distinct timestamps, because the per-address + memory-token chain is totally ordered and every MEMW variant enforces + `old_ts < ts` (`memw.rs:757-830`; `memw_register.rs:286-301`; + `spec/memory.typ:102-110`). Since every live ECSM2 row read-writes `x10` at its + own `ts`, distinct lincomb2 ecalls have distinct `ts`. Separation of the joint + buses is then `ts` (across calls) × `phase` (across the three segments of one + call) × chain id (across the two chip families on bus 28) × `stream`/`sel` + tags. *Do not cite `trace_builder.rs` for this — that is the honest builder.* +- **C8 Bus-carried range inheritance** *(new)* — a receiver may inherit a limb + range check from a sender's checked columns iff the two tuples place those + limbs in the same positions as **individual** bus elements + (`Packing::Direct`, one element per byte — `ecsm.rs:272-286`), and no two + interactions on the same bus differ only by trailing zero elements. Repacking a + point coordinate (`Word4L`) or shortening a tuple to a zero-padded prefix of + another on the same bus invalidates every inheritance and, via `WIDTH-AUDIT` + §2, the integer-lifting argument itself. +- **C9 EC constants and preprocessed tables** *(new)* — the compile-time + constants the chips assert rather than prove are the intended ones: `T₀` + (`witness.rs:490-497`) is the on-curve NUMS point of `T0.md`, and the `EC_T0` + table's 256 rows are `−2^(j+1)·T₀` under a preprocessed commitment the verifier + computes from its own compiled-in constants (`ec_t0.rs:190-274`, + `prover/src/lib.rs:777-780`). `G` is exempt: it is anchored to guest memory by + the P1 MEMW read, so a wrong value can only reject or fall back. +- **C10 Caller status discipline** *(new)* — the calling program treats every + non-zero status word as "the accelerator produced nothing" and re-computes in + software, so a prover's free choice of `STATUS` on an `OK = 0` row costs cycles + and cannot change the program's output. +- **A-PRIME** — `p` and `N` prime (hence `N` odd). Unchanged, and still + load-bearing for the joint chain via L4a (`p`) and L5a (`N` odd). L5c's use is + retired with L5b. + +Two smaller edits worth making while the file is open: + +1. Withdraw "*plus nothing else*" from `RESULTS-lincomb2.md` §5 and replace the + §5 preamble with "under C1–C10 + A-PRIME (C1–C7 + A-PRIME as restated in + `CONTRACT-BOUNDARY.md`; C8–C10 are new to the joint chain)". +2. Fix the three false "zeros are skipped by the fingerprint" justifications + (`types.rs:351-357`, `types.rs:375-386`, `ecsm2.rs:110-119`) — same correction + `L6-COUNTING.md` §5.2 already made for `JOINT_CHAIN_ID`. + +--- + +## 4. What I could not determine + +- **Whether the generic LogUp argument exists anywhere.** I established it is not + in `spec/logup.typ` and not elsewhere in `spec/` or `crypto/stark/src/`. It may + exist in a design note outside the repo. If it does not, C5 is the largest + unproven object the entire EC board rests on, and it is shared with every other + chip. +- **Whether the global C4 invariant actually holds for every token writer.** I + verified STORE, PAGE and L2G range-check their bytes. `commit.rs` contains no + `AreBytes` and `keccak.rs` one; I did not trace whether those chips' written + bytes are byte-bounded by other means (bit decomposition, etc.). It does not + affect the joint chain's *own* operands unless a guest can point `a2` at + accelerator-written memory, which for ecrecover it does not — but the restated + C4 is a whole-VM claim and I have only spot-checked it. +- **Completeness of the honest carry windows for the varying addend.** + `WIDTH-AUDIT.md` §4 is explicit that its table is a measurement over 6,346 + rows, not a proof. Unchanged by this pass; completeness-only. +- **The `PH*`/`S*` modelling gap** already recorded in `RESULTS-lincomb2.md` §7: + those are derived by `phase_bits`/`selector_bits` rather than being witness + fields, and my probe reproduces that mapping from the same source, so it shares + the gap. +- **Whether `LEN_M1` needs `ROUND`-style byte-ness on an `OK = 0` row.** It does + not, as far as I traced — every consumer of `LEN_M1` (`EcT0` send, phase-1 seed + round) is `OK`-gated — but I did not enumerate the ECSM2 column set + exhaustively for other free-on-error-row columns. That enumeration belongs to + the transcription audit, not here. +- **Cross-epoch behaviour.** All of the above assumes one proof. Whether `ts` + uniqueness survives continuations (L2G/GlobalMemory boundaries) for + accelerator ecalls is untouched by this pass. + +--- + +## 5. Reproduction + +```sh +cd /Users/maurofab/workspace/lambda_vm +python3 thoughts/ec-recover-opt/gate/c9_constants_probe.py # 2/2 forgeries +``` +Pure stdlib (no venv, no z3); reference machinery is `oracle/ec_ref.py` + +`oracle/lincomb2_ref.py`. Log: `logs/c9_constants.log`. diff --git a/thoughts/ec-recover-opt/gate/RESULTS-lincomb2.md b/thoughts/ec-recover-opt/gate/RESULTS-lincomb2.md new file mode 100644 index 000000000..a27fd2b96 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/RESULTS-lincomb2.md @@ -0,0 +1,311 @@ +# lincomb2 z3 gate (phase E) — lemma board & soundness theorem + +Verification of the JOINT-CHAIN chips `prover/src/tables/ecsm2.rs` (1,155 cols) +and `ecdas2.rs` (658 cols, 288 constraints). Companion board to +[`RESULTS.md`](RESULTS.md), which covers the original single-scalar chips. + +Model transcribed by READING the chips; independent reference = +`../oracle/lincomb2_ref.py` + `jacobian_ref.py`, themselves anchored on four +lineages (see `../oracle/README.md`). The transcription itself was then audited +in the model ⊆ chip direction — the one the positive anchor structurally cannot +see — in [`TRANSCRIPTION-AUDIT.md`](TRANSCRIPTION-AUDIT.md). + +**Faithfulness anchor**: before any UNSAT was trusted, the transcribed model was +evaluated on REAL prover witnesses (`ecsm::lincomb2_witness` + `dinv_witness` +via the oracle harness): 265 cases → **5,960 ECDAS2 rows, 3,317,087 checks**, +every one of the 288 constraint values ≡ 0 mod p_g, every carry inside its +IsHalfword window, every quotient inside 33 bytes, every schedule relation +satisfied, and the prover's own `D_INV`/`Q3`/`C3` columns equal to an +independent group-law derivation. (`positive_real_witness2.py`.) + +**Layout pins** (settled, verified in the tree): `cols::D_INV = 529`, +`NUM_COLUMNS = 658`, `debug_assert_eq!(idx, 288)` = 28 + 4×65, four-entry +relation loop ending `(Relation::Dinv, cols::C3)`, and the `NB..MU = 519..528` +block preserved by appending rather than inserting the new columns. + +> **This gate found two real forgeries.** Both were open in the chips when phase +> E began and are now closed. The gate is written so that it keeps telling the +> truth as the chips change: `gate2_common.chip_state()` **parses** the chip +> source at run time — the emitted constraint expressions and the bus +> multiplicity expressions, never a comment — and a control whose defence is +> missing is reported as **LIVE HOLE** rather than scored as a passing ablation. +> Every parser fails closed: an unrecognised shape reports the defence ABSENT. +> +> That sentence was **false when first written** (`chip_state` matched comments +> and token presence — `TRANSCRIPTION-AUDIT.md` F2), which is why +> `audit_transcription.py` now tampers each defence and requires the detector to +> fire. A detector nobody has watched fail is not a detector. + +## Board + +| Lemma | Statement | Verdict | Notes | +|---|---|---|---| +| PORT | ECDAS2's `Lambda`/`Xr`/`Yr` relation arms, the `s_i` **operand bindings**, `conv_carry` and the shared helpers are ECDAS's, modulo the documented `XG/YG → XB/YB` rename | PROVED (mechanical text comparison) | so every lemma quantified over those three relations transfers verbatim. The prologue and `conv_carry` were added after `TRANSCRIPTION-AUDIT.md` F3: without them a chip whose relations read the **wrong columns** compared identical | +| PORT-M | ECSM2's `X2`/`Yg` membership relations are ECSM's, modulo the column rename and the `µ → OK` gate swap | PROVED (mechanical) | new. The soundness theorem's "`P2` is on the curve" clause rests on this port and nothing checked it. `OK` is IS_BIT with `OK·(1−MU) = 0`, so `OK = 1` rows are a subset of `MU = 1` rows and every ECSM lemma applies verbatim | +| L1 | carry recurrence + `c₆₃ = 0` ⇒ `Σ256^i·S_i = 0` over ℤ | PORTED | unchanged relations ⇒ unchanged proof | +| L2a | per-limb `\|256c − c⁻ − S\|` < p_g with a **varying, non-canonical** addend | PROVED (exact intervals + z3 ×72 + 36k corners) | worst case 2^24.4 vs 2^64 — 2^39 headroom. `../lincomb2/WIDTH-AUDIT.md` | +| L2b | honest carries fit the unchanged `CARRY_OFFSET_*` windows | PROVED (6,346 real rows, differentially checked vs the prover) | λ `[-4303, 6728]`, xR `[-112, 8308]`, yR `[-465, 5914]`, D_INV `[-581, 6041]` | +| L2c | word-carry lift + strict-inequality chains | PORTED | same overflow-witness machinery | +| L3a/L3b | convolutions capture the intended polynomial; chord/tangent stays on curve | PORTED | | +| L4a/b/c | λ, xR, yR pinned mod p given the side condition | PORTED | the side condition is now discharged by L5b′ | +| L5a | no `y ≡ 0` point on secp256k1 | PORTED | discharges the doubling side condition | +| **L5b′** | **REPLACES L5b.** `D_INV·(xB − xA) ≡ 1 (mod p)` is imposed on exactly the addend-consuming rows and is unsatisfiable exactly when `xB ≡ xA (mod p)` | PROVED (z3, 5 sub-lemmas) | **unconditional** — no dlog assumption. §2 below | +| **L6** | joint-schedule counting: the chain is exactly the honest schedule | PROVED **given the idx 22..=27 gate**, which this gate's break forced | §3 below; `../lincomb2/L6-COUNTING.md` | +| L6.5 | exact-MSB pinning | **DROPPED** | blinding makes any `len ∈ [max_msb+1, 256]` yield the same Q; `len ≤ 256` is structural via the EC_T0 table | +| L7 | drained Q equals fully-enumerated ground truth | PROVED (265 comparisons, 0 mismatches) | 256 small-joint-scalar cases with ground truth by repeated group addition | +| L8 | negative / sensitivity controls | PASSED (**7 forgeries**, 2 redundancies, 0 live holes) | §4. One control (N4b) was mis-aimed and has been re-pointed — read §4 before quoting the count | +| AUDIT | the model asserts nothing the chips do not enforce | PROVED for the schedule block (2^11 brute force vs an independent second transcription, symmetric difference empty **both ways**); 4 unchecked premises found and closed | `TRANSCRIPTION-AUDIT.md`, regression suite `audit_transcription.py` (22/22) | + +## 1. What replaced the NUMS assumption + +DESIGN §4 proposed closing the incomplete-addition edge with NUMS accumulator +blinding, converting one lemma from unconditional to a named dlog assumption. +**That reduction does not hold** — the prover chooses `P2`, so setting +`P2 = μ·T₀` cancels `T₀`'s coefficient out of the collision equation and no +discrete log is needed (`../lincomb2/FINDING-nums-blinding.log`, 5/5 +constructions, corroborated by the Python reference, the Rust witness and an +independent Jacobian path). + +The chip instead carries `D_INV·(xB − xA) ≡ 1 (mod p)` as a fourth convolution +relation. **The gate is therefore unconditional again: lincomb2 rests on no +cryptographic assumption that the original chips did not.** The blind is kept +only for the `len` simplification (L6.5), which is a convenience, not a soundness +property. + +## 2. L5b′ — the non-degeneracy relation + +`l1_l5_port2.py` §3, all PROVED: + +| | statement | verdict | +|---|---|---| +| a1 | `OP = ΣS` on every live row, so the chip's `ΣS` gate coincides with `OP` | z3 UNSAT | +| a2 | all five addend-consuming row types (AddP1/P2/P12, Precompute, **Correction**) always consume an addend; doublings never do | z3 UNSAT ×5 + SAT | +| b1 | unsatisfiable whenever `xB ≡ xA (mod p)` — including byte-different encodings that agree mod p | z3 UNSAT (`p·(d·k − m) = 1`) | +| b2 | satisfiable whenever `xB ≢ xA (mod p)` — costs no completeness | 204 residues incl. 1, 2, p−1, p−2 | +| c | the **gated-off branch pins `q3 = µ·3p`** — a doubling is not a hole | z3 UNSAT | +| d | discharges L4a's side condition unconditionally | — | + +Sub-lemma (c) is worth its own line because "the check is gated off here" is +exactly the shape a real hole takes. With `g = 0` only `rq` survives, and L1's +telescoping turns that into `p·(µ·R − q3) = 0` — so `q3` is **pinned** to `3p` on +a live doubling and `0` on a padding row, not left free. Confirmed on real +witnesses as well: every doubling row's `Q3` column is exactly `3p` with zero +carries. + +The chip gates by `ΣS` rather than `OP`. That is strictly better than the `OP` +gate the audit proposed: it ties the check to the very expression that counts the +Addend receive, so it cannot drift away from the rows that consume one. a1 shows +the two coincide. + +**"Cannot drift" is now enforced, not asserted.** `TRANSCRIPTION-AUDIT.md` F1 +found that (a1)/(a2) quantify over a *Python* expression and nothing read the +chip's actual gate: deleting the `S_CORR` term left the correction row with no +non-degeneracy check — a working forgery, reachable by one point subtraction +(`u1 = u2 = 1`, `P2 = −2^(len+1)·T₀ − G` makes `xA = xB` **and** `yA = yB` there, +so λ is free) — while every verdict on this board stayed green. +`gate2_common.dinv_gate_state()` now parses the `Relation::Dinv` arm, requires +the gate to be literally a sum of plain columns, and requires that column set to +**equal** the `Addend` receive's `Multiplicity::Linear` terms (each with +coefficient 1). Tamper and untampered results in `audit_transcription.py` §E. + +## 3. L6 — the joint-schedule counting argument + +Full derivation in `../lincomb2/L6-COUNTING.md`. Established, in order: + +1. **Phase separation** — `PHASE = PH1 + 2·PH2` with `PH1·PH2 = 0`; carried + unchanged along every row, so it is a path invariant pinned by the seeds. +2. **One segment per phase** — all six ECSM2 chain interactions carry + multiplicity `OK`, which is `IS_BIT`. +3. **No cycles; paths end only at drains** — `round` never increases, a `Δ = 0` + step forces an add next which decrements, and the `−1` drain round is not a + byte so no row can receive it. +4. **Phases 0 and 2 are exactly one row each**, with their selectors pinned by + idx 20 / idx 21. +5. **The main chain is one doubling per round plus an add iff a digit is set** + (idx 13). +6. **Digit consumption is exact** — balance gives + `#{rows at round i with D = 1} = 2·u_bit(i)`, each row contributes 0 or 1, so + both the doubling and its add must exist and agree. +7. **The addend matches the digits** — idx 14/17/18/19 force + `(1,0) ⇒ S1`, `(0,1) ⇒ S2`, `(1,1) ⇒ S3`, and make `(0,0)` with `OP = 1` + unsatisfiable. + +`len ≥ max_msb + 1` follows from balance (a set bit above `LEN_M1` has a 2× +receive with no possible sender); `len ≤ 256` is structural. + +**The 2× JointBit multiplicity is load-bearing**, with a concrete 1× +counterexample: at a round where both digits are set, a 1× prover splits them +across the two rows and the add selects **P2 where the schedule calls for P12**. +z3 SAT at 1×, UNSAT at 2×. + +**Bus-28 separator — holds, but not for the reason stated in the source.** +`alpha_offset` advances by `num_bus_elements()` unconditionally +(`lookup.rs:1651-1663`), so zeros never shift positions and there is no +re-alignment risk; the `if result != zero` skip at `:679` is a multiply-avoidance +that still consumes its α slot. What separates the two chains is that tuple +position 1 is constant `0` (old) vs `1` (new), so the difference of the two +fingerprint polynomials has a non-zero α¹ coefficient. Trailing-zero aliasing of +a shorter tuple is real in general — that is what the `sel ≠ 0` note on the +Addend bus guards — but is not the mechanism here. No need for a fresh bus id; +the comment is worth rewording. + +## 4. L8 battery + +`l8_negative2.py`. Every control is first shown BLOCKED on the untampered chip, +then re-run ablated. Forgeries are constructive (fixed numerals; z3 only checks). + +| Control | Verdict | Meaning | +|---|---|---| +| **N1** drop `(1−MU)·D1/D2` | **SAT — FORGES** | padding rows send live JointBit digits ⇒ a set scalar bit is consumed with **no add on the chain**. **Was a live hole**; closed by idx 22..=27 | +| **N2** drop `D_INV` | **SAT — FORGES** | degenerate add ⇒ λ unconstrained. **Was a live hole**; closed by the fourth relation | +| **N3** drop `xQ`/`yQ < p` | SAT — FORGES | a `+p`-shifted output coordinate is the same field element but a different byte string ⇒ the guest keccaks a different address | +| **N4** drop idx 18/19 | SAT — FORGES | an add consumes an addend its digits do not select (P2 with digits `(1,0)`) | +| **N4b** drop `OP = ΣS`, **live** `PH1 = 0` rows (precompute, correction) | SAT — FORGES | an `OP = 0` doubling that still consumes its addend, where idx 17/18/19 are vacuous. **Re-pointed** — see below | +| **N4c** drop `OP = ΣS`, live main-chain doubling | UNSAT — REDUNDANT | idx 17/18/19 already force every selector to 0 when `PH1 = 1, OP = 0`. Keep idx 14 — N4b is what it covers | +| **N5** drop `MU·(STATUS·S_INV − (1−OK))` | SAT — FORGES | `status = 0` with `OK = 0` ⇒ the guest consumes an unproven result | +| **N6** drop the `EcT0` lookup | SAT — FORGES | the correction addend becomes free ⇒ the chain lands on any chosen Q (`W = target − acc`) | +| **N7** drop `yP2 < p` | **UNSAT — REDUNDANT (expected)** | see below | + +**N7 is the expected result, not a gate bug** (IMPL-PLAN §11 risk 7). Three +independent reasons, all recorded rather than papered over: + +1. the bytes are MEMW-bound to what the guest wrote (contract C4), and the guest + derives `y` by field arithmetic, so `y < p` already holds; +2. the only other 32-byte encoding congruent mod p is `y + p`, which needs + `y < 2^256 − p = 2^32 + 977` — and denotes the **same point**; +3. a `< p` test cannot separate a point from its negation anyway: both `y` and + `p − y` are below `p`. Parity is the guest's authority, backed by MEMW. + +Keep the column as defence in depth — it lets the chip's argument stand on its +own constraints rather than on guest-code correctness — but it closes no forgery, +and DESIGN §3's parity-flip justification for it is wrong. + +### N4b was mis-aimed, and the count moved twice + +`TRANSCRIPTION-AUDIT.md` F4. N4b used to aim at a `MU = 0` padding row **and +build it with `padding_gate=False`**, i.e. against a chip without idx 22..=27. +Its `SAT — FORGES` therefore came from the model, not the chip: on the real +constraint set idx 24..=27 zero every selector on a padding row regardless of +idx 14, and the query is UNSAT. So the board's non-vacuity was really **6** +genuine forgeries plus one artefact, not 7. + +Re-pointed at the two **live** `PH1 = 0` phases — where idx 17/18/19 are vacuous +and idx 20/21 still force `S2`/`S_CORR = 1` — it is a real forgery again, and +exhibits its witness rows: + +``` +precompute (MU=1, PH1=PH2=0) untampered unsat ablated sat + forged row: MU=1 OP=0 NB=0 D1=0 D2=0 S1=0 S2=1 S3=0 SC=0 PH1=0 PH2=0 +correction (MU=1, PH2=1) untampered unsat ablated sat + forged row: MU=1 OP=0 NB=0 D1=0 D2=0 S1=0 S2=0 S3=0 SC=1 PH1=0 PH2=1 +``` + +**So the count is back to 7 — for a different reason than this board previously +claimed.** *Keep idx 14* survives unchanged; only its justification was wrong. +The root cause was `Ecdas2Row(padding_gate=…)` defaulting to `False`, a model +strictly weaker than the chip. It now defaults to `True` and ablations opt out +explicitly. + +**Non-vacuity: 7 genuine forgeries.** Two of them (N1, N2) were live holes in the +chip, which is the strongest possible evidence that this gate can see real bugs. + +## 5. Soundness theorem + +Under contracts C1–C7 + A-PRIME (unchanged from `RESULTS.md`), any accepted +trace satisfies: for every ECSM2 row with `OK = 1` at ecall timestamp `ts`, +inputs `P1 = G` (constant), `P2`, `u1`, `u2` bound by the MEMW reads, and output +`xQ‖yQ` bound by the MEMW writes: + +> `P2` is on the curve; `0 < u1, u2 < N`; and `(xQ, yQ)` is the canonical affine +> representation of `Q = u1·G + u2·P2`, or the row reports `status ≠ 0` and +> proves nothing (whereupon the guest's software fallback runs, which is sound +> because guest code is proven execution). + +Chain of proof: field constraints →(L2a/L2c) integer identities →(L1, L3a) value +relations →(L4, sides by L5a/**L5b′**) per-step group law mod p, on-curve +preserved (L3b) →(L6) the whole chain is the honest joint schedule with each +digit consumed exactly once and the selected addend →(L7) the drain equals +fully-enumerated ground truth on concrete instances. + +**Status: green, and unconditional.** No lemma is OPEN. The board rests on the +same eight contracts as the original chips plus nothing else — in particular the +NUMS dlog assumption proposed by DESIGN §4 is **not** required and is **not** +sufficient; it should not be signed off. + +## 6. Reproduction + +```sh +cd thoughts/ec-recover-opt/gate +/bin/python positive_real_witness2.py # anchor — run FIRST (3.3M checks) +/bin/python l1_l5_port2.py # port arguments, L2b, L5b′ +/bin/python l6_joint_counting.py # L6 + the padding-row break +/bin/python l8_negative2.py # the control battery +/bin/python audit_transcription.py # model ⊆ chip + detector regressions +``` + +Current verdicts: `l1_l5_port2` 10/10 PROVED, `l6_joint_counting` all PASS / +CONFIRMED / DEMONSTRATED, `l8_negative2` 7 forgeries + 2 redundancies + **0 live +holes** + 0 broken controls, `audit_transcription` 22/22. + +venv: `python3 -m venv venv && ./venv/bin/pip install ecdsa z3-solver sympy`. +The harness must be built: `(cd ../oracle/repo-harness && cargo build --release)`. +Logs in `logs/`. + +## 7. Caveats, honestly + +- **Column indices are settled** (pins listed at the top). They moved once — + `D_INV` landed *while this gate was being written*, taking ECDAS2 from 529 → + 658 columns and 217 → 288 constraints mid-run — which `chip_state()` caught. + The gate is written against constraint identities and bus multiplicities and + re-reads the source at run time, so it survives further movement; indices + appear only in prose. +- **The positive anchor evaluates CONSTRAINT VALUES only — never a multiplicity + and never a gating expression.** Every honest row has `MU = 1`, so idx 22..=27 + and idx 20's `MU` factor are vacuous in all 3.3M checks *by construction*. The + volume is real, but it is volume in one dimension: the ECDAS2 JointBit bug (an + ungated `Multiplicity::Column(D1)`) would have passed the anchor unchanged, and + so would a narrowed `D_INV` gate. **No amount of honest-witness evaluation can + catch a gating error, and none of the 3.3M checks is evidence about one.** + Those two classes are covered by `gate2_common.chip_state()`'s parsed + invariants and by the L8 controls instead — see `TRANSCRIPTION-AUDIT.md` + F1/F2, and `audit_transcription.py` §D/§E, which tamper each defence and + require the detector to fire. + +- ~~**`PH*`/`S*` are a modelled step**~~ — **closed.** They are still not fields + of `Lincomb2Witness`, and `positive_real_witness2.py` still reproduces the + chip's `JointSel → (PH1, PH2)` / `(S1, S2, S3, S_CORR)` derivation by hand — + but `check_sel_maps()` now compares that hand copy against + `Ecdas2Operation::phase_bits` / `selector_bits` parsed from the chip, arm for + arm, plus the `JointSel` variant list from `crypto/ecsm/src/witness.rs`. A + changed *or added* arm fails the anchor instead of silently re-deriving a + different chip (`audit_transcription.py` §F). +- **L2b is a measurement plus a structural invariance argument**, not a + closed-form worst-case bound. Completeness-only: a miss costs an unprovable + honest witness, never a forgery. See `WIDTH-AUDIT.md` §4. +- **The standing residual risk is hand transcription**, mitigated (not + eliminated) by the anchor *and*, since `TRANSCRIPTION-AUDIT.md`, by an explicit + model ⊆ chip audit: the schedule block was brute-forced over all 2^11 boolean + assignments against an independently written second transcription, with the + symmetric difference empty in **both** directions. That covers idx 0..=27. It + does **not** cover the convolution blocks, which rest on the (now broader) + PORT comparison plus the anchor. The durable fix is still the one the keccak + note calls for: generate the SMT from the constraint IR + (`air.constraint_program()`). + +- **The gate's own detectors are now regression-tested.** `chip_state()` used to + match comments and token presence; deleting a defence while keeping its + comment reported the defence present. Everything is parsed from the emitted + expression, fails closed on an unrecognised shape, and + `audit_transcription.py` re-runs each tamper and requires detection (22/22). + Two structural invariants are enforced in both directions: gated columns == + raw bus multiplicities, and the `D_INV` gate == the `Addend` receive terms. + +- **Still unverified from inside this gate**, unchanged: contracts C1–C7 and + A-PRIME (only the *sending* side of each bus is read here — not `bitwise.rs`'s + receivers, MEMW's byte authority, the CPU↔Ecall binding, timestamp uniqueness, + or the generic LogUp balance argument); and the completeness-side mirroring of + `collect_bitwise_from_ecdas2` / `collect_bitwise_from_ecsm2`, whose failure + mode is an unprovable honest witness rather than a forgery. Note also that + C4 as written in `RESULTS.md` names `xG`/`k`/`xR`; its ECSM2 instance is + `X_P2`/`Y_P2` byte-ness via the eight MEMW dword reads at `ecsm2.rs:631-649`, + which is a different (and unstated) instance of the same contract. diff --git a/thoughts/ec-recover-opt/gate/RESULTS.md b/thoughts/ec-recover-opt/gate/RESULTS.md new file mode 100644 index 000000000..0607d1229 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/RESULTS.md @@ -0,0 +1,228 @@ +# ECSM/ECDAS z3 gate — lemma board & soundness theorem + +> **PHASE E (lincomb2 / ECSM2 / ECDAS2) is a SEPARATE BOARD — see +> [`RESULTS-lincomb2.md`](RESULTS-lincomb2.md).** The board below verifies the +> ORIGINAL single-scalar chips (`ecsm.rs` / `ecdas.rs`), which remain in the tree +> and are unaffected by the joint-chain work. Phase E found and closed two real +> forgeries in the new chips; neither touches these lemmas. + +> **Post-gate rewrite (feat/ec-arebytes-pairing):** the single-byte AreBytes +> sends were paired ([b,0]×2 → [b_even,b_odd]; ECDAS 388→290, ECSM 579→515 +> interactions/row). The theorem below is unaffected — every lemma consumes the +> byte contract per COLUMN, not per send, and contract C1 checks both tuple +> elements. Argument + layout: `pairing-equivalence.md`. + +Reverse-order verification of the EXISTING chips (keccak_rnd playbook), 2026-07-24. +Model transcribed from `prover/src/tables/ecsm.rs` / `ecdas.rs` (citations inline in +the scripts); independent reference = `../oracle/ec_ref.py` (3-lineage-anchored). + +**Faithfulness anchor**: before any UNSAT was trusted, the transcribed model was +evaluated on REAL prover witnesses (`crypto/ecsm::compute_witness` via the extended +oracle harness): 12 scalars incl. k=1, k=N−1, 2^255, 2^255−1 → 872,242 checks, +2,190 ECDAS rows, all 413/200 constraint values ≡ 0 mod p_g, all carries inside +their claimed IsHalfword windows, all chaining/bit-balance relations hold. +(`positive_real_witness.py`, run log below.) + +## Board + +| Lemma | Statement | Verdict | Notes | +|---|---|---|---| +| L1 ×5 | carry recurrence + c₆₃=0 ⇒ Σ256^i·S_i = 0 over ℤ | PROVED (z3 UNSAT ×5) | telescoping, per relation | +| L2a ×5 | every ConvCarry LHS integer value < p_g under contracts | PROVED (exact intervals) | max ≈ 2^25 ≪ 2^64; bounds exact for multilinear-plus-signed-squares forms; 9,000-sample corner cross-check | +| L2b ×5 | honest carries fit the IsHalfword windows (completeness) | PROVED | minimal offsets computed: x2 7949, yG 8371, λ 24605, xR 256, yR 8289 vs repo 8160/16319/32636/8161/16320 — all sound with slack | +| L2b-ctl | offset-below-necessity fails the audit; r=2p ⇒ negative honest quotient, r=3p ⇒ q_min=5 ≥ 0 | PROVED | the audit binds; r=3p is necessary AND sufficient | +| L2b-q | quotient headroom: ECDAS q ≲ 2^259 < 2^264, ECSM q1 ≲ 2^257 | PROVED | honest completeness | +| L2c | word-carry lift + strict-inequality chains (xG xG is a canonical field element (< p) and a valid secp256k1 x-coordinate; +> 0 < k < N; and xR is the canonical x-coordinate of k·P where P is either lift +> (xG, ±y) — both give the same xR. Exactly matching the oracle/executor +> semantics (`ec_ref.x_only_mul`), including the k=1 echo. + +Chain of proof: field constraints →(L2a/L2c) integer identities →(L1, L3a) value +relations →(L4, sides by L5) per-step group law mod p, on-curve preserved (L3b) +→(L6) whole-chain = double-and-add per the bits of k, adds exactly at set bits, +len_k = MSB →(L7) drain equals oracle on concrete instances (soundness spot-proof +battery over 72 chains ensuring no compositional gap). + +**Status: the board is fully green.** All L1–L7 lemmas PROVED (or +PROVED-with-explicitly-discharged side conditions); A-PRIME certified; L8 +establishes non-vacuity (4 forgeries/catches) with the baseline UNSAT and every +load-bearing check confirmed. No lemma is OPEN. Transcription is anchored by the +872k-check real-witness evaluation. Remaining trust surface = the eight contracts +C1–C7 + A-PRIME below (the assume-guarantee boundary), plus the standing +residual-risk of hand transcription mitigated (not eliminated) by the +real-witness anchor — the durable fix is generating the SMT from the constraint +IR (`air.constraint_program()`), same as the keccak note. + +**Completeness** (no honest rejection): L2b windows + L2b-q headroom + the +real-witness runs (all contracts satisfied by construction-faithful witnesses). + +## L6 — chain soundness argument (the multiset/induction core) + +Setting: LogUp gives exact signed multiset balance per bus (contract C5). All +tuple components are field elements; byte-level equality of tuples ⇒ integer +equality of composed values. + +1. **Degrees.** Every µ=1 ECDAS row receives exactly one Ecdas tuple and sends + exactly one (both interactions have multiplicity µ; ecdas.rs:159-172, 224-247). + Every µ=0 (padding) row participates in neither, and its Bit send is also + dead: NEXT_OP·(1−µ)=0 (ecdas.rs:429-433) forces next_op=0. Every ECSM µ=1 + row sends one seed and receives one drain (ecsm.rs:542-576). +2. **Graph.** Balance ⇒ the µ=1 ECDAS rows form a 1-regular flow graph whose + sources are ECSM seeds and sinks are ECSM drains, i.e. disjoint paths plus + possibly cycles. Along any edge the tuple's (ts, xG, yG) components are + copied unchanged (the ECDAS sender reuses the receiver's TS/XG/YG columns — + same column indices in both tuples), so they are path invariants. +3. **No cycles.** Along consecutive rows, round' = round − 1 + next_op with + op' = next_op; a row with op = 1 (add) satisfies... any two consecutive + steps decrease round by ≥ 1 in total: a next_op=1 hop keeps round equal but + forces the successor to be an add row, whose own Bit-send multiplicity + pattern (see 5) prevents a second same-round add hop [z3-checked in N4's + model: no schedule satisfying balance revisits a round]. A cycle would need + total round change 0 with at least one strict decrease — impossible since + round never increases. Also no row can receive round = −1 (ROUND is + byte-checked, ecdas.rs:184; −1 mod p_g is not a byte), so paths terminate + only at drains. +4. **Per-ecall uniqueness.** Distinct ecalls have distinct ts (C7). A path's ts + invariant therefore matches it to exactly one ECSM row: its seed and drain + belong to the same row (an ECSM row's drain receiver uses its own ts + columns). Two ECSM rows cannot share a path. (If two ecalls had equal ts, + xG, yG AND equal k they'd be fully interchangeable — same outputs — hence + harmless; C7 rules it out anyway.) +5. **Bit counting ⇒ schedule.** For position i: receivers total k_bit(i) ∈ + {0,1} (IS_BIT, ecsm.rs:837-843; multiplicity column k_bit(i), ecsm.rs:529-534). + Senders: the ECSM MSB send at len_k (mult µ, ecsm.rs:536-540) plus one send + per ECDAS row with next_op=1 at its round (ecdas.rs:217-221). Balance ⇒ + (a) len_k names a set bit; (b) every set bit above len_k or not consumed by + an add ⇒ imbalance ⇒ len_k = MSB(k) and adds occur EXACTLY at set bits below + the MSB, each once (round strictly decreases between add opportunities); + (c) zero bits get no add. With seed round = len_k − 1 and op₀ = 0 (constants + in the seed tuple, ecsm.rs:541-561), the path's (round, op) sequence is + exactly the reference double-and-add schedule of k. K=1: len_k = 0, seed + round = −1: no ECDAS row can receive it (3.), so balance forces drain = seed + ⇒ xR = xG, yR = yG — the echo, = oracle. KBitsZeroOnPadding (ecsm.rs:845-853) + plus IS_BIT keep padding rows out of the Bit bus (see N7: even without it, + padding could only add unmatched receives ⇒ rejection-only). +6. **Induction along the path.** Invariant: entering step t, the accumulator + values (xA, yA) ≡ (mod p) the affine coordinates of c_t·P, on curve, with + c_t = the binary prefix of k consumed so far; 2 ≤ c_t ≤ k < N after the + first double. Base: seed = (xG, yG), on curve by the ECSM relations (L3a on + x2/yG relations + L2), canonical x (XG_SUB_P, L2c), c = 1. Step: L4 pins the + row's outputs to the chord/tangent result mod p — side conditions discharged + by L5a (double: yA ≢ 0 for on-curve A) and L5b+L5c (add: A ≠ ±G ⇒ xA ≢ xG); + L3b keeps the invariant on-curve; the multiplier updates ×2 / +1 per the + schedule (5.). Drain: c_final = k, so (xR, yR) ≡ k·P; XR_SUB_P forces xR + canonical ⇒ xR = x(k·P) exactly. yG's sign is never fixed — both lifts give + the same x (x(k·P) = x(k·(−P))), matching the x-only oracle contract. + +## Contracts (assume-guarantee boundary) + +- **C1 AreBytes**: each element of an `AreBytes[x,y]` send is in [0,256) + (bitwise.rs:646, receiver :783-796; precomputed table). +- **C2 IsHalfword**: sent value in [0, 2^16) (bitwise.rs:797-810). +- **C3 IS_BIT/booleans**: in-table x·(1−x) constraints (µ, k bits, op, next_op, + q1[32], overflow carry bits). +- **C4 MEMW byte authority**: xG and k bytes are range-checked at memory-write + time (store.rs path; ecsm.rs:460 comment), and xR bytes at the ECSM MEMW + write; ECSM's YR inherits byte-ness from tuple equality with ECDAS's + byte-checked yR (or YG for k=1). +- **C5 LogUp multiset soundness**: exact signed balance per bus (generic + argument, spec/logup.typ). +- **C6 Ecall binding**: each ECSM row's ts corresponds to a real executed ECSM + ecall (CPU Ecall bus sender ↔ receiver, ecsm.rs:307-316). +- **C7 Timestamp uniqueness**: distinct CPU rows (hence ecalls) have distinct + timestamps — enforced by the PC-token chain through the MEMW consistency + argument (trace_builder.rs:341-347 builder; cpu.rs:541-542 + spec/memory.typ + in-proof cadence). +- **A-PRIME**: p and N are prime (sympy-certified; SEC2 published constants). + +## Findings + +1. **[redundancy, keep-as-insurance] OP·NEXT_OP = 0** (ecdas.rs:424-427): Bit-bus + balance + IS_BIT(k_bit) already exclude add-after-add schedules (N4: tampered + model UNSAT with balance kept, SAT once balance is also dropped). Keep — it + is what makes the round-monotonicity argument local. +2. **[redundancy, keep-as-insurance] IS_BIT(q1[32])** (ecsm.rs:876-879): the yG + relation pins yG² ≡ xG³+7 mod p for ANY q1 < 2^264 (N5 UNSAT); Goldilocks + headroom unaffected (L2a re-audit with fat q1). Completeness needs q1 < 2^257 + which the honest builder satisfies. Keep as spec clarity. +3. **[redundancy-for-soundness] KBitsZeroOnPadding** (ecsm.rs:845-853): padding + k_bits could only fire unmatched Bit RECEIVES (multiplicities are {0,1} by + unconditional IS_BIT; padding ECDAS/ECSM senders are µ- or next_op-dead) ⇒ + rejection-only ⇒ not soundness-load-bearing. It IS completeness-relevant + hygiene (honest padding is all-zero) and cheap. Keep. +4. **[tightness] Carry-offset slack**: minimal sound offsets are {x2: 7949, + yG: 8371, λ: 24605, xR: 256, yR: 8289}; the repo constants are safely above + with 2^16-window room on both sides. No action. +5. **[non-dead-weight] XR_SUB_P** is genuinely load-bearing: without it, drain + values v < 2^32 + 977 admit the non-canonical representation v + p (N6 SAT), + i.e. a wrong 32-byte xR delivered to the guest. Astronomically rare input + class, but the check is what closes it. +6. **[redundancy, keep-as-insurance] Mid-limb carry windows** (e.g. the + IsHalfword on c[40]): individually redundant — the linear carry gadget shows + a Goldilocks wrap injected at one un-windowed interior carry cannot be + absorbed while c₆₃=0 and the neighbouring windows hold (N1 UNSAT, S free = + strong). By contrast the TOP closing check c₆₃=0 IS load-bearing (N3 SAT). + Reading: the interior windows earn their place collectively (they are the L1 + telescoping hypothesis); no single interior one is a soundness lynchpin, but + removing several would break L1. Do not churn — they are cheap + precomputed-table sends. + +## Reproduction + +venv: the oracle scratchpad venv + `z3-solver sympy` (see ../oracle/README.md). +``` +python positive_real_witness.py # transcription anchor (run FIRST) — 872k checks +python l1_l2_lift.py # L1, L2a/b/c + audit controls +python l3_l4_value.py # L3a/b, A-PRIME, L4a/b/c +python l5_sides.py # L5a/b/c +python l7_pin.py # L7 (990 queries) +python l8_negative.py # L8 battery (~5 min; carry-gadget queries dominate) +``` +Logs in `logs/`. The harness `witness` command (added to +`../oracle/repo-harness/src/main.rs`) dumps real EcsmWitness/EcdasStep values for +the positive control; rebuild with `cargo build --release` in that dir. diff --git a/thoughts/ec-recover-opt/gate/TRANSCRIPTION-AUDIT.md b/thoughts/ec-recover-opt/gate/TRANSCRIPTION-AUDIT.md new file mode 100644 index 000000000..4dc8226a1 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/TRANSCRIPTION-AUDIT.md @@ -0,0 +1,560 @@ +# Transcription audit — does the lincomb2 gate assert more than the chips enforce? + +Adversarial, one-directional audit of `thoughts/ec-recover-opt/gate/` against +`prover/src/tables/ecdas2.rs` (658 cols, 288 constraints) and `ecsm2.rs` +(1,155 cols, 693 constraints), branch `feat/ec-lincomb2`, PR #871. + +Only one direction is dangerous. A model **weaker** than the chip yields a +spurious SAT — a false alarm. A model **stronger** than the chip yields UNSAT on +a chip that is genuinely forgeable — false assurance. The 3.3M-check positive +anchor cannot see the second kind: an honest witness satisfies a correct model +and an over-strong model equally well. That blind spot is what this audit +covers. + +Reproduce: `/bin/python audit_transcription.py` (z3 only; §E also needs +`../oracle`). No `.rs` file was modified — the tampers in §C/§D/§E are done on +in-memory copies. + +--- + +> ## STATUS: all five findings FIXED and regression-tested. +> +> `audit_transcription.py` is now the regression suite for the fixes: it re-runs +> every tamper below and requires the detector to fire — **22/22 pass**. The +> chips were not touched (they were correct; the gate was the problem). +> +> | # | fix | where | +> |---|---|---| +> | F1 | `dinv_gate_state()` parses the `Relation::Dinv` arm, requires the gate to be a plain sum of columns, and requires that set to equal the `Addend` receive's unit-coefficient `Multiplicity::Linear` terms | `gate2_common.py` | +> | F2 | `padding_gate_state()` parses the emitted `(1 − MU)·X` expression and enforces **gated columns == raw bus multiplicities**, in both directions. Every parser fails closed | `gate2_common.py` | +> | F3 | `relation_bodies_identical()` extended to the `s_i` prologue and `conv_carry`; new `membership_bodies_identical()` for the ECSM/ECSM2 pair | `gate2_common.py`, reported by `l1_l5_port2.py` | +> | F4 | `Ecdas2Row.padding_gate` defaults to `True`; N4b re-pointed at live `PH1 = 0` rows and now prints its witness rows | `gate2_common.py`, `l8_negative2.py` | +> | — | `JointSel → PH*/S*` compared arm for arm against the chip (§7's last modelled step) | `joint_sel_maps()`, `check_sel_maps()` | +> | — | doc hygiene: `L6-COUNTING.md` status header, stale cites, position-0/1 wording | `L6-COUNTING.md`, `RESULTS-lincomb2.md`, the scripts' docstrings | +> +> **One fix failed its own regression test on the first attempt**, and is +> recorded rather than quietly patched: §G's tamper +> `let g = gate_expr(b) * b.main(0, cols::S1) + …` left the `cols::` **set** +> unchanged, so the first version of the F1 check accepted it while an opaque +> factor could gate the relation off at will. `_is_plain_column_sum()` closed it +> — set equality was not enough; the expression must *be* the sum. +> +> Board impact: **the L8 non-vacuity count was 6, not 7** (F4). After +> re-pointing N4b it is 7 again, for a different and now-correct reason. No +> lemma changed verdict. `l1_l5_port2` 10/10, `l6_joint_counting` all pass, +> `l8_negative2` 7 forgeries / 2 redundancies / **0 live holes**. + +## Verdict + +**No live over-strong assertion was found.** The boolean core of the model is +*exactly* equivalent to the chip: brute-forcing all 2^11 assignments of +`{MU, OP, NB, D1, D2, S1, S2, S3, S_CORR, PH1, PH2}` against an independent +second transcription of `Ecdas2Constraints::eval` idx 0..=27 gives **11 admitted +assignments on each side, symmetric difference empty in both directions** +(`audit_transcription.py` §A). Every multiplicity, gating factor, bus tuple and +enum mapping listed in the table below matches the source. + +But three of the gate's assertions rest on premises the gate **does not check +and would not notice becoming false**, and one negative control reports a +forgery that the chip actually blocks: + +| # | severity | what | +|---|---|---| +| **F1** | **high** | The D_INV gate `g = S1+S2+S3+S_CORR` is asserted by every L5b′ lemma and read by nothing. A one-term deletion breaks it, produces a working forgery, and leaves every gate verdict green. | +| **F2** | **high** | `chip_state()` — the mechanism the board credits with "keeping the gate honest as the chips change" — detects `idx 22..=27` from a **comment**, and `D_INV` from token presence. Delete the defences, keep the comments: still reported present. | +| **F3** | medium | The PORT lemma's mechanical check compares only the `match` arms of `s_i`. Rebinding an operand column in the prologue (e.g. `xa → cols::XR`) falsifies L3a/L4a/b/c and is still reported "identical". | +| **F4** | low (wrong direction) | L8 control **N4b** claims `SAT — FORGES`; on the chip's real constraint set the same ablation is **UNSAT**. The SAT comes from a model that omits idx 22..=27. Non-vacuity is 6 genuine forgeries, not 7. | +| F5 | cosmetic | One literal over-strong assertion — `ROUND ∈ [0,255]` on `MU = 0` rows — verified benign. | + +None of F1–F3 is a chip bug. All three are **unverified premises presented as +verified results**, which is the failure mode the ECDAS2 JointBit incident +already demonstrated once. + +--- + +## F1 — the D_INV gating expression is asserted everywhere and checked nowhere + +`RESULTS-lincomb2.md` §2 states the chip "gates by `ΣS` rather than `OP`… it ties +the check to the very expression that counts the Addend receive, so it cannot +drift away from the rows that consume one", and L5b′(a1)/(a2) are the lemmas +that discharge L4a's side condition — the whole unconditionality claim. + +The chip's gate is at **`ecdas2.rs:810-813`**: + +```rust +let g = b.main(0, cols::S1) + + b.main(0, cols::S2) + + b.main(0, cols::S3) + + b.main(0, cols::S_CORR); +``` + +`l1_l5_port2.py` §3 (a1) and (a2) quantify over `Ecdas2Row.addend_receive()` — +`self.s1 + self.s2 + self.s3 + self.sc`, a Python expression +(`gate2_common.py:229-231`). **Nothing connects the two.** A grep over +`gate/*.py` for any reference to `Relation::Dinv`, `cols::S_CORR` or the `let g` +expression returns nothing; `relation_bodies_identical()` deliberately excludes +the Dinv arm; `chip_state()["dinv_relation"]` is `"D_INV" in src and "Dinv" in +src`. + +### The forgery a narrowed gate would hide + +Drop one term — `g = S1 + S2 + S3` — and the **correction row** (which carries +`S_CORR = 1` and every other selector 0, by idx 21 + idx 14) has `g = 0`: no +non-degeneracy check at all. Its λ relation then degenerates whenever the +accumulator entering it equals its addend `W = −2^len·T₀`. + +That is cheap to arrange and needs **no discrete log**: + +``` +acc = 2^len·T₀ + u1·G + u2·P2 (the chain's accumulator at the correction row) +acc = W = −2^len·T₀ ⟺ u1·G + u2·P2 = −2^(len+1)·T₀ + +take u1 = u2 = 1 (len = 1) ⇒ P2 = −2^(len+1)·T₀ − G — one point subtraction +``` + +`audit_transcription.py` §E runs it: + +``` +P2 = (0x6d2601d3ba4652d07eec0066ed211b5cdbdf3c1cf8d0cbe07877b0871e15eb14, + 0x15d65f47ef5cb786daaf7273f57fd2d9d80c4d9a8ac63e0bd716c5bad616431c) +correction row: xA == xB True, yA == yB True +lambda relation identically 0 (free lambda): True +honest Q = (0x3f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b, ...) +forged Q' family, 5 distinct values, none equal honest: True +``` + +With `xA = xB` *and* `yA = yB`, `op·(Σλ_j(xB−xA)_{i−j} + yA_i − yB_i)` is +identically zero for **every** λ, so `xR = λ² − 2xA`, `yR = λ(xA − xR) − yA` is a +free one-parameter family of outputs — the same shape as the NUMS finding this +relation was added to close, relocated to the correction row. `P2` is on the +curve and MEMW-bound, both scalars are in `[1, N)`, the schedule is the honest +one, the Addend and JointBit balances hold, and `status = 0`. + +And with the tampered source in place: + +``` +chip_state dinv_relation True ecdas2_constraints 288 PORT all-identical True +l1_l5_port2 §3 (a1) unsat (a2) Correction consumes an addend unsat +``` + +Every verdict on the board is unchanged. **The gate cannot distinguish the chip +that blocks this from the chip that does not.** + +To be explicit: **the chip as committed has the `S_CORR` term** (verified by +reading `ecdas2.rs:810-813`), so this forgery is blocked today — +`d·(xB − xA) = 1` with `xB = xA` is unsatisfiable, which §E also confirms. F1 is +a hole in the gate's coverage, not in the chip. + +**Fix:** have `chip_state()` extract the `Relation::Dinv` arm and assert the `g` +expression is literally the four selector columns, in the same style +`relation_bodies_identical()` uses for the other three arms — and assert it +matches the Addend receive's `Multiplicity::Linear` term list, which is the +property the prose actually claims. + +--- + +## F2 — `chip_state()` detects the comment, not the defence + +`gate2_common.py:9-21` is explicit about why this function exists: two soundness +fixes were outstanding, and "the gate must say so rather than quietly reporting +the expected SAT… so this file keeps telling the truth as `ecdas2.rs` changes +underneath it." `RESULTS-lincomb2.md` repeats the claim in a block quote. + +`padding_digit_gate` (`gate2_common.py:122-126`) tries three regexes. The chip +emits idx 22..=27 as a loop over a column list (`ecdas2.rs:988-1003`): + +```rust +for (i, col) in [cols::D1, cols::D2, cols::S1, cols::S2, cols::S3, cols::S_CORR] … { + b.emit_base(22 + i, (one - mu) * x); +} +``` + +The multiplicand is the loop variable `x`, so the two **code** regexes +(`(one|1)\s*-\s*mu…\*\s*d1` and `d1\s*\*\s*\(\s*(one|1)\s*-\s*mu`) never match. +Only the **comment** regex fires — on the module-header table (`ecdas2.rs:116`) +and on the constraint map (`ecdas2.rs:669`). §D deletes the emitting loop while +leaving every comment intact: + +``` +emitting loop present : False +padding_digit_gate : True <- should be False +``` + +A chip in that state is the exact L6-E arbitrary-chosen-sender forgery, and +`l8_negative2.py` would score N1 as `SAT — FORGES` (a passing ablation) instead +of `LIVE HOLE`. + +`dinv_relation` is `"D_INV" in src and "Dinv" in src`. §D removes +`(Relation::Dinv, cols::C3)` from the emit loop — the relation is then never +emitted, the block shrinks from 288 to 223 constraints — and the detector still +reports `True`, because the columns, the enum variant and the comments survive. + +The other four `chip_state()` fields (`ecdas2_columns`, `ecdas2_constraints`, +`ecsm2_columns`, `jointbit_multiplicity`) are **display-only** — grepped, no +lemma or verdict reads them. `jointbit_multiplicity` in particular correctly +reports `Multiplicity::Column`, but if the chip changed it, nothing would react. + +**Fix:** detect from the emitted expression, or better, assert on the *shape*: +parse the `for … b.emit_base(22 + i, (one - mu) * x)` loop and its column list, +and cross-check the list against the set of columns that appear in any +`Multiplicity::` of `bus_interactions()`. That last check is the invariant the +header actually claims ("every column that is a bus *multiplicity*") and it +would have caught the original JointBit bug from the other side. + +--- + +## F3 — the PORT lemma compares the arms, not the operands + +`relation_bodies_identical()` (`gate2_common.py:90-107`) extracts the +`Relation::{Lambda,Xr,Yr} => { … }` arms of `s_i` from both chips, normalises out +comments/whitespace and the `XB/YB → XG/YG` rename, and compares. Every lemma +marked PORTED rests on the result. + +The operand bindings are **not in the arms**. They are in the `s_i` prologue, +before the `match` (`ecdas2.rs:747-755`): + +```rust +let lam = |j| Self::byte_at(b, cols::LAMBDA, 32, j); +let xg = |j| Self::byte_at(b, cols::XB, 32, j); +let xa = |j| Self::byte_at(b, cols::XA, 32, j); +… +``` + +§C rebinds `xa` to `cols::XR` in the ECDAS2 prologue — so every occurrence of +`xA` in the λ, xR and yR relations reads `xR` instead, falsifying L3a's +composition identity and L4a/b/c's pinning outright — and re-runs the gate's own +check: + +``` +s_i::Lambda : identical s_i::Xr : identical s_i::Yr : identical +-> port argument still reports all-identical: True +``` + +`conv_carry` and the emit loop are not compared either (§C prints +`conv_carry bodies identical: False` — expected, ECDAS2 gained a `Dinv` arm — +but the function is never called by the port check, so nothing depends on it). + +I verified by reading that the prologues **are** identical today, modulo exactly +the documented `XG→XB` / `YG→YB` rename, and the audit script confirms it under +the same normalisation. So the PORT premise holds in fact; it is just not +established by the check that claims to establish it. + +**Fix:** compare `_norm(prologue(ECDAS1)) == _norm(prologue(ECDAS2))` and +`_fn_body(…, "conv_carry")` with the `Dinv` arm excised, alongside the existing +per-arm comparison. Three lines. + +--- + +## F4 — N4b's forgery does not exist on the chip (model *weaker*, not stronger) + +`l8_negative2.control_4b` builds its row with `Ecdas2Row(s, "pad", ablate=…)` — +`padding_gate` defaults to `False` (`gate2_common.py:194`), i.e. a chip **without +idx 22..=27**. It then sets `MU = 0, PH1 = PH2 = 0, OP = 0`, asks for a live +Addend receive, gets `unsat / sat`, and reports `SAT — FORGES`. + +On the chip's real constraint set the same ablation is **UNSAT** (§B): idx +24..=27 zero every selector on a `MU = 0` row regardless of idx 14. Ablating idx +14 alone cannot mint the spurious receive. + +This is the *safe* direction — a spurious SAT, a false alarm — but it means: + +- the board's headline "**7 genuine forgeries**" non-vacuity claim is **6**; +- `RESULTS-lincomb2.md` §4's reading of N4b ("Load-bearing exactly where PH1 = 0: + padding rows and the two off-chain phases") is half wrong: the padding-row half + is covered by idx 22..=27, not by idx 14; +- N4c's note "Keep idx 14 — N4b is what it covers" cites the wrong evidence. + +The conclusion *keep idx 14* survives — §B runs the probe N4b should have run, +on **live** `PH1 = 0` rows, where idx 22..=27 is vacuous: + +``` +precompute (MU=1, PH1=PH2=0) untampered unsat ablate-14 sat +correction (MU=1, PH2=1) untampered unsat ablate-14 sat +``` + +Without idx 14 the precompute or correction row can be an `OP = 0` doubling that +still consumes its addend — a genuine forgery. Only the justification needs +rewriting. + +Same root cause, worth checking before the next run: `l1_l5_port2.py` §3(a1)/(a2) +and `l8` controls 4 and 4c also use `padding_gate=False`. Those are all `MU = 1` +queries, where idx 22..=27 is vacuous, so their verdicts are unaffected — but the +default is a trap. Make `padding_gate` default to `True` and have the ablations +pass `False` explicitly. + +--- + +## F5 — the one literal over-strong assertion (benign) + +`Ecdas2Row.__init__` (`gate2_common.py:200-201`) and +`l6_joint_counting.Row.__init__` (`:52-53`) assert `0 ≤ ROUND ≤ 255` on **every** +row. The chip's only `ROUND` range check is the `AreBytes` pair +`(ROUND, Q0+32)` at multiplicity `MU` (`ecdas2.rs:566`), which is **dead on +padding rows** — the model's own comment says so ("AreBytes(ROUND), MU-gated"), +and L6-COUNTING §2.2 notes it explicitly. + +Verified benign. On a `MU = 0` row, idx 22..=27 force `D1 = D2 = S* = 0`, idx 14 +then forces `OP = 0` and idx 13 forces `NB = 0`, so `ROUND` feeds only: +the JointBit send (multiplicity `D1`/`D2` = 0), the Ecdas receive/send +(multiplicity `MU` = 0) and the AreBytes pair (multiplicity `MU` = 0). It is +free and unread. Nothing is hidden. + +Two smaller instances of the same shape, both benign for the same reason: +`l1_l5_port2` §3(c) bounds `q3 < 2^264` and §3(b1)/`l8` control 2 bound +`0 ≤ d < P`, where the chip gives `q3 < 2^264` and `d < 2^256` **only at +`MU = 1`**; both arguments (`p·(µR − q3) = 0`, `p | 1`) are independent of the +bound, so the conclusions stand. + +--- + +## The assertion table + +Chip references are `file:line` on `feat/ec-lincomb2` @ `bc62f00e`. Verdicts: +**match** = model = chip; **stronger** = model asserts more than the chip; +**weaker** = model omits a chip constraint; **unchecked** = the gate asserts it +but never reads the source. + +### ECDAS2 constraints — `Ecdas2Row` / `check_row` / `l6_joint_counting.Row` + +| model assertion | chip | verdict | +|---|---|---| +| `bit_var` on 11 columns MU, OP, NB, D1, D2, S1, S2, S3, S_CORR, PH1, PH2 | `ecdas2.rs:851-870` idx 0..=10, same 11 columns, `x·(1−x)`, ungated | match | +| idx 11 `PH1·PH2` | `:873-875` | match | +| idx 12 `OP·NB` | `:879-881` | match | +| idx 13 `(1−OP)(NB−D1−D2+D1·D2)` | `:886-891` | match | +| idx 14 `OP−S1−S2−S3−S_CORR` (ungated) | `:897-902`, ungated | match | +| idx 15/16 `(1−PH1)·D1`, `(1−PH1)·D2` | `:909-916` | match | +| idx 17 `PH1·S_CORR` | `:920-922` | match | +| idx 18 `PH1·(S1+S3−OP·D1)` | `:933-938` | match | +| idx 19 `PH1·(S2+S3−OP·D2)` | `:939-944` | match | +| idx 20 `MU·(1−PH1−PH2)·(S2−1)` — MU-gated | `:950-956`, MU-gated | match | +| idx 21 `PH2·(S_CORR−1)` — **not** MU-gated | `:960-963`, not MU-gated | match | +| idx 22..=27 `(1−MU)·{D1,D2,S1,S2,S3,S_CORR}` (opt-in) | `:988-1003`, exactly those 6 columns | match — but see F2 for how it is *detected*, F4 for the default | +| all constraints hold on every row | `emit_base` → `RowDomain::ALL` (`crypto/stark/src/constraints/builder.rs:133-135`); no `emit_base_rows`, no `except_last` in either chip | match | +| whole boolean block, 2^11 brute force | independent second transcription | **match, both directions, 11 = 11** | +| `ROUND ∈ [0,255]` on every row | `:566` AreBytes pair at multiplicity `MU` — dead at `MU = 0` | **stronger** (F5, benign) | +| relation `Dinv` gated by `ΣS`; `g == op` on live rows | `:810-813` `g = S1+S2+S3+S_CORR` | match — **unchecked** (F1) | +| `Dinv` `S_i = g·(Σd_j(xB−xA)_{i−j} − [i=0]) + rq(Q3)` | `:802-814` | match (read; `positive_real_witness2.py:176-183`) | +| 4 relation blocks × (64 ConvCarry + ColIsZero(c_63)) = idx 28..=287 | `:1006-1021`, `debug_assert_eq!(idx, 288)` | match | +| `IsHalfword` on `c_0..c_62` only (63 per relation), `c_63` pinned by ColIsZero | `:590` `for i in 0..63`; `:1018-1019` | match | +| λ/xR/yR arms identical to `ecdas.rs` modulo `XG/YG → XB/YB` | `ecdas2.rs:757-789` vs `ecdas.rs:363-395`; prologues `:747-755` vs `:353-361` | match (read) — **check does not cover the prologue** (F3) | +| `rq`, `p_byte_expr`, `r_byte_expr`, `byte_at` identical | `:685-738` vs `ecdas.rs:290-345` | match (mechanically compared) | +| `s_ecdas_lambda/xr/yr` (`gate_common.py:154-187`) | `ecdas.rs:363-395` | match (read, term by term) | +| `CARRY_OFFSET_DINV = CARRY_OFFSET_XR = 8161` | `:139`, and `OFF["ecdas_xr"]` in `positive_real_witness2.py:186` | match | + +### ECDAS2 bus interactions — `digit_send` / `addend_receive` / the L6 prose + +| model assertion | chip | verdict | +|---|---|---| +| Ecdas receive multiplicity `MU` | `:466-478` `mu()` | match | +| Ecdas send multiplicity `MU` | `:616-638` `mu()` | match | +| `digit_send` = raw `D1`/`D2`, **ungated** | `:601-612` `Multiplicity::Column(col)` | match | +| `addend_receive` = `S1+S2+S3+S_CORR`, **ungated** | `:487-504` `Multiplicity::Linear`, coefficient 1 each | match | +| 131 AreBytes at `MU` | `:545-572` — 8 bases × 16 + `(ROUND,Q0[32])` + `(Q1[32],Q2[32])` + `(Q3[32],0)` = 131, all `Column(cols::MU)` | match | +| 252 IsHalfword at `MU` | `:584-597` — 4 × 63, `mu()` | match | +| no other column supplies a multiplicity | grep of `Multiplicity::` in the file: `MU`, `D1`, `D2`, `{S1,S2,S3,S_CORR}` only | match | +| joint tuple `[1, ts_lo, ts_hi, phase, accX(32), accY(32), round, op]`, arity 70 | `:399-420`, `JOINT_CHAIN_ID = 1` at `:172` | match | +| `phase` = `PH1 + 2·PH2`, same expression on receive and send | `:446-457`, used at `:471` and `:621` | match | +| send round = `ROUND + NB − 1`, send op = `NB` | `:623-634` | match | +| addend tuple `[ts_lo, ts_hi, sel, x(32), y(32)]`, `sel = S1+2S2+3S3+4S_CORR` | `:423-439`, `:508-525` | match | +| JointBit send tuple `[ts_lo, ts_hi, ROUND, stream]`, stream ∈ {1,2} | `:601-611` | match | +| bus-28 separator: old chain pins tuple position 0 to `0`, joint chain to `1` ⇒ different α¹ coefficient | `ecsm.rs:616` `constant(0)`; `ecdas2.rs:411` `constant(1)`; `lookup.rs:1653` `alpha_offset = 1` advanced unconditionally, `:679` skips only the multiply | match — the board's correction of the source comment is right | + +### ECSM2 — the L6/L8 prose and `l8.control_5` + +| model assertion | chip | verdict | +|---|---|---| +| idx 2 `OK·(1−MU)`, idx 3 `OK·STATUS`, idx 4 `MU·(STATUS·S_INV−(1−OK))` | `ecsm2.rs:1156-1177` | match | +| all six chain seeds/drains at multiplicity `OK`; `OK` is IS_BIT | `:836-920` all `ok()`; `:1149-1153` idx 1 | match | +| seeds: phase 0 `(G, 0, round 0, op 1)`, phase 1 `(T₀, 1, LEN_M1, op 0)`, phase 2 `(ACC, 2, round 0, op 1)`; all drains `round = −1, op = 0` | `:836-920` | match | +| phase-1 drain and phase-2 seed use **the same columns** (a literal relay) | `:881` and `:899` both `coord(cols::ACC_X)/coord(cols::ACC_Y)` | match | +| JointBit receive multiplicity `2·u_bit`, raw | `:771-787` `Multiplicity::Linear([{coefficient: 2, column: base+i}])` | match | +| …made inert by idx 517/518 `(Σ u_bit)·(1−OK)` | `:1194-1203` | match | +| Addend publishes `N1`/`N2`/`N3` raw, correction at `OK` | `:795-817` | match | +| …made inert by idx 519..=521 `N·(1−OK)` | `:1207-1213` | match | +| everything else `OK`-gated; Ecall + x10 MEMW `MU`-gated | `:553-582` `mu()`, `:587-826` `ok()` | match | +| `len ≤ 256` structural via EC_T0 | `ec_t0.rs:116` `NUM_ROWS = 256`, no padding; `:353-369` receive key `LEN_M1 + 1` | match | +| EcT0 tuple `[len, x(32), y(32)]`, arity 65, both sides | `ecsm2.rs:821-826` / `ec_t0.rs:353-368` | match | +| `u1, u2 ≠ 0` via the Zero bus | `:749-765` — sums the 32 **bytes** (coefficient `1 << (b % 8)`), which is zero iff every byte is zero | match (the byte-sum form is correct, and is the only form expressible in `i64` coefficients) | +| membership relations X2/Yg are ECSM's with `µ → OK` | `ecsm2.rs:1048-1082` vs `ecsm.rs:744-782` | match (read) — **no lemma or mechanical check in the lincomb2 board covers this port** | + +### Derived / modelled values + +| model assertion | chip | verdict | +|---|---|---| +| `PHASE = {Precompute:(0,0), Correction:(0,1), Double/AddP1/AddP2/AddP12:(1,0)}` (`positive_real_witness2.py:72-73`) | `ecdas2.rs:258-264` `phase_bits`, all 6 `JointSel` arms | **match, arm for arm** | +| `SELECT = {Double:(0,0,0,0), AddP1:(1,0,0,0), AddP2:(0,1,0,0), Precompute:(0,1,0,0), AddP12:(0,0,1,0), Correction:(0,0,0,1)}` (`:74-76`) | `ecdas2.rs:268-276` `selector_bits`, all 6 arms | **match, arm for arm** | +| dict keys are the harness's `sel` strings | `oracle/repo-harness/src/main.rs:59-68` `sel_name`, all 6 | match | +| `JointSel` has exactly these 6 variants | `crypto/ecsm/src/witness.rs:551-565` | match | + +This is `RESULTS-lincomb2.md` §7's flagged "one remaining modelled gap". It is +**exact today**, verified arm for arm against an exhaustive `match` — but it is a +hand copy with no mechanical link, so it belongs in the same class as F1/F2/F3. +`JointSel` is not `#[non_exhaustive]`, so a new variant forces a compile error in +`phase_bits`/`selector_bits`, but silently gets a `KeyError` (a crash, not a +false pass) on the Python side — acceptable. + +--- + +## Cross-checks that came back clean + +- **Row domains.** Neither chip calls `emit_base_rows`, `RowDomain::except_last` + or any end-exemption; `emit_base` is `RowDomain::ALL` + (`crypto/stark/src/constraints/builder.rs:133-135`). The model's "holds on + every row" is exact. No padding-row exemption exists to be over-modelled. +- **Integer vs field modelling.** Every schedule constraint the model evaluates + over ℤ has range within `[−4, 1]` on boolean inputs, so `≡ 0 mod p_g` and + `= 0` over ℤ coincide. No wraparound is available to a prover. +- **Multiplicity semantics.** `Multiplicity::Column` is the raw column value and + `Linear` the linear combination (`crypto/stark/src/lookup.rs:1328-1363`); there + is no product form, so L6-COUNTING §4's "make the multiplicities `MU·D1`" + suggestion is not currently expressible. The counting argument's "each row + contributes 0 or 1" holds because `D1`/`D2` are IS_BIT. +- **`N1/N2/N3` need no range check.** The matching side is a sum of at most + `2^k` bits with `k ≪ 64`, so its integer value is far below `p_g`; a "negative" + or inflated count cannot balance. The chip comment is right. +- **Padding-row inertness, ECDAS2.** With idx 22..=27: `S* = 0` ⇒ (idx 14) + `OP = 0` ⇒ (idx 13) `NB = 0`; `D1 = D2 = 0`. Every remaining interaction is + `MU`-gated. Nothing a padding row can carry reaches a bus. +- **Padding/error-row inertness, ECSM2.** `MU = 0` ⇒ (idx 2) `OK = 0`; idx + 517-521 kill the four raw-multiplicity interactions; the rest are `OK`- or + `MU`-gated. An error row (`MU = 1, OK = 0`) fires only the Ecall receive and + the x10 access, and idx 4 forces `STATUS ≠ 0`. +- **L6-COUNTING §3(f)'s "at most two live rows share a round."** Re-derived: + `OP·NB = 0` gives add ⇒ `Δround = −1`; a double with `NB = 1` forces the + successor to be an add at the same round, which then decrements; so no cycle + and no third row at a round. Balance decomposes each phase into one seed→drain + path (cycles excluded by monotonicity), and the `round = −1` drain is + unreceivable because live `ROUND` is byte-checked. The counting step is sound. +- **Byte-ness inheritance for `XB`/`YB`.** `point_coord_busvalues` + (`ecsm.rs:284-286`) is `(0..32).map(packed)` — one element per byte — so tuple + equality is per-limb and byte-ness transfers. `WIDTH-AUDIT.md` §3.1 already + flags this as load-bearing. Roots: `G` constant, `P2` via MEMW, `P12` = the + phase-0 drain of an AreBytes-checked `XR`/`YR`, `T₀N` from the preprocessed + table. No cycle. +- **`gate_common.s_ecdas_*` vs `ecdas.rs`.** Compared term by term. Identical, + including the `byte_at` zero-padding and the 33-limb quotients. +- **L3a/L4a/L4b/L4c models vs the composed relations.** `l3_l4_value.py:69-92` + and `:148-231` state exactly the composed forms of `ecdas.rs`'s three + relations with `µ = 1`; the operand bounds used (`lam < 2^256`, `q < 2^264`) + are what the chip's AreBytes checks give at `MU = 1`. + +--- + +## Could not verify + +Listed so the boundary is explicit rather than implied. + +1. **Contracts C1–C7 and A-PRIME.** I read the *sending* side in both chips, not + the receiving side: `bitwise.rs`'s AreBytes/IsHalfword tables, MEMW's byte + authority for `X_P2`/`Y_P2`, the CPU↔Ecall binding, timestamp uniqueness, and + the generic LogUp balance argument. `RESULTS-lincomb2.md` says the contracts + are "unchanged from RESULTS.md", but C4 as written there names `xG`/`k`/`xR`; + its ECSM2 instance (`X_P2`, `Y_P2` bytes from the 8 MEMW dword reads at + `ecsm2.rs:631-649`) is a different, unstated instance. Worth restating C4 for + the joint chip. +2. **The ECSM2 membership port.** `Relation::X2`/`Yg` (`ecsm2.rs:1048-1082`) are + ECSM's bodies with the column rename and `µ → OK`; I verified that by reading, + but no lemma on the lincomb2 board and no mechanical check covers it, even + though the soundness theorem's "`P2` is on the curve" clause depends on it. + Same fix as F3: extend `relation_bodies_identical()` to the ECSM/ECSM2 pair. +3. **`positive_real_witness2.py` was not executed** — it needs the built Rust + harness (`../oracle/repo-harness/target/release/ecsm-oracle-harness`). I read + its model and verified its `PHASE`/`SELECT` maps and its idx 11..=21 / Dinv + transcription against the source; I did not reproduce the 3.3M checks. + Note that the anchor checks **constraint values only** — it never evaluates a + multiplicity or a gating expression, so it could not have caught the original + JointBit bug and cannot catch F1/F2 either. +4. **`l1_l2_lift.py`, `l3_l4_value.py`, `l5_sides.py`, `l8_negative.py` + (the old-gate lemmas) were not re-run**, nor were `width_audit.py` / + `width_audit_z3.py` (~25 min). I audited the *premise* they are ported on + (F3) and read their models against `ecdas.rs`; I did not re-derive their + proofs. +5. **Completeness-side mirroring.** `collect_bitwise_from_ecdas2` / + `collect_bitwise_from_ecsm2` must mirror the AreBytes send layouts. Not + checked — a mismatch is an unprovable honest witness, not a forgery. +6. **Whether the constructions in F1 can be packaged as well-formed `(z, v, r, s)` + ecrecover inputs.** The chip-level forgery needs only an on-curve `P2` in + memory, which the construction gives. Packaging additionally needs + `x(P2) < N`, which is overwhelmingly likely but was not checked for the + specific `P2` printed above. + +--- + +## Documentation defects found along the way + +Not soundness, but a reader following the citations is misled: + +- **`L6-COUNTING.md`'s headline verdict is stale.** It still opens with "**L6 + does NOT hold for `ecdas2.rs` as written. There is a constructive break**", + and §2 presents the padding-row forgery as live. `RESULTS-lincomb2.md` §3 + links it as "Full derivation in `../lincomb2/L6-COUNTING.md`". The fix landed + as idx 22..=27; the doc needs a status header. +- **Stale line citations.** `L6-COUNTING.md` §2.1 and + `l6_joint_counting.py:76,229` cite the JointBit send as `ecdas2.rs:459-470`; + it is now `:601-612`. `l6_joint_counting.py:4` and + `positive_real_witness2.py:15-18,80` still say ECDAS2 has 217 constraints + / `idx 0..=216` / `22..=216`; it has 288 / `0..=287` / `28..=287` (the code + itself does check all four relation blocks — only the prose is stale). +- **Tuple position off by one between docs.** `RESULTS-lincomb2.md` §3 says the + separator is "tuple position 1"; `L6-COUNTING.md` §5.2 says "position 0". It + is `values[0]`, which lands at α¹ because `alpha_offset` starts at 1 + (`lookup.rs:1653`). Both are defensible readings of "position"; pick one. +- **`gate2_common.py`'s module docstring** still describes both fixes as + outstanding ("Two soundness fixes were outstanding when this gate was + written"). True as history, confusing as a header. + +--- + +## Recommended actions, in priority order — ALL DONE + +1. **F1 — DONE.** `dinv_gate_state()` extracts the `Relation::Dinv` arm, checks + `g` is applied as `g * s`, checks it is a plain sum of columns, and requires + that set to equal the `Addend` receive's `Multiplicity::Linear` terms (each + with coefficient 1, since a `coefficient: 2` would change the multiplicity + without changing the set). +2. **F2 — DONE.** `padding_gated_columns()` parses the emitted expression in + both the loop and unrolled forms; `padding_gate_state()` requires the gated + set to **equal** `multiplicity_columns() − {MU}`, which resolves loop-bound + `Multiplicity::Column(col)` through its `for` header. `Dinv` presence is read + from the emit loop. Unparsed multiplicities are surfaced, never ignored. +3. **F3 — DONE.** `relation_bodies_identical()` now covers `s_i::prologue` and + `conv_carry` (Dinv dispatch excised); `membership_bodies_identical()` covers + the ECSM/ECSM2 pair, closing gap 2. `carry_chain` is excluded and the reason + is stated in the docstring. +4. **F4 — DONE.** `padding_gate` defaults to `True`; N4b re-points at the live + `PH1 = 0` phases and prints its witness rows; the count is corrected in + `RESULTS-lincomb2.md` §4 with the history recorded. +5. **Doc hygiene — DONE.** `L6-COUNTING.md` has a status header and its stale + cites/counts refreshed; `gate2_common.py`, `l6_joint_counting.py` and + `positive_real_witness2.py` docstrings corrected; the position-0 / position-1 + wording reconciled (element 0, exponent α¹). + +Beyond the list: the `JointSel → PH*/S*` mapping is compared arm for arm against +the chip, which closes `RESULTS-lincomb2.md` §7's last "modelled step", and §7 +now records the anchor's structural limitation (constraint values only — never a +multiplicity, never a gating expression). + +None of this changed a chip. The chips, as far as this audit can determine, +enforce everything the gate says they do — and the gate now checks that claim +instead of asserting it. + +## Regression suite + +`audit_transcription.py`, 22/22: + +``` +A model ⊆ chip and chip ⊆ model on idx 0..=27 (2^11 cases, empty both ways) + padding_gate defaults to the chip +B the OLD N4b target is NOT a forgery; the NEW one IS +C untampered ECDAS/ECDAS2 and ECSM/ECSM2 ports clean; + rebound operand column DETECTED; broken carry recurrence DETECTED; + tampered ECSM2 membership relation DETECTED +D gated set == raw multiplicity set; defence-deleted-comment-kept DETECTED; + digit send escaping the gate DETECTED; a NEW ungated multiplicity DETECTED; + Dinv dropped from the emit loop DETECTED +E gate == Addend receive; S_CORR dropped DETECTED; the forgery it hides, + constructed, and blocked by the real chip +F JointSel arms match; a changed arm DETECTED +G unparsed gate shape reports ABSENT; opaque gate helper rejected +``` diff --git a/thoughts/ec-recover-opt/gate/audit_transcription.py b/thoughts/ec-recover-opt/gate/audit_transcription.py new file mode 100644 index 000000000..5d0eb71f8 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/audit_transcription.py @@ -0,0 +1,471 @@ +"""Adversarial transcription audit of the lincomb2 gate — model ⊆ chip. + +Companion to `TRANSCRIPTION-AUDIT.md`. Everything here answers ONE question: + + does the z3 model assert something `prover/src/tables/ecdas2.rs` / + `ecsm2.rs` do not actually enforce? + +That direction is the dangerous one: a model STRONGER than the chip turns a +genuinely forgeable chip into a green UNSAT. The positive anchor +(`positive_real_witness2.py`) structurally cannot see it — honest witnesses +satisfy a correct model and an over-strong model equally well. + +The audit found no LIVE over-strong assertion (§A is the proof: the boolean core +is exactly equivalent, in both directions). It found four places where the gate +ASSERTED a property of the chip that nothing read. Those are now fixed, and this +file is the **regression suite for the fixes**: every section re-runs the tamper +that used to pass and requires the detector to fire. + + A brute-force equivalence of `Ecdas2Row` with an INDEPENDENT second + transcription of `Ecdas2Constraints::eval` idx 0..=27 (all 2^11 cases, + both directions). + B F4 — N4b re-pointed at the rows where idx 14 is actually load-bearing. + C F3 — the PORT lemma now covers the `s_i` prologue, `conv_carry`, and the + ECSM/ECSM2 membership pair. + D F2 — `chip_state()` parses the emitted expression, and enforces + "gated columns == raw bus multiplicities" in both directions. + E F1 — the D_INV gate expression is parsed and cross-checked against the + Addend receive, with the forgery a narrowed gate would hide. + F the `JointSel → PH*/S*` derivation is compared arm for arm. + G fail-closed behaviour: an unrecognised chip shape reports ABSENT. + +No `.rs` file is modified — every tamper is applied to an in-memory copy. + +Run: /bin/python audit_transcription.py (z3; §E's construction needs ../oracle) +""" + +import itertools +import sys +from pathlib import Path + +import z3 + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE)) +sys.path.insert(0, str(HERE.parent / "oracle")) + +import gate2_common as gc +from gate2_common import ( + ECDAS2, ECSM2, Ecdas2Row, chip_state, dinv_gate_state, joint_sel_maps, + membership_bodies_identical, padding_gate_state, relation_bodies_identical, +) + +ECDAS2_SRC = ECDAS2.read_text() +ECSM2_SRC = ECSM2.read_text() +verdicts = [] + + +def hdr(t): + print() + print("=" * 78) + print(t) + print("=" * 78) + + +def check(name, ok, note=""): + verdicts.append((name, ok)) + print(f" [{'PASS' if ok else 'FAIL':^6}] {name}") + for line in note.splitlines(): + if line: + print(f" {line}") + + +def _with_ecdas2(src, fn): + """Run `fn()` with `gate2_common.ECDAS2` pointing at a tampered copy.""" + tmp = Path("/tmp/_audit_ecdas2.rs") + tmp.write_text(src) + orig, gc.ECDAS2 = gc.ECDAS2, tmp + try: + return fn() + finally: + gc.ECDAS2 = orig + + +def _with_ecsm2(src, fn): + tmp = Path("/tmp/_audit_ecsm2.rs") + tmp.write_text(src) + orig, gc.ECSM2 = gc.ECSM2, tmp + try: + return fn() + finally: + gc.ECSM2 = orig + + +def _replace_once(src, old, new, what): + assert old in src, f"tamper target not found verbatim: {what}" + out = src.replace(old, new, 1) + assert out != src + return out + + +# ── A. the schedule block, both directions ────────────────────────────────── + +NAMES = ("mu", "op", "nb", "d1", "d2", "s1", "s2", "s3", "sc", "ph1", "ph2") + + +def chip_admits(vals, with_2227=True): + """SECOND, independent transcription of ecdas2.rs::eval idx 0..=27.""" + mu, op, nb, d1, d2, s1, s2, s3, sc, ph1, ph2 = vals + c = [x * (1 - x) for x in vals] # 0..=10 + c += [ + ph1 * ph2, # 11 + op * nb, # 12 + (1 - op) * (nb - d1 - d2 + d1 * d2), # 13 + op - s1 - s2 - s3 - sc, # 14 + (1 - ph1) * d1, # 15 + (1 - ph1) * d2, # 16 + ph1 * sc, # 17 + ph1 * (s1 + s3 - op * d1), # 18 + ph1 * (s2 + s3 - op * d2), # 19 + mu * (1 - ph1 - ph2) * (s2 - 1), # 20 + ph2 * (sc - 1), # 21 + ] + if with_2227: + c += [(1 - mu) * x for x in (d1, d2, s1, s2, s3, sc)] # 22..=27 + return all(v == 0 for v in c) + + +def model_admits(vals, padding_gate, ablate=()): + s = z3.Solver() + r = Ecdas2Row(s, "x", ablate=ablate, padding_gate=padding_gate) + for n, v in zip(NAMES, vals): + s.add(getattr(r, n) == v) + return s.check() == z3.sat + + +def section_a(): + hdr("A — Ecdas2Row vs an independent transcription of idx 0..=27 (2^11 cases)") + space = list(itertools.product((0, 1), repeat=11)) + m = {v for v in space if model_admits(v, True)} + ch = {v for v in space if chip_admits(v, True)} + stronger, weaker = ch - m, m - ch + print(f" model {len(m)} / chip {len(ch)} admitted assignments") + check("model ⊆ chip (no over-strong boolean constraint)", not stronger, + "" if not stronger else f"chip admits, model rejects: {sorted(stronger)}") + check("chip ⊆ model (no omitted boolean constraint)", not weaker, + "" if not weaker else f"model admits, chip rejects: {sorted(weaker)}") + + m0 = {v for v in space if model_admits(v, False)} + check("`padding_gate` defaults to the chip (True), not to a weaker model", + Ecdas2Row.__init__.__defaults__[-1] is True, + f"padding_gate=False still models the pre-fix chip ({len(m0)} " + f"assignments vs {len(ch)}) — ablations must now opt in explicitly.") + + +# ── B. F4: where idx 14 is actually load-bearing ──────────────────────────── + +def section_b(): + hdr("B — F4: where `OP = ΣS` (idx 14) is actually load-bearing") + + def q(ablate, mu, extra, padding_gate=True): + s = z3.Solver() + r = Ecdas2Row(s, "r", ablate=ablate, padding_gate=padding_gate) + s.add(r.mu == mu) + extra(s, r) + s.add(r.op == 0, r.addend_receive() > 0) + return s.check() + + pad = lambda s, r: s.add(r.ph1 == 0, r.ph2 == 0) + old_model = q((14,), 0, pad, padding_gate=False) + real_chip = q((14,), 0, pad, padding_gate=True) + check("the OLD N4b target (MU=0 padding row) is NOT a forgery on the chip", + old_model == z3.sat and real_chip == z3.unsat, + f"padding_gate=False (as N4b used to run): {old_model}\n" + f"padding_gate=True (the chip as written): {real_chip}\n" + "idx 24..=27 zero every selector on a MU=0 row regardless of idx 14.") + + live = { + "precompute (MU=1, PH1=PH2=0)": lambda s, r: s.add(r.ph1 == 0, r.ph2 == 0), + "correction (MU=1, PH2=1)": lambda s, r: s.add(r.ph2 == 1), + } + ok, lines = True, [] + for name, extra in live.items(): + b, a = q((), 1, extra), q((14,), 1, extra) + lines.append(f"{name:30} untampered {b} ablate-14 {a}") + ok &= (b == z3.unsat and a == z3.sat) + check("the NEW N4b target (live PH1=0 phases) IS a forgery", ok, + "\n".join(lines) + "\nidx 14 stays — the conclusion survives; only the " + "justification was wrong.") + + +# ── C. F3: what the PORT lemma covers ─────────────────────────────────────── + +def section_c(): + hdr("C — F3: the PORT lemma now covers the prologue, conv_carry, and ECSM2") + + base = relation_bodies_identical() + check("untampered ECDAS/ECDAS2 port is clean", all(base.values()), + " ".join(base)) + + mem = membership_bodies_identical() + check("untampered ECSM/ECSM2 membership port is clean", all(mem.values()), + " ".join(mem) + + "\nThis pair was never compared before; the soundness theorem's " + '"P2 is on the curve" clause depends on it.') + + # TAMPER 1: rebind an operand column in the s_i prologue. + t = _replace_once( + ECDAS2_SRC, + "let xa = |j: usize| Self::byte_at(b, cols::XA, 32, j);", + "let xa = |j: usize| Self::byte_at(b, cols::XR, 32, j);", + "s_i prologue xa binding") + res = _with_ecdas2(t, relation_bodies_identical) + check("a rebound operand column (xa → cols::XR) is DETECTED", + not all(res.values()), + f"flagged: {sorted(k for k, v in res.items() if not v)}\n" + "Every value lemma (L3a, L4a/b/c) is false on that chip. This tamper " + "used to report all-identical.") + + # TAMPER 2: break the carry recurrence itself. + t = _replace_once( + ECDAS2_SRC, + "two_pow_8 * c_i - c_prev - Self::s_i(b, relation, i)", + "two_pow_8 * c_i - Self::s_i(b, relation, i)", + "conv_carry recurrence") + res = _with_ecdas2(t, relation_bodies_identical) + check("a broken carry recurrence (dropped c_prev) is DETECTED", + not res["conv_carry"], + "L1's telescoping IS this recurrence; conv_carry was never compared " + "before.") + + # TAMPER 3: drop the curve constant from ECSM2's membership relation. + t = _replace_once( + ECSM2_SRC, "s = s - ok * curve_b;", "s = s - ok * ok;", + "ECSM2 Yg curve constant") + res = _with_ecsm2(t, membership_bodies_identical) + check("a tampered ECSM2 membership relation is DETECTED", + not all(res.values()), + f"flagged: {sorted(k for k, v in res.items() if not v)}\n" + "Without `b` the y² relation no longer pins P2 to the curve.") + + +# ── D. F2: the padding gate, parsed and matched to the multiplicities ─────── + +def section_d(): + hdr("D — F2: the padding gate is parsed, and matched against the multiplicities") + + pad = padding_gate_state() + check("untampered: gate present, and gated set == raw multiplicity set", + pad["present"] and pad["exact"], + f"gated {sorted(pad['gated'])}\n" + f"raw multiplicities {sorted(pad['raw_multiplicity'])}\n" + f"unparsed {pad['unresolved_multiplicities']}") + + # TAMPER 1: delete the emitting loop, keep every comment. + start = ECDAS2_SRC.index(" for (i, col) in [\n cols::D1,") + end = ECDAS2_SRC.index("b.emit_base(22 + i, (one - mu) * x);", start) + loop = ECDAS2_SRC[start:end + len("b.emit_base(22 + i, (one - mu) * x);")] \ + + "\n }\n" + t = _replace_once(ECDAS2_SRC, loop, " // defence removed\n", + "idx 22..=27 emitting loop") + assert "emit_base(22 + i" not in t + assert "(1 − MU)·{D1" in t, "the header comment must survive this tamper" + st = padding_gate_state(t) + check("deleting the defence while KEEPING its comment is DETECTED", + not st["present"], + f"reason: {st['reason']}\n" + "The old detector matched the comment, so this reported the defence " + "present and scored N1 as a passing ablation.") + + # TAMPER 2: the original JointBit bug's shape — digits escape the gate. + t = _replace_once( + ECDAS2_SRC, + " for (i, col) in [\n cols::D1,\n cols::D2,\n", + " for (i, col) in [\n", + "gate column list") + st = padding_gate_state(t) + check("a digit send escaping the gate is DETECTED (the original bug's shape)", + st["present"] and not st["exact"] + and st["ungated_multiplicities"] == {"D1", "D2"}, + f"gated {sorted(st['gated'])}\n" + f"UNGATED MULTIPLICITY: {sorted(st['ungated_multiplicities'])}") + + # TAMPER 3: a NEW ungated multiplicity appears on a bus. + t = _replace_once(ECDAS2_SRC, + " Multiplicity::Column(col),", + " Multiplicity::Column(cols::NB),", + "JointBit send multiplicity") + st = padding_gate_state(t) + check("a NEW ungated multiplicity column (NB) is DETECTED", + "NB" in st["ungated_multiplicities"], + f"UNGATED MULTIPLICITY: {sorted(st['ungated_multiplicities'])}\n" + "The invariant is an EQUALITY, so it fires on a new raw multiplicity " + "as well as on a deleted gate. That is the direction the original " + "JointBit bug arrived from.") + + # TAMPER 4: the Dinv block is never emitted. + t = _replace_once(ECDAS2_SRC, " (Relation::Dinv, cols::C3),\n", "", + "Dinv emit-loop entry") + st = dinv_gate_state(t) + check("dropping Dinv from the emit loop is DETECTED", not st["present"], + f"reason: {st['reason']}\n" + 'The old detector was `"D_INV" in src and "Dinv" in src`, which ' + "survives this untouched.") + + +# ── E. F1: the D_INV gate expression, and the forgery it hides ────────────── + +def section_e(): + hdr("E — F1: the D_INV gate is parsed and matched to the Addend receive") + + st = dinv_gate_state() + check("untampered: gate expression == Addend receive multiplicity", + st["present"] and st["matches_addend"], + f"gate {sorted(st['gate'])}\naddend {sorted(st['addend'])}\n" + f"applied as `g * s`: {st['applied']} emitted: {st['emitted']}") + + narrowed = _replace_once( + ECDAS2_SRC, + """ let g = b.main(0, cols::S1) + + b.main(0, cols::S2) + + b.main(0, cols::S3) + + b.main(0, cols::S_CORR);""", + """ let g = b.main(0, cols::S1) + + b.main(0, cols::S2) + + b.main(0, cols::S3);""", + "Dinv gate expression") + st_n = _with_ecdas2(narrowed, lambda: chip_state()["dinv_gate_detail"]) + port_n = _with_ecdas2(narrowed, relation_bodies_identical) + check("dropping S_CORR from the gate is DETECTED", not st_n["present"], + f"reason: {st_n['reason']}\n" + f"gate {sorted(st_n['gate'])} vs addend {sorted(st_n['addend'])}\n" + f"(the PORT check still reports all-identical: {all(port_n.values())} " + "— it excludes the Dinv arm by design, which is exactly why the gate " + "needed an invariant of its own.)") + + # the forgery that tamper hides, constructed + try: + from ec_ref import GX, GY, P, pt_add, pt_double + import lincomb2_ref + except Exception as e: + print(f" (construction skipped: {e})") + return + + T0, _ = lincomb2_ref.t0_ref() + G = (GX, GY) + neg = lambda pt: (pt[0], (P - pt[1]) % P) + + # acc = 2^len·T0 + u1·G + u2·P2 ; W = −2^len·T0. Degenerate ⟺ acc == W + # ⟺ u1·G + u2·P2 = −2^(len+1)·T0. Take u1 = u2 = 1 (len = 1). + u1 = u2 = 1 + length = max(u1.bit_length(), u2.bit_length()) + t = T0 + for _ in range(length + 1): + t = pt_double(t) + P2 = pt_add(neg(t), neg(G)) + + acc = T0 + for rr in range(length - 1, -1, -1): + acc = pt_double(acc) + e1, e2 = (u1 >> rr) & 1, (u2 >> rr) & 1 + if e1 or e2: + acc = pt_add(acc, pt_add(G, P2) if (e1 and e2) else (G if e1 else P2)) + tpow = T0 + for _ in range(length): + tpow = pt_double(tpow) + W = neg(tpow) + + lam_rel = lambda lam: (lam * (W[0] - acc[0]) + acc[1] - W[1]) % P + degenerate = acc == W and lam_rel(12345) == 0 and lam_rel(67890) == 0 + + def step(lam): + xr = (lam * lam - 2 * acc[0]) % P + return xr, (lam * (acc[0] - xr) - acc[1]) % P + + honest = pt_double(acc) + forged = {step(l) for l in (2, 3, 5, 7, 11)} + + d = z3.Int("d") + s = z3.Solver() + s.add(d >= 0, d < P, (d * ((W[0] - acc[0]) % P) - 1) % P == 0) + blocked = s.check() == z3.unsat + + print() + print(" THE FORGERY (no discrete log — one point subtraction):") + print(f" u1 = u2 = 1, len = {length}, P2 = -2^(len+1)*T0 - G") + print(f" P2 = ({P2[0]:#x},") + print(f" {P2[1]:#x})") + print(f" correction row: xA == xB {acc[0] == W[0]}, " + f"yA == yB {acc[1] == W[1]}") + print(f" lambda relation identically 0 (free lambda): {degenerate}") + print(f" honest Q = ({honest[0]:#x}, ...)") + print(f" forged Q' family: {len(forged)} distinct, none honest: " + f"{honest not in forged}") + check("with the real gate, the forged correction row is UNSATISFIABLE", + degenerate and blocked, + "d·(xB − xA) = 1 with xB = xA has no solution — the chip as written " + "blocks it.") + + +# ── F. the JointSel → PH*/S* derivation ───────────────────────────────────── + +def section_f(): + hdr("F — the `JointSel → phase_bits/selector_bits` mapping, arm for arm") + import positive_real_witness2 as anchor + + rows = anchor.check_sel_maps() + check("the anchor's hand copy matches the chip's `match` arms", + all(ok for _, ok, _ in rows), + "\n".join(f"{n:18}: {'MATCHES' if ok else 'DIFFERS'} {note}" + for n, ok, note in rows)) + + chip = joint_sel_maps() + tampered = _replace_once(ECDAS2_SRC, "JointSel::Correction => (0, 1),", + "JointSel::Correction => (1, 1),", "phase_bits arm") + got = _with_ecdas2(tampered, lambda: joint_sel_maps()["phase_bits"]) + check("a changed phase_bits arm is DETECTED", + got != chip["phase_bits"] and got["Correction"] == (1, 1), + f"chip now maps Correction → {got['Correction']} while the anchor's " + "dict still says (0, 1), so `check_sel_maps` fails.\n" + "RESULTS §7 called this the anchor's last modelled step; it is now " + "machine-checked.") + + +# ── G. fail-closed ────────────────────────────────────────────────────────── + +def section_g(): + hdr("G — the detectors fail CLOSED on an unrecognised chip shape") + + t = _replace_once(ECDAS2_SRC, "b.emit_base(22 + i, (one - mu) * x);", + "b.emit_base(22 + i, gate_helper(b, col));", + "idx 22..=27 emission") + st = padding_gate_state(t) + check("an unparsed gate shape reports ABSENT, not present", not st["present"], + f"reason: {st['reason']}\n" + "A detector that guesses 'probably fine' is the failure mode this " + "file exists to prevent.") + + t = _replace_once(ECDAS2_SRC, " let g = b.main(0, cols::S1)", + " let g = gate_expr(b)\n" + " * b.main(0, cols::S1)", "Dinv gate") + st = dinv_gate_state(t) + check("an opaque D_INV gate helper is not silently accepted", + not st["present"] or not st["matches_addend"], + f"present={st['present']} reason: {st['reason']}\n" + f"parsed gate columns {sorted(st['gate'])}") + + +def main(): + section_a() + section_b() + section_c() + section_d() + section_e() + section_f() + section_g() + + hdr("SUMMARY") + for name, ok in verdicts: + print(f" [{'PASS' if ok else 'FAIL':^6}] {name}") + bad = [n for n, ok in verdicts if not ok] + print() + print(f" {len(verdicts) - len(bad)}/{len(verdicts)} checks pass") + if bad: + print(" FAILED:") + for n in bad: + print(f" - {n}") + return 1 if bad else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/gate/c9_constants_probe.py b/thoughts/ec-recover-opt/gate/c9_constants_probe.py new file mode 100644 index 000000000..eef270acd --- /dev/null +++ b/thoughts/ec-recover-opt/gate/c9_constants_probe.py @@ -0,0 +1,353 @@ +"""C9 probe — the joint chain's compile-time curve constants are load-bearing, +and NOTHING in the constraint system checks them. + +The lincomb2 soundness theorem (`RESULTS-lincomb2.md` §5) claims to rest on +"contracts C1-C7 + A-PRIME (unchanged from RESULTS.md)" and "plus nothing else". +This script shows that claim is false: the joint chain also depends on two +classes of compile-time constant that the single-scalar chips never had, and one +of those classes is bound by NO in-proof mechanism at all. + + G (`GENERATOR_LE`, ecsm2.rs:614-628) ANCHORED — the P1 read is a + MEMW access, so the constant is checked against what the guest wrote + at `a1`. A wrong G cannot forge; it can only make an honest run + unprovable (or, via the executor's status 7, take the fallback). + + T0 (`T0_X_LE`/`T0_Y_LE`, ecsm2.rs:869-870) UNANCHORED + EC_T0 (256 rows of -2^(j+1)*T0, ec_t0.rs:131-153) UNANCHORED + Nothing outside the AIR ever sees these. They enter the proof as an + AIR constant and a preprocessed commitment the verifier compiles in. + If the generator that produced them is wrong, every constraint and + every bus still balances and the chip returns a WRONG Q. + +Two constructions, both plausible generator bugs the source itself warns about: + + A. SIGN FLIP — the table stores +2^len*T0 instead of -2^len*T0. `ec_t0.rs` + lines 16-41 and `lincomb2_table.rs` lines 10-22 both carry a warning that + `Lincomb2Witness::x_t0_pow`/`y_t0_pow` hold the OPPOSITE convention and + that "reading y_t0_pow where you meant Y is a silent sign flip that still + type-checks". + + B. OFF-BY-ONE — the table row for `len` stores -2^(len+1)*T0, i.e. the + `points[idx + MIN_LEN]` index arithmetic at ec_t0.rs:143 is off by one. + +For each, the script rebuilds the full joint chain, re-derives the correction +row from the tampered addend by the group law, and then CHECKS, rather than +asserts, that: + + * every one of the four ECDAS2 convolution relations holds mod p on every row + (Lambda / Xr / Yr / Dinv — the value-level content of idx 28..=287); + * every ECDAS2 schedule constraint idx 11..=27 holds on every row; + * every ECSM2 range/selector constraint that reads a tampered value holds; + * all five buses balance: Ecdas (chain telescoping), Addend, JointBit, EcT0 + (against the TAMPERED table, which is the point), and the MEMW result write; + * and Q' != Q, with Q' a canonical on-curve point the guest will happily hash. + +Run: python3 thoughts/ec-recover-opt/gate/c9_constants_probe.py +""" + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "oracle")) + +from ec_ref import P, N, GX, GY, pt_add, pt_double, pt_neg, scalar_mul # noqa: E402 +from lincomb2_ref import lincomb2, lincomb2_rows, t0_ref # noqa: E402 + +G = (GX, GY) + +# Row-role -> (PH1, PH2) and (S1, S2, S3, S_CORR), transcribed from +# `Ecdas2Operation::phase_bits` / `selector_bits` (ecdas2.rs:256-277). +PHASE_BITS = { + "Precompute": (0, 0), + "Correction": (0, 1), + "Double": (1, 0), + "AddP1": (1, 0), + "AddP2": (1, 0), + "AddP12": (1, 0), +} +SEL_BITS = { + "Double": (0, 0, 0, 0), + "AddP1": (1, 0, 0, 0), + "AddP2": (0, 1, 0, 0), + "Precompute": (0, 1, 0, 0), + "AddP12": (0, 0, 1, 0), + "Correction": (0, 0, 0, 1), +} +# Addend-bus `sel` values (ecsm2.rs:111-114). +SEL_VALUE = {"AddP1": 1, "AddP2": 2, "Precompute": 2, "AddP12": 3, "Correction": 4} + + +def finv(a): + return pow(a % P, P - 2, P) + + +# ── the four ECDAS2 relations, at value level (mod p) ──────────────────────── +# +# The chip states each as a byte convolution with a quotient absorbing the +# integer offset; gate lemmas L1 + L3a say the convolution is exactly the +# mod-p identity below. Transcribed from `Ecdas2Constraints::s_i` +# (ecdas2.rs:742-817). + +def relations_hold(row, ph1, ph2, sel_bits): + xa, ya = row["a"] + xb, yb = row["addend"] + xr, yr = row["r"] + lam = row["lam"] + op = row["op"] + g = sum(sel_bits) # S1 + S2 + S3 + S_CORR, the Dinv gate + out = {} + + out["Lambda"] = ( + op * (lam * (xb - xa) + ya - yb) + (1 - op) * (2 * lam * ya - 3 * xa * xa) + ) % P == 0 + out["Xr"] = (lam * lam - xa - xb - xr - (1 - op) * (xa - xb)) % P == 0 + out["Yr"] = (lam * (xa - xr) - ya - yr) % P == 0 + if g: + # D_INV exists iff xB != xA mod p; the chip witnesses it. + d_ok = (xb - xa) % P != 0 + out["Dinv"] = d_ok and (finv(xb - xa) * (xb - xa) - 1) % P == 0 + else: + out["Dinv"] = True # gated off; q3 is pinned to 3p (L5b' sub-lemma c) + return out + + +def schedule_holds(row, ph1, ph2, sel_bits, mu=1): + s1, s2, s3, sc = sel_bits + op, nb, d1, d2 = row["op"], row["nb"], row["d1"], row["d2"] + checks = { + "11 PH1*PH2": ph1 * ph2, + "12 OP*NB": op * nb, + "13 (1-OP)(NB-D1-D2+D1D2)": (1 - op) * (nb - d1 - d2 + d1 * d2), + "14 OP-SumS": op - s1 - s2 - s3 - sc, + "15 (1-PH1)D1": (1 - ph1) * d1, + "16 (1-PH1)D2": (1 - ph1) * d2, + "17 PH1*S_CORR": ph1 * sc, + "18 PH1(S1+S3-OP*D1)": ph1 * (s1 + s3 - op * d1), + "19 PH1(S2+S3-OP*D2)": ph1 * (s2 + s3 - op * d2), + "20 MU(1-PH1-PH2)(S2-1)": mu * (1 - ph1 - ph2) * (s2 - 1), + "21 PH2(S_CORR-1)": ph2 * (sc - 1), + } + for i, col in enumerate([d1, d2, s1, s2, s3, sc]): + checks[f"{22 + i} (1-MU)*col"] = (1 - mu) * col + return {k: v == 0 for k, v in checks.items()} + + +def canonical_bytes(pt): + """Every coordinate is a canonical field element, so its 32 limbs are + genuine bytes: the AreBytes contract (C1) and the `< p` overflow witnesses + (X_Q_SUB_P / Y_Q_SUB_P) are satisfiable.""" + return 0 <= pt[0] < P and 0 <= pt[1] < P + + +# ── whole-chain checker ───────────────────────────────────────────────────── + +def check_chain(rows, u1, u2, length, table_entry, p2, verbose=False): + """Returns (ok, report). `table_entry` is what the EC_T0 table publishes for + this `len` — i.e. what the correction row's addend is bound to.""" + report = [] + ok = True + + def fail(msg): + nonlocal ok + ok = False + report.append(" FAIL " + msg) + + # 1. per-row constraints + for i, row in enumerate(rows): + ph1, ph2 = PHASE_BITS[row["sel"]] + sel_bits = SEL_BITS[row["sel"]] + for name, good in relations_hold(row, ph1, ph2, sel_bits).items(): + if not good: + fail(f"row {i} ({row['sel']}): relation {name}") + for name, good in schedule_holds(row, ph1, ph2, sel_bits).items(): + if not good: + fail(f"row {i} ({row['sel']}): constraint idx {name}") + for pt in (row["a"], row["r"]): + if not canonical_bytes(pt): + fail(f"row {i}: non-canonical coordinate") + if row["sel"] != "Double" and not canonical_bytes(row["addend"]): + fail(f"row {i}: non-canonical addend") + report.append(f" per-row: {len(rows)} rows x (4 relations + 17 schedule) OK") + + # 2. Ecdas bus — the three segments telescope, seeds/drains pin both ends + phases = {"Precompute": 0, "Correction": 2} + seg = {0: [], 1: [], 2: []} + for row in rows: + seg[phases.get(row["sel"], 1)].append(row) + seeds = { + 0: (G, 0, 1), # a = P1 = G, round 0, op = add + 1: (T0, length - 1, 0), # a = T0, round len-1, op = double + 2: (seg[1][-1]["r"], 0, 1), # a = phase-1 drain (relayed by ECSM2) + } + drains = {} + for ph in (0, 1, 2): + acc, rnd, op = seeds[ph] + for row in seg[ph]: + if row["a"] != acc or row["round"] != rnd or row["op"] != op: + fail(f"phase {ph}: chain tuple mismatch at round {rnd}") + break + acc, rnd, op = row["r"], row["round"] - 1 + row["nb"], row["nb"] + else: + if rnd != -1 or op != 0: + fail(f"phase {ph}: drain tuple is (round={rnd}, op={op}), want (-1, 0)") + drains[ph] = acc + report.append(" Ecdas bus: 3 segments telescope seed -> drain, round hits -1") + + # 3. JointBit bus — per (round, stream) the receive is 2*bit, senders are + # the rows carrying that digit. + for stream, u in ((1, u1), (2, u2)): + for i in range(256): + sends = sum(r["d1" if stream == 1 else "d2"] for r in rows if r["round"] == i) + if sends != 2 * ((u >> i) & 1): + fail(f"JointBit[{i}, stream {stream}]: {sends} sends vs {2 * ((u >> i) & 1)}") + report.append(" JointBit bus: 512 receives at 2*bit, balanced by the digit sends") + + # 4. Addend bus — ECSM2's N1/N2/N3 are free columns pinned by balance, so + # any consistent count balances; the VALUES are what matters. + published = {1: G, 2: p2, 3: pt_add(G, p2), 4: table_entry} + counts = {1: 0, 2: 0, 3: 0, 4: 0} + for row in rows: + if row["sel"] == "Double": + continue + s = SEL_VALUE[row["sel"]] + counts[s] += 1 + if row["addend"] != published[s]: + fail(f"Addend[sel={s}]: row addend != published value") + if counts[4] != 1: + fail(f"Addend[sel=4]: {counts[4]} correction receives, must be exactly 1 (mult = OK)") + report.append( + f" Addend bus: N1={counts[1]} N2={counts[2]} N3={counts[3]}, " + "correction receive = 1 = OK" + ) + + # 5. EcT0 bus — the send is [len, x, y]; the table receives. This is the + # ONLY thing that binds the correction addend, and it binds it to the + # TABLE, whatever the table contains. + if rows[-1]["addend"] != table_entry: + fail("EcT0: correction addend != table row") + report.append(f" EcT0 bus: send key len={length} matches the table row it looks up") + + q_chain = drains.get(2) + return ok, report, q_chain + + +# ── scenarios ─────────────────────────────────────────────────────────────── + +def rebuild_correction(rows, new_addend): + """Replace the correction row's addend and re-derive lambda/xR/yR by the + group law, exactly as the witness generator would for that addend.""" + rows = [dict(r) for r in rows] + corr = rows[-1] + assert corr["sel"] == "Correction" + xa, ya = corr["a"] + xb, yb = new_addend + assert (xb - xa) % P != 0, "chosen tamper hits the degenerate edge; pick another instance" + lam = ((yb - ya) * finv(xb - xa)) % P + xr = (lam * lam - xa - xb) % P + yr = (lam * (xa - xr) - ya) % P + corr["addend"] = (xb, yb) + corr["lam"] = lam + corr["r"] = (xr, yr) + return rows, (xr, yr) + + +def two_pow(k, pt): + for _ in range(k): + pt = pt_double(pt) + return pt + + +def main(): + global T0 + T0, counter = t0_ref() + print("=" * 78) + print("C9 PROBE — compile-time curve constants of the joint chain") + print("=" * 78) + print(f"T0 (NUMS, tag counter {counter}) = ({hex(T0[0])[:18]}..., {hex(T0[1])[:18]}...)") + assert (T0[1] * T0[1] - T0[0] ** 3 - 7) % P == 0, "T0 off curve" + + # A concrete instance. Any (u1, u2, P2) works; these keep the chain short + # enough to print. + u1 = 0xB3D5_7A1E + u2 = 0x4F2C_9E07 + p2 = scalar_mul(7, G) + q_true = lincomb2(u1, G, u2, p2) + rows, length, _ = (None, None, None) + q_ref, length, rows = lincomb2_rows(u1, G, u2, p2, T0) + assert q_ref == q_true + print(f"instance: u1={hex(u1)} u2={hex(u2)} P2=7*G len={length} rows={len(rows)}") + + honest_entry = pt_neg(two_pow(length, T0)) + ok, report, q_chain = check_chain(rows, u1, u2, length, honest_entry, p2) + print("\n[baseline] honest EC_T0 table") + for line in report: + print(line) + print(f" chain drains Q = {'MATCHES' if q_chain == q_true else 'DIFFERS FROM'} u1*G + u2*P2") + baseline_ok = ok and q_chain == q_true + print(f" => {'ACCEPTED, correct' if baseline_ok else 'BROKEN — probe bug'}") + assert baseline_ok, "baseline must pass, else the probe models the chip wrongly" + + scenarios = [ + ( + "A. SIGN FLIP (table stores +2^len*T0; ec_t0.rs:28-41 warns about exactly this)", + two_pow(length, T0), + ), + ( + "B. OFF-BY-ONE (table row for len holds -2^(len+1)*T0; ec_t0.rs:143 index)", + pt_neg(two_pow(length + 1, T0)), + ), + ] + + forged = 0 + for title, tampered_entry in scenarios: + print(f"\n[tamper] {title}") + t_rows, q_forged = rebuild_correction(rows, tampered_entry) + ok, report, q_chain = check_chain(t_rows, u1, u2, length, tampered_entry, p2) + for line in report: + print(line) + differs = q_chain != q_true + on_curve = (q_chain[1] ** 2 - q_chain[0] ** 3 - 7) % P == 0 + print(f" Q_chain != Q_true : {differs}") + print(f" Q_chain is a canonical point : {on_curve and canonical_bytes(q_chain)}") + print(f" Q_true x = {hex(q_true[0])}") + print(f" Q_chain x = {hex(q_chain[0])}") + if ok and differs and on_curve: + forged += 1 + print(" => ACCEPTED with a WRONG Q. Every constraint and every bus is") + print(" satisfied; the only thing that would have caught it is the") + print(" correctness of the preprocessed EC_T0 table itself.") + else: + print(" => not a forgery (constraints caught it)") + + # The contrast: G is anchored to guest memory, so a wrong G cannot forge. + print("\n[contrast] wrong GENERATOR_LE — anchored, therefore NOT a forgery") + print(" ecsm2.rs:612-629 reads P1 as 8 MEMW doublewords with CONSTANT values.") + print(" The tuple must match the memory token the guest wrote at a1, so a") + print(" GENERATOR_LE != G makes the Memw bus unbalance: rejection, not forgery.") + print(" (Executor-side it returns status 7 -> software fallback -> correct.)") + print(" T0 and the EC_T0 rows have NO such anchor: no guest write, no executor") + print(" read, no in-circuit curve check. They are pure AIR constants.") + + print("\n" + "=" * 78) + print(f"RESULT: {forged}/2 tampered constant sets produce an accepted, wrong Q.") + print("The joint chain therefore rests on a contract the board does not name:") + print(" C9 the compile-time EC constants (T0, and the 256 EC_T0 rows bound by") + print(" the verifier's compiled-in preprocessed commitment) are the") + print(" intended, on-curve, mutually consistent values.") + print("Discharged today by TESTS + a static commitment, never by a constraint:") + print(" crypto/ecsm/src/tests/lincomb2_tests.rs::t0_is_on_curve_and_pinned") + print(" crypto/ecsm/src/tests/lincomb2_tests.rs::t0_derivation_matches") + print(" prover/src/tests/ec_t0_tests.rs::every_entry_is_on_curve_and_canonical") + print(" prover/src/tests/ec_t0_tests.rs::trace_rows_recompute_from_t0_by_doubling") + print(" prover/src/tests/ec_t0_tests.rs::table_matches_lincomb2_witness_correction_row") + print(" prover/src/tests/ec_t0_tests.rs::commitment_is_stable_and_matches_the_shipped_static_bytes") + print("Those tests are good and they close BOTH constructions above. The finding") + print("is not that the constants are wrong — it is that the board's contract list") + print("does not say they are load-bearing, so nothing tells a future reader that") + print("those tests are part of the soundness argument rather than hygiene.") + print("=" * 78) + return 0 if forged == 2 else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/gate/gate2_common.py b/thoughts/ec-recover-opt/gate/gate2_common.py new file mode 100644 index 000000000..d77fe9a13 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/gate2_common.py @@ -0,0 +1,655 @@ +"""Shared model for the lincomb2 (ECSM2/ECDAS2) z3 gate — phase E. + +Layered on `gate_common.py`: the three convolution relations are BYTE-FOR-BYTE +the old chip's (proved mechanically by `relation_bodies_identical()` below), so +the S_i builders, interval machinery and constants are imported rather than +re-transcribed. What is new here is the SCHEDULE model — phases, selectors, +digit streams — and the chip-state detector. + +## Why there is a chip-state detector + +Two soundness fixes were outstanding when this gate was first written — the +padding-row digit gate and the non-degeneracy relation. **Both have since +landed** (`ecdas2.rs` idx 22..=27 and the `Relation::Dinv` block). The detector +stays, because its job was never "report the state on the day this was written": +it is what stops a negative control from being scored as a passing *ablation* +when the defence it ablates is actually missing. A gate whose controls go SAT +for the real reason, and record it as an expected result, is worse than no gate. + +## What the detector must NOT be + +`TRANSCRIPTION-AUDIT.md` F1/F2 documented the failure mode this file used to +have: every predicate was a *token or comment* match. Deleting the emitting loop +while leaving its header comment still reported the defence present; narrowing +the `D_INV` gate by one term — which yields a working forgery on the correction +row — changed no verdict anywhere on the board. + +So every predicate here is now parsed from the **emitted expression** or the +**multiplicity expression**, and every parser **fails closed**: an unrecognised +shape reports the defence ABSENT with a reason, never present. Two structural +invariants are checked in both directions: + + * `padding_gate_state()` — the set of columns carrying `(1 − MU)·X = 0` must + EQUAL the set of columns supplying a multiplicity in + `ecdas2::bus_interactions()`. This is the invariant the chip header claims + ("which column supplies its multiplicity, and what forces that column to + zero?"), and it catches a *new ungated multiplicity* — the original JointBit + bug — from the side that bug actually appeared on. + * `dinv_gate_state()` — the `Relation::Dinv` arm's gate expression must be + exactly the term list of the `Addend` receive's `Multiplicity::Linear`. + That is what `RESULTS-lincomb2.md` §2 asserts in prose ("it ties the check + to the very expression that counts the Addend receive"). + +Column indices are deliberately NOT hardcoded anywhere that matters: the model +is written against constraint identities and bus multiplicities. +""" + +import re +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) + +from gate_common import ( # noqa: F401 (re-exported for the phase-E scripts) + B, BIT, BYTE, GEN_X, GEN_Y, Iv, N, OFF, P, PG, P_BYTES, R3P, R_BYTES, + compose, decompose, s_ecdas_lambda, s_ecdas_xr, s_ecdas_yr, +) + +REPO = Path(__file__).resolve().parents[3] +ECDAS2 = REPO / "prover/src/tables/ecdas2.rs" +ECSM2 = REPO / "prover/src/tables/ecsm2.rs" +ECDAS1 = REPO / "prover/src/tables/ecdas.rs" +ECSM1 = REPO / "prover/src/tables/ecsm.rs" + +# The four Addend-bus selectors (ecsm2.rs `SEL_*`). +SEL_P1, SEL_P2, SEL_P12, SEL_CORRECTION = 1, 2, 3, 4 + + +# ── source extraction primitives ──────────────────────────────────────────── + +def _match_from(s, i, opener="{", closer="}"): + """Brace/bracket-matched span starting at the first `opener` at or after i.""" + j = s.index(opener, i) + depth, k = 0, j + while True: + if s[k] == opener: + depth += 1 + elif s[k] == closer: + depth -= 1 + if depth == 0: + return j, k + k += 1 + + +def _fn_body_text(src, fn): + """The full text of `fn ` including its brace-matched body. + + Accepts both the generic (`fn s_i`) and plain (`fn bus_interactions()`) + declaration forms. + """ + for marker in (f"fn {fn} => { … }` arm of `fn`, brace-matched.""" + s = _fn_body_text(src, fn) + i = s.index(f"Relation::{variant} => {{") + j, k = _match_from(s, i) + return s[j:k + 1] + + +def _match_arm(path, variant): + return _match_arm_text(path.read_text(), variant) + + +def _prologue(src, fn="s_i"): + """The part of `fn` before its `match relation {` — the operand bindings. + + `TRANSCRIPTION-AUDIT.md` F3: rebinding an operand here (e.g. `xa` to + `cols::XR`) falsifies every value lemma while leaving all three arms + textually identical, so this must be compared too. + """ + body = _fn_body_text(src, fn) + return body[: body.index("match relation")] + + +def _strip_dinv_arm(t): + """Remove ECDAS2's extra `Relation::Dinv => cols::…,` dispatch line.""" + return re.sub(r"\s*Relation::Dinv\s*=>\s*cols::\w+,", "", t) + + +# ── mechanical port arguments ─────────────────────────────────────────────── + +def relation_bodies_identical(): + """L1/L2a/L3/L4/L5a port argument, checked rather than asserted. + + Every lemma of the original gate that speaks only about the three original + convolution relations transfers verbatim IF those relations are built by the + same expressions. Compared PER ARM, because ECDAS2 has since gained a fourth + relation (`Dinv`) — an additive block that cannot affect a lemma quantified + over the other three. + + Covers, since `TRANSCRIPTION-AUDIT.md` F3: + + * the three arms (as before); + * the `s_i` PROLOGUE, i.e. every operand → column binding. Without this + the check passes on a chip whose relations read the wrong columns; + * `conv_carry`, with ECDAS2's `Dinv` dispatch line excised — this is the + carry recurrence L1 telescopes; + * the four shared helpers, compared whole. + + Returns {name: bool}. + """ + src1, src2 = ECDAS1.read_text(), ECDAS2.read_text() + out = {} + for variant in ("Lambda", "Xr", "Yr"): + out[f"s_i::{variant}"] = (_norm(_match_arm_text(src1, variant)) + == _norm(_match_arm_text(src2, variant))) + out["s_i::prologue"] = _norm(_prologue(src1)) == _norm(_prologue(src2)) + out["conv_carry"] = (_norm(_fn_body_text(src1, "conv_carry")) + == _norm(_strip_dinv_arm(_fn_body_text(src2, "conv_carry")))) + for fn in ("rq", "p_byte_expr", "r_byte_expr", "byte_at"): + out[fn] = _norm(_fn_body_text(src1, fn)) == _norm(_fn_body_text(src2, fn)) + return out + + +# ECSM2's membership relations are ECSM's, modulo the column rename and the +# `µ → OK` gate swap. The soundness theorem's "P2 is on the curve" clause rests +# on this port, and nothing checked it (`TRANSCRIPTION-AUDIT.md`, gap 2). +_MEMBERSHIP_RENAME = ( + ("cols::MEM_X2", "cols::X2"), + ("cols::MEM_Q0", "cols::Q0"), + ("cols::MEM_Q1", "cols::Q1"), + ("cols::MEM_C0", "cols::C0"), + ("cols::MEM_C1", "cols::C1"), + ("cols::X_P2", "cols::XG"), + ("cols::Y_P2", "cols::YG"), + ("cols::OK", "cols::MU"), +) + + +def _norm_membership(t): + t = re.sub(r"//.*", "", t) + for a, b in _MEMBERSHIP_RENAME: + t = t.replace(a, b) + t = re.sub(r"\bok\b", "mu", t) # the local binding, after cols::OK + t = re.sub(r"\s+", " ", t) + return t.strip() + + +def membership_bodies_identical(): + """ECSM2's `Relation::X2`/`Yg` are ECSM's, modulo rename + `µ → OK`. + + The gate swap is not cosmetic — it is what lets an ECSM2 error row + (`MU = 1, OK = 0`) close at zero carries like a padding row — but it is + sound because `OK` is IS_BIT and `OK·(1 − MU) = 0` (`ecsm2.rs` idx 1, 2), so + `OK = 1` rows are a subset of `MU = 1` rows and every ECSM lemma applies to + them verbatim. + + `carry_chain` is deliberately NOT compared: ECSM2 has five `OverflowKind`s + to ECSM's three, so the bodies differ by design. Its five overflow checks + are covered by L8 N3 / N7 instead. + + Returns {name: bool}. + """ + src1, src2 = ECSM1.read_text(), ECSM2.read_text() + out = {} + for variant in ("X2", "Yg"): + out[f"s_i::{variant}"] = (_norm_membership(_match_arm_text(src1, variant)) + == _norm_membership(_match_arm_text(src2, variant))) + out["s_i::prologue"] = (_norm_membership(_prologue(src1)) + == _norm_membership(_prologue(src2))) + for fn in ("conv_carry", "p_byte_expr", "byte_at"): + out[fn] = (_norm_membership(_fn_body_text(src1, fn)) + == _norm_membership(_fn_body_text(src2, fn))) + return out + + +# ── multiplicity extraction (the F2 invariant) ────────────────────────────── + +_MULT_RE = re.compile(r"Multiplicity::(Column|Sum3|Sum|Diff|Negated|Linear)\s*\(") +_FOR_TUPLE_RE = re.compile(r"for\s*\(([^)]*)\)\s*in\s*\[") + + +def _resolve_loop_ident(body, pos, ident): + """`cols::` names bound to `ident` by the nearest enclosing `for (…) in […]`. + + `Multiplicity::Column(col)` inside + `for (stream, col) in [(1u64, cols::D1), (2u64, cols::D2)]` supplies TWO + multiplicity columns; a regex for `cols::` alone would miss both. + """ + best = None + for m in _FOR_TUPLE_RE.finditer(body, 0, pos): + if ident in [p.strip() for p in m.group(1).split(",")]: + best = m + if best is None: + return None + j, k = _match_from(body, best.end() - 1, "[", "]") + return set(re.findall(r"cols::(\w+)", body[j:k + 1])) + + +def multiplicity_columns(src, fn="bus_interactions"): + """Every column that supplies a bus multiplicity, parsed from the source. + + Returns `(columns, unresolved)`. `unresolved` lists multiplicity expressions + the parser did not understand — a non-empty list must be read as "the + invariant could not be checked", never as "no extra columns". + """ + body = _fn_body_text(src, fn) + cols, unresolved = set(), [] + for m in _MULT_RE.finditer(body): + kind = m.group(1) + j, k = _match_from(body, m.end() - 1, "(", ")") + arg = body[j + 1:k] + if kind == "Linear": + found = re.findall(r"column:\s*cols::(\w+)", arg) + cols.update(found) + n_terms = len(re.findall(r"LinearTerm::Column\w*\s*\{", arg)) + if n_terms != len(found): + unresolved.append(f"Linear with {n_terms - len(found)} non-`cols::` terms") + continue + for piece in arg.split(","): + piece = piece.strip() + if not piece: + continue + direct = re.fullmatch(r"cols::(\w+)", piece) + if direct: + cols.add(direct.group(1)) + continue + if re.fullmatch(r"\w+", piece): + resolved = _resolve_loop_ident(body, m.start(), piece) + if resolved: + cols.update(resolved) + else: + unresolved.append(f"{kind}({piece})") + else: + unresolved.append(f"{kind}({piece[:40]})") + return cols, unresolved + + +def padding_gated_columns(src): + """Columns X for which the chip emits `(1 − MU)·X = 0`, from the EXPRESSION. + + Returns `(columns, reason)`. `reason` is None on success; on any + unrecognised shape the column set is empty and `reason` says why — the + detector fails CLOSED, so an un-parsed chip is reported undefended. + """ + body = _fn_body_text(src, "eval") + cols = set() + + # (a) unrolled form: `b.emit_base(i, (one - mu) * b.main(0, cols::X))` + cols.update(re.findall( + r"\(\s*(?:one|1)\s*-\s*mu\s*\)\s*\*\s*b\.main\(0,\s*cols::(\w+)\)", body)) + cols.update(re.findall( + r"b\.main\(0,\s*cols::(\w+)\)\s*\*\s*\(\s*(?:one|1)\s*-\s*mu\s*\)", body)) + + # (b) loop form, which is what the chip uses: + # for (i, col) in [cols::…] { let x = b.main(0, col); + # b.emit_base(22 + i, (one - mu) * x); } + loop_reason = None + for m in re.finditer(r"for\s*(\(?[^)\n]*\)?)\s*in\s*\[", body): + try: + bj, bk = _match_from(body, m.end() - 1, "[", "]") + hj, hk = _match_from(body, bk) + except (ValueError, IndexError): + continue + loop_body = body[hj:hk + 1] + if "emit_base" not in loop_body: + continue + prod = re.search(r"\(\s*(?:one|1)\s*-\s*mu\s*\)\s*\*\s*(\w+)", loop_body) + if not prod: + continue + var = prod.group(1) + bind = re.search(rf"let\s+{re.escape(var)}\s*=\s*b\.main\(0,\s*(\w+)\)", loop_body) + if not bind: + loop_reason = (f"`(1 - mu) * {var}` in a loop, but `{var}` is not bound " + f"by `b.main(0, )`") + continue + bindings = [p.strip() for p in m.group(1).strip("()").split(",")] + if bind.group(1) not in bindings: + loop_reason = (f"`(1 - mu) * {var}` reads `{bind.group(1)}`, not a " + f"binding of this loop {bindings}") + continue + found = set(re.findall(r"cols::(\w+)", body[bj:bk + 1])) + if not found: + loop_reason = "gate loop header lists no `cols::` columns" + continue + cols.update(found) + + if not cols: + return set(), (loop_reason or "no `(1 - mu) * ` emission found") + return cols, None + + +def padding_gate_state(src=None): + """The F2 invariant: gated columns == raw-multiplicity columns. + + `MU` is excluded from the multiplicity side: it gates itself by + construction, and `(1 − MU)·MU = 0` is implied by `IS_BIT(MU)`. + """ + src = ECDAS2.read_text() if src is None else src + gated, reason = padding_gated_columns(src) + mult, unresolved = multiplicity_columns(src) + raw = mult - {"MU"} + return { + "present": bool(gated) and reason is None, + "reason": reason, + "gated": gated, + "raw_multiplicity": raw, + "unresolved_multiplicities": unresolved, + "exact": (not unresolved) and reason is None and gated == raw, + "ungated_multiplicities": raw - gated, + "gated_non_multiplicities": gated - raw, + } + + +# ── the D_INV gate (the F1 invariant) ─────────────────────────────────────── + +def emitted_relations(src): + """`(Relation, carry-column)` pairs the `eval` body actually emits.""" + return set(re.findall(r"\(Relation::(\w+),\s*cols::(\w+)\)", + _fn_body_text(src, "eval"))) + + +def addend_multiplicity_columns(src): + """The term list of the `Addend` receive's `Multiplicity::Linear`. + + Returns `(columns, problem)`. Every term must be a unit-coefficient plain + column: a `coefficient: 2` would double the receive without changing the + column set, so the set alone is not enough to characterise the multiplicity. + """ + body = _fn_body_text(src, "bus_interactions") + i = body.index("BusId::Addend") + m = _MULT_RE.search(body, i) + if not m or m.group(1) != "Linear": + return set(), f"Addend receive multiplicity is {m and m.group(1)}, not Linear" + j, k = _match_from(body, m.end() - 1, "(", ")") + arg = body[j:k + 1] + terms = re.findall( + r"LinearTerm::Column\w*\s*\{\s*coefficient:\s*(-?\d+),\s*column:\s*cols::(\w+)", + arg) + n_all = len(re.findall(r"LinearTerm::\w+", arg)) + if len(terms) != n_all: + return set(), f"{n_all - len(terms)} Addend term(s) are not plain `cols::` columns" + bad = [c for coeff, c in terms if coeff != "1"] + if bad: + return set(), f"Addend terms with coefficient != 1: {sorted(bad)}" + return {c for _, c in terms}, None + + +def _is_plain_column_sum(expr): + """Is `expr` literally `b.main(0, cols::A) + b.main(0, cols::B) + …`? + + Set equality on the `cols::` names is NOT enough: an opaque factor + (`gate_expr(b) * b.main(0, cols::S1) + …`) leaves the set unchanged while + letting the whole relation be gated off on rows of the tamperer's choosing. + Found by `audit_transcription.py` §G against the first version of this + check, which compared sets only. + """ + norm = re.sub(r"\s+", " ", expr).strip() + terms = [t.strip() for t in norm.split("+")] + return all(re.fullmatch(r"b\.main\(0, cols::\w+\)", t) for t in terms) + + +def dinv_gate_state(src=None): + """The F1 invariant: `Relation::Dinv`'s gate == the Addend receive's terms. + + Narrowing the gate by one term (dropping `S_CORR`) leaves the correction row + with no non-degeneracy check, which is a working forgery reachable by one + point subtraction — `TRANSCRIPTION-AUDIT.md` F1. Nothing used to read this + expression, so no verdict on the board moved. + """ + src = ECDAS2.read_text() if src is None else src + state = {"present": False, "reason": None, "gate": set(), "addend": set(), + "emitted": False, "applied": False, "matches_addend": False, + "plain_sum": False} + + state["emitted"] = any(r == "Dinv" for r, _ in emitted_relations(src)) + try: + arm = _match_arm_text(src, "Dinv") + except ValueError: + state["reason"] = "no `Relation::Dinv` arm in `s_i`" + return state + + m = re.search(r"let\s+g\s*=\s*(.*?);", arm, re.S) + if not m: + state["reason"] = "no `let g = …;` gate expression in the Dinv arm" + return state + expr = re.sub(r"//.*", "", m.group(1)) + state["gate"] = set(re.findall(r"cols::(\w+)", expr)) + state["plain_sum"] = _is_plain_column_sum(expr) + state["applied"] = re.search(r"\bg\s*\*\s*s\b", arm) is not None + addend, addend_problem = addend_multiplicity_columns(src) + state["addend"] = addend + state["matches_addend"] = bool(state["gate"]) and state["gate"] == addend + + if not state["emitted"]: + state["reason"] = "the Dinv block is never emitted by `eval`" + elif not state["applied"]: + state["reason"] = "the gate expression `g` does not multiply the relation" + elif not state["plain_sum"]: + state["reason"] = ("the gate is not a plain sum of columns: " + f"`{re.sub(chr(10) + r'\s*', ' ', expr).strip()[:90]}`") + elif addend_problem: + state["reason"] = addend_problem + elif not state["matches_addend"]: + state["reason"] = (f"gate {sorted(state['gate'])} != Addend receive " + f"{sorted(state['addend'])}") + state["present"] = state["reason"] is None + return state + + +# ── the JointSel → PH*/S* mapping (RESULTS §7's modelled step) ────────────── + +_ARM_RE = re.compile(r"((?:JointSel::\w+\s*\|?\s*)+)=>\s*\(([^)]*)\)") + + +def _sel_map(src, fn): + """`{JointSel variant: tuple}` for a `match self.step.sel` mapping fn.""" + out = {} + for m in _ARM_RE.finditer(_fn_body_text(src, fn)): + bits = tuple(int(x.strip()) for x in m.group(2).split(",")) + for v in re.findall(r"JointSel::(\w+)", m.group(1)): + out[v] = bits + return out + + +def joint_sel_maps(src=None): + """`Ecdas2Operation::phase_bits` / `selector_bits`, parsed from the chip. + + `PH*`/`S*` are not fields of `Lincomb2Witness`; the chip derives them from + `JointSel`, and `positive_real_witness2.py` reproduces that derivation by + hand. `RESULTS-lincomb2.md` §7 flagged the hand copy as the anchor's one + remaining modelled step — this is what makes it machine-checked instead. + + Also returns the enum's variant list, so a NEW variant (which would be a + silent gap in the Python dicts) is visible rather than merely absent. + """ + src = ECDAS2.read_text() if src is None else src + witness = (REPO / "crypto/ecsm/src/witness.rs").read_text() + i = witness.index("pub enum JointSel {") + j, k = _match_from(witness, i) + variants = re.findall(r"^\s*(\w+),", witness[j:k + 1], re.M) + return { + "phase_bits": _sel_map(src, "phase_bits"), + "selector_bits": _sel_map(src, "selector_bits"), + "variants": variants, + } + + +# ── chip-state detection ──────────────────────────────────────────────────── + +def chip_state(ecdas2_src=None, ecsm2_src=None): + """What is actually in the chip right now. Parsed, not pattern-matched. + + `padding_digit_gate` and `dinv_relation` keep their names and meanings for + the phase-E scripts, but are now derived from the emitted expressions, carry + the two structural invariants, and fail closed. + """ + ecdas2 = ECDAS2.read_text() if ecdas2_src is None else ecdas2_src + ecsm2 = ECSM2.read_text() if ecsm2_src is None else ecsm2_src + + pad = padding_gate_state(ecdas2) + dinv = dinv_gate_state(ecdas2) + + n_cols = int(re.search(r"pub const NUM_COLUMNS: usize = (\d+);", ecdas2).group(1)) + m = re.search(r"debug_assert_eq!\(idx, (\d+)\);", ecdas2) + n_constraints = int(m.group(1)) if m else None + + jb = re.search(r"BusId::JointBit,\s*\n\s*(Multiplicity::[A-Za-z]+)", ecdas2) + jb_mult = jb.group(1) if jb else "?" + + return { + "ecdas2_columns": n_cols, + "ecdas2_constraints": n_constraints, + "padding_digit_gate": pad["present"], + "padding_gate_detail": pad, + "dinv_relation": dinv["present"], + "dinv_gate_detail": dinv, + "jointbit_multiplicity": jb_mult, + "ecsm2_columns": int( + re.search(r"pub const NUM_COLUMNS: usize = (\d+);", ecsm2).group(1) + ), + } + + +def print_chip_state(state=None): + st = state or chip_state() + pad, dinv = st["padding_gate_detail"], st["dinv_gate_detail"] + print("chip state (PARSED from prover/src/tables/ at run time):") + print(f" ECDAS2 : {st['ecdas2_columns']} columns, " + f"{st['ecdas2_constraints']} constraints") + print(f" ECSM2 : {st['ecsm2_columns']} columns") + print(f" JointBit send multiplicity : {st['jointbit_multiplicity']}") + print(f" (1−MU)·X padding gate present : {st['padding_digit_gate']}" + + ("" if st["padding_digit_gate"] else f" [{pad['reason']}]")) + print(f" gated columns : {sorted(pad['gated'])}") + print(f" raw bus multiplicities : {sorted(pad['raw_multiplicity'])}") + print(f" sets are EQUAL : {pad['exact']}") + if pad["ungated_multiplicities"]: + print(" *** UNGATED MULTIPLICITY *** : " + f"{sorted(pad['ungated_multiplicities'])}") + if pad["gated_non_multiplicities"]: + print(" (gated but not a multiplicity, harmless): " + f"{sorted(pad['gated_non_multiplicities'])}") + if pad["unresolved_multiplicities"]: + print(" *** UNPARSED MULTIPLICITY ** : " + f"{pad['unresolved_multiplicities']}") + print(f" D_INV non-degeneracy present : {st['dinv_relation']}" + + ("" if st["dinv_relation"] else f" [{dinv['reason']}]")) + print(f" gate expression columns : {sorted(dinv['gate'])}") + print(f" Addend receive multiplicity : {sorted(dinv['addend'])}") + print(f" gate == Addend receive : {dinv['matches_addend']}") + return st + + +# ── ECDAS2 schedule model (z3) ────────────────────────────────────────────── + +def bit_var(s, name): + import z3 + v = z3.Int(name) + s.add(z3.Or(v == 0, v == 1)) + return v + + +class Ecdas2Row: + """The schedule columns of one ECDAS2 row, with `ecdas2.rs` idx 11..=21. + + `ablate` names a constraint to DROP (negative controls); `padding_gate` + toggles idx 22..=27. + + `padding_gate` defaults to **True**, i.e. to the chip as it is. It used to + default to False — a model strictly WEAKER than the chip on `MU = 0` rows, + which produced one spurious forgery (`TRANSCRIPTION-AUDIT.md` F4). Ablations + must now pass `padding_gate=False` explicitly. + """ + + SCHEDULE_IDX = { + 11: "PH1·PH2", + 12: "OP·NB", + 13: "(1−OP)(NB−D1−D2+D1·D2)", + 14: "OP−ΣS", + 15: "(1−PH1)·D1", + 16: "(1−PH1)·D2", + 17: "PH1·S_CORR", + 18: "PH1·(S1+S3−OP·D1)", + 19: "PH1·(S2+S3−OP·D2)", + 20: "MU·(1−PH1−PH2)·(S2−1)", + 21: "PH2·(S_CORR−1)", + } + + def __init__(self, s, tag, ablate=(), padding_gate=True): + self.tag = tag + for nm in ("mu", "op", "nb", "d1", "d2", "s1", "s2", "s3", "sc", "ph1", "ph2"): + setattr(self, nm, bit_var(s, f"{nm.upper()}_{tag}")) + import z3 + self.round = z3.Int(f"ROUND_{tag}") + # AreBytes(ROUND) is MU-gated, so this is asserted on padding rows where + # the chip does NOT enforce it (`TRANSCRIPTION-AUDIT.md` F5). Verified + # benign: with idx 22..=27 a MU=0 row's ROUND reaches no bus at all. + s.add(self.round >= 0, self.round <= 255) + + def add(idx, expr): + if idx not in ablate: + s.add(expr == 0) + + add(11, self.ph1 * self.ph2) + add(12, self.op * self.nb) + add(13, (1 - self.op) * (self.nb - self.d1 - self.d2 + self.d1 * self.d2)) + add(14, self.op - self.s1 - self.s2 - self.s3 - self.sc) + add(15, (1 - self.ph1) * self.d1) + add(16, (1 - self.ph1) * self.d2) + add(17, self.ph1 * self.sc) + add(18, self.ph1 * (self.s1 + self.s3 - self.op * self.d1)) + add(19, self.ph1 * (self.s2 + self.s3 - self.op * self.d2)) + add(20, self.mu * (1 - self.ph1 - self.ph2) * (self.s2 - 1)) + add(21, self.ph2 * (self.sc - 1)) + + # idx 22..=27: (1 − MU)·x = 0 for every column that is a bus + # MULTIPLICITY — the two digit sends and the four Addend selectors. + # Ablated as the unit "pad". + if padding_gate and "pad" not in ablate: + for col in (self.d1, self.d2, self.s1, self.s2, self.s3, self.sc): + s.add((1 - self.mu) * col == 0) + + def digit_send(self, stream): + """JointBit send multiplicity — `Multiplicity::Column(D1/D2)`, ungated.""" + return self.d1 if stream == 1 else self.d2 + + def addend_receive(self): + """Addend receive multiplicity — S1+S2+S3+S_CORR, also ungated.""" + return self.s1 + self.s2 + self.s3 + self.sc + + +# ── real lincomb2 witnesses via the oracle harness ────────────────────────── + +HARNESS = Path(__file__).resolve().parents[1] / "oracle/repo-harness/target/release/ecsm-oracle-harness" + + +def lincomb2_witness(u1, u2, p1, p2): + """One `ecsm::lincomb2_witness` dump, as a dict. Raises on the error path.""" + import json + import subprocess + line = f"lincomb2 {u1:x} {u2:x} {p1[0]:x} {p1[1]:x} {p2[0]:x} {p2[1]:x}\n" + r = subprocess.run([str(HARNESS)], input=line, capture_output=True, + text=True, check=True) + out = r.stdout.strip() + if not out.startswith("lincomb2_json "): + raise RuntimeError(f"harness rejected: {out[:80]}") + return json.loads(out[len("lincomb2_json "):]) diff --git a/thoughts/ec-recover-opt/gate/gate_common.py b/thoughts/ec-recover-opt/gate/gate_common.py new file mode 100644 index 000000000..f145b77e3 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/gate_common.py @@ -0,0 +1,252 @@ +"""Shared model for the ECSM/ECDAS z3 gate. + +Ground truth: prover/src/tables/ecsm.rs and prover/src/tables/ecdas.rs (constraint +bodies + bus sends). The SAME S_i builders below serve three purposes: + 1. exact interval bounds (L2 width audit) — Interval leaves + 2. z3 constraint models (L1/L8/byte-level) — z3 Int leaves + 3. concrete evaluation of real Rust witnesses — int leaves (positive controls) +so a transcription error would be caught by the real-witness evaluation (purpose 3) +before any UNSAT is trusted. + +Citations per relation are in each builder's docstring. +""" + +import json +from fractions import Fraction + +# ── Constants (independently recomputed; cross-checked vs crypto/ecsm/src/lib.rs +# by the oracle's check_constants.py — see thoughts/ec-recover-opt/oracle/) ── + +P = 2**256 - 2**32 - 977 # secp256k1 base field prime +N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 # curve order +PG = 2**64 - 2**32 + 1 # Goldilocks prime (constraints are enforced mod PG) +R3P = 3 * P # the µ-gated offset in all three ECDAS relations (R_BYTES == 3p) +B = 7 + +P_BYTES = list(P.to_bytes(32, "little")) +N_BYTES = list(N.to_bytes(32, "little")) +R_BYTES = list(R3P.to_bytes(33, "little")) + +# Carry offsets: ecsm.rs:27-28, ecdas.rs:24-26. +OFF = { + "ecsm_x2": 8160, + "ecsm_yg": 16319, + "ecdas_lambda": 32636, + "ecdas_xr": 8161, + "ecdas_yr": 16320, +} + +GEN_X = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 +GEN_Y = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 + + +def compose(bytes_seq): + """Value of a little-endian byte/limb sequence: Σ 256^j · b_j.""" + v = 0 + for j, b in enumerate(reversed(list(bytes_seq))): + v = v * 256 + b + return v + + +def decompose(v, n): + """n little-endian byte limbs of v (must fit).""" + assert 0 <= v < 256**n + return [(v >> (8 * j)) & 0xFF for j in range(n)] + + +# ── Interval arithmetic (exact for the multilinear-plus-signed-square forms +# of every S_i: all extremes are attained at byte corners 0/255, and one +# consistent corner assignment attains every monomial extreme at once — +# see RESULTS.md L2 method note) ── + + +class Iv: + __slots__ = ("lo", "hi") + + def __init__(self, lo, hi=None): + self.lo = lo + self.hi = lo if hi is None else hi + assert self.lo <= self.hi + + @staticmethod + def of(x): + return x if isinstance(x, Iv) else Iv(x, x) + + def __add__(self, o): + o = Iv.of(o) + return Iv(self.lo + o.lo, self.hi + o.hi) + + __radd__ = __add__ + + def __neg__(self): + return Iv(-self.hi, -self.lo) + + def __sub__(self, o): + return self + (-Iv.of(o)) + + def __rsub__(self, o): + return Iv.of(o) + (-self) + + def __mul__(self, o): + o = Iv.of(o) + cs = [self.lo * o.lo, self.lo * o.hi, self.hi * o.lo, self.hi * o.hi] + return Iv(min(cs), max(cs)) + + __rmul__ = __mul__ + + def __repr__(self): + return f"[{self.lo}, {self.hi}]" + + +BYTE = Iv(0, 255) +BIT = Iv(0, 1) + + +# ── S_i builders. `v` maps operand name -> indexable of leaves (int / z3 Int / Iv). +# Leaves must support +, -, * with python ints. Zero-padding past each +# operand's length mirrors byte_at (ecsm.rs:710-721, ecdas.rs:302-314). ── + + +def _at(arr, length, j): + return arr[j] if j < length else 0 + + +def s_ecsm_x2(v, i): + """ECSM X2 relation S_i (ecsm.rs:731-739): Σ xG_j·xG_{i-j} − x2_i − Σ q0_j·P_{i-j}.""" + s = 0 + for j in range(i + 1): + s = s + _at(v["xg"], 32, j) * _at(v["xg"], 32, i - j) + s = s - _at(v["q0"], 32, j) * (P_BYTES[i - j] if i - j < 32 else 0) + s = s - _at(v["x2"], 32, i) + return s + + +def s_ecsm_yg(v, i, mu=1): + """ECSM Yg relation S_i (ecsm.rs:740-759): + Σ yG_j·yG_{i-j} + µ·Σ P_j·P_{i-j} − Σ x2_j·xG_{i-j} − Σ q1_j·P_{i-j} − µ·B·[i=0]. + q1 is 33 bytes (byte 32 is IS_BIT-constrained, ecsm.rs:876-879).""" + s = 0 + p2 = 0 + for j in range(i + 1): + pj = P_BYTES[j] if j < 32 else 0 + pij = P_BYTES[i - j] if i - j < 32 else 0 + s = s + _at(v["yg"], 32, j) * _at(v["yg"], 32, i - j) + p2 = p2 + pj * pij + s = s - _at(v["x2"], 32, j) * _at(v["xg"], 32, i - j) + s = s - _at(v["q1"], 33, j) * pij + s = s + mu * p2 + if i == 0: + s = s - mu * B + return s + + +def _rq(v, i, qname, mu=1): + """µ·Σ R_j·P_{i-j} − Σ q_j·P_{i-j} (ecdas.rs:321-334). R = 3p, 33 const bytes.""" + rp = 0 + qp = 0 + for j in range(i + 1): + pij = P_BYTES[i - j] if i - j < 32 else 0 + rp += (R_BYTES[j] if j < 33 else 0) * pij + qp = qp + _at(v[qname], 33, j) * pij + return mu * rp - qp + + +def s_ecdas_lambda(v, i, op, mu=1, tamper=None): + """ECDAS Lambda relation S_i (ecdas.rs:352-368): + op·(Σ λ_j(xG−xA)_{i-j} + yA_i − yG_i) + (1−op)·(Σ 2λ_j·yA_{i-j} − 3xA_j·xA_{i-j}) + rq(Q0).""" + ob = _at(v["ya"], 32, i) - _at(v["yg"], 32, i) + for j in range(i + 1): + ob = ob + _at(v["lam"], 32, j) * (_at(v["xg"], 32, i - j) - _at(v["xa"], 32, i - j)) + nb = 0 + for j in range(i + 1): + nb = nb + 2 * _at(v["lam"], 32, j) * _at(v["ya"], 32, i - j) + nb = nb - 3 * _at(v["xa"], 32, j) * _at(v["xa"], 32, i - j) + return op * ob + (1 - op) * nb + _rq(v, i, "q0", mu) + + +def s_ecdas_xr(v, i, op, mu=1, tamper=None): + """ECDAS Xr relation S_i (ecdas.rs:369-376): + Σ λ_j·λ_{i-j} − xA_i − xG_i − xR_i − (1−op)(xA_i − xG_i) + rq(Q1).""" + s = 0 + for j in range(i + 1): + s = s + _at(v["lam"], 32, j) * _at(v["lam"], 32, i - j) + s = s - _at(v["xa"], 32, i) - _at(v["xg"], 32, i) - _at(v["xr"], 32, i) + s = s - (1 - op) * (_at(v["xa"], 32, i) - _at(v["xg"], 32, i)) + return s + _rq(v, i, "q1", mu) + + +def s_ecdas_yr(v, i, op=None, mu=1, tamper=None): + """ECDAS Yr relation S_i (ecdas.rs:377-384): + Σ λ_j(xA−xR)_{i-j} − yA_i − yR_i + rq(Q2). + tamper='swap_xa_xg' replaces xA by xG (transcription-sensitivity control).""" + xa = v["xg"] if tamper == "swap_xa_xg" else v["xa"] + s = 0 + for j in range(i + 1): + s = s + _at(v["lam"], 32, j) * (_at(xa, 32, i - j) - _at(v["xr"], 32, i - j)) + s = s - _at(v["ya"], 32, i) - _at(v["yr"], 32, i) + return s + _rq(v, i, "q2", mu) + + +def conv_carry(c, s_i, i): + """256·c_i − c_{i-1} − S_i (ecsm.rs:764-781, ecdas.rs:388-407); c_{-1}=0.""" + prev = c[i - 1] if i > 0 else 0 + return 256 * c[i] - prev - s_i + + +# ── Value-level integer relations (what L1+L2+L3 prove the byte constraints +# equivalent to, µ=1 rows). All are EXACT integer equations. ── + + +def val_relations_ecdas(op, lam, xa, ya, xg, yg, xr, yr, q0, q1, q2): + """The three ECDAS step identities over ℤ (µ=1).""" + lam_rel = ( + op * (lam * (xg - xa) + ya - yg) + + (1 - op) * (2 * lam * ya - 3 * xa * xa) + + R3P * P + - q0 * P + ) + xr_rel = lam * lam - xa - xg - xr - (1 - op) * (xa - xg) + R3P * P - q1 * P + yr_rel = lam * (xa - xr) - ya - yr + R3P * P - q2 * P + return lam_rel, xr_rel, yr_rel + + +def val_relations_ecsm(xg, yg, x2, q0, q1): + """ECSM curve-membership identities over ℤ (µ=1).""" + x2_rel = xg * xg - x2 - q0 * P + yg_rel = yg * yg + P * P - x2 * xg - B - q1 * P + return x2_rel, yg_rel + + +# ── Real-witness loading (harness `witness` command output) ── + + +def load_witness_json(line): + """Parses one `witness_json {...}` line into ints/lists (bytes stay as lists).""" + assert line.startswith("witness_json ") + w = json.loads(line[len("witness_json "):]) + + def bl(h): + return list(bytes.fromhex(h)) + + for k in ["x_g", "y_g", "k", "x2", "q0", "q1", "x_g_sub_p", "k_sub_n", + "x_r_sub_p", "x_r", "y_r"]: + w[k] = bl(w[k]) + for st in w["steps"]: + for k in ["x_a", "y_a", "x_g", "y_g", "lambda", "x_r", "y_r", "q0", "q1", "q2"]: + st[k] = bl(st[k]) + return w + + +# ── Reference step (chord/tangent over F_p) — used for expected values only; +# the independent reference remains the oracle's ec_ref.py. ── + + +def ref_step(op, xa, ya, xg, yg): + if op == 1: + lam = ((yg - ya) * pow(xg - xa, P - 2, P)) % P + else: + lam = (3 * xa * xa * pow(2 * ya, P - 2, P)) % P + xr = (lam * lam - xa - xg - (1 - op) * (xa - xg)) % P + # NB (1-op)(xa-xg) mirrors the chip's Xr relation: op=0 → λ²−2xA, op=1 → λ²−xA−xG. + yr = (lam * (xa - xr) - ya) % P + return lam, xr, yr diff --git a/thoughts/ec-recover-opt/gate/l1_l2_lift.py b/thoughts/ec-recover-opt/gate/l1_l2_lift.py new file mode 100644 index 000000000..8933c3538 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l1_l2_lift.py @@ -0,0 +1,252 @@ +"""L1 + L2: lifting field constraints to integer identities. + +L1 (z3, per relation): carry recurrence over ℤ + c_63 = 0 ⇒ Σ 256^i·S_i = 0 over ℤ + (S_i opaque bounded symbols; telescoping). + +L2a (exact interval arithmetic): for every ConvCarry constraint, the integer value + of the constraint LHS under the range CONTRACTS (bytes: AreBytes sends + ecsm.rs:446-470 / ecdas.rs:174-194 (paired ARE_BYTES sends — the contract + checks BOTH tuple elements, so the per-column byte hypothesis is identical + to the pre-pairing [b, 0] form; see pairing-equivalence.md) + MEMW-write + byte authority for xG,k; + carries: IsHalfword sends ecsm.rs:462-506 / ecdas.rs:192-214 with the exact + offsets; bits: IS_BIT constraints) is bounded ≪ p_g, so "≡ 0 mod p_g" ⇒ "= 0 + over ℤ". Bounds are EXACT: every S_i is multilinear-plus-signed-squares in + the byte leaves, so extremes sit at byte corners and one corner assignment + attains all monomial extremes simultaneously (verified by random corner + sampling cross-check below). + +L2b (exact interval arithmetic): completeness window audit — the HONEST carry + range per limb fits the IsHalfword window [−offset, 65536−offset) for all + five relations; validates the magic offsets 8160/16319/32636/8161/16320. + Includes the audit-controls: offset−1 tightness probe and the wrong-R probe + (r = 2p instead of 3p ⇒ honest quotient goes negative). + +L2c (z3): the overflow-chain word-carry lift — field equation + (addend0 + addend1 + c_prev − sum)·2^{-32} = c with c ∈ {0,1} forced and all + words < 2^32 by contract ⇒ the integer word equation holds; chained ⇒ + const + witness = value + 2^256·c_7, and c_7 = 1 ⇒ value < const strictly. +""" + +import random +import sys +import time +from pathlib import Path + +import z3 + +sys.path.insert(0, str(Path(__file__).parent)) +from gate_common import ( + B, Iv, BYTE, BIT, N, OFF, P, PG, P_BYTES, R_BYTES, R3P, + s_ecsm_x2, s_ecsm_yg, s_ecdas_lambda, s_ecdas_xr, s_ecdas_yr, +) + +random.seed(0xEC) +results = [] + + +def report(name, verdict, detail=""): + results.append((name, verdict, detail)) + print(f"[{verdict}] {name} {detail}") + + +# ── L1: telescoping (per relation family — offsets differ, structure identical) ── + +def l1_telescoping(): + for name, off in OFF.items(): + t0 = time.time() + s = z3.Solver() + S = [z3.Int(f"S{i}") for i in range(64)] + c = [z3.Int(f"c{i}") for i in range(64)] + SB = 10**9 # any bound works; L2a's exact bounds are far smaller + for i in range(64): + s.add(S[i] >= -SB, S[i] <= SB) + s.add(c[i] >= -off, c[i] < 65536 - off) + prev = c[i - 1] if i > 0 else 0 + s.add(256 * c[i] - prev - S[i] == 0) + s.add(c[63] == 0) + s.add(z3.Sum([256**i * S[i] for i in range(64)]) != 0) + r = s.check() + report(f"L1 telescoping [{name}]", "PROVED" if r == z3.unsat else str(r).upper(), + f"{time.time()-t0:.1f}s") + + +# ── L2a: soundness width audit ── + +BYTE_OPS_ECSM = {"xg": [BYTE] * 32, "x2": [BYTE] * 32, "q0": [BYTE] * 32, + "yg": [BYTE] * 32, "q1": [BYTE] * 32 + [BIT]} +# ECDAS quotients: all 33 bytes are full bytes (ecdas.rs:186-190; no IS_BIT on q[32]). +BYTE_OPS_ECDAS = {k: [BYTE] * 32 for k in ["lam", "xa", "ya", "xg", "yg", "xr", "yr"]} +for q in ["q0", "q1", "q2"]: + BYTE_OPS_ECDAS[q] = [BYTE] * 33 + +RELS = [ + ("ecsm_x2", lambda v, i, op: s_ecsm_x2(v, i), BYTE_OPS_ECSM, None), + ("ecsm_yg", lambda v, i, op: s_ecsm_yg(v, i, mu=1), BYTE_OPS_ECSM, None), + ("ecdas_lambda", lambda v, i, op: s_ecdas_lambda(v, i, op, mu=1), BYTE_OPS_ECDAS, "op"), + ("ecdas_xr", lambda v, i, op: s_ecdas_xr(v, i, op, mu=1), BYTE_OPS_ECDAS, "op"), + ("ecdas_yr", lambda v, i, op: s_ecdas_yr(v, i, op, mu=1), BYTE_OPS_ECDAS, "op"), +] + + +def s_interval(name, sfn, ops, i): + """Exact interval of S_i under contracts; op ∈ {0,1} handled by branch union.""" + outs = [] + for op in ([0, 1] if name.startswith("ecdas") else [None]): + v = {k: arr for k, arr in ops.items()} + iv = sfn(v, i, op) + iv = Iv.of(iv) + outs.append(iv) + return Iv(min(o.lo for o in outs), max(o.hi for o in outs)) + + +def l2a_soundness(): + worst = 0 + for name, sfn, ops, _ in RELS: + off = OFF[name] + cmax = max(off, 65536 - off) # |c| bound from the IsHalfword window + rel_worst = 0 + for i in range(64): + iv = s_interval(name, sfn, ops, i) + # ConvCarry LHS: 256·c_i − c_{i−1} − S_i. + m = 256 * cmax + cmax + max(abs(iv.lo), abs(iv.hi)) + rel_worst = max(rel_worst, m) + worst = max(worst, rel_worst) + ok = rel_worst < PG + report(f"L2a width [{name}]", + "PROVED" if ok else "FAIL", + f"max|LHS| = {rel_worst} = 2^{rel_worst.bit_length()-1}.. < p_g=2^63.99 ({rel_worst/PG:.2e}·p_g)") + # c_63 = 0 and bit constraints are single-symbol: trivially < p_g. Recorded. + report("L2a width [ColIsZero/IS_BIT/deg-1 constraints]", "PROVED", + "single-column values < 2^17 < p_g by their own contracts") + return worst + + +def l2a_corner_crosscheck(): + """Random corner sampling: no sampled S_i value may exceed the interval.""" + bad = 0 + for name, sfn, ops, _ in RELS: + for i in [0, 17, 31, 47, 62, 63]: + iv = s_interval(name, sfn, ops, i) + for _ in range(300): + v = {k: [random.choice([0, 255]) if isinstance(b, Iv) and b.hi == 255 + else random.choice([0, 1]) for b in arr] + for k, arr in ops.items()} + op = random.choice([0, 1]) + val = sfn(v, i, op) + if not (iv.lo <= val <= iv.hi): + bad += 1 + report("L2a corner cross-check", "PROVED" if bad == 0 else "FAIL", + f"{5*6*300} sampled corner evaluations inside interval bounds") + + +# ── L2b: completeness window audit (honest carries fit the windows) ── + +def l2b_completeness(tamper_off=None, tamper_r=None, quiet=False): + """Interval recurrence c_i ∈ [ (cmin+Smin)/256 , (cmax+Smax)/256 ] (exact int div, + monotone) must stay inside each window. Returns per-relation extremes.""" + all_ok = True + extremes = {} + for name, sfn, ops, _ in RELS: + off = (tamper_off or OFF)[name] if isinstance(tamper_off, dict) else OFF[name] + # Honest carries satisfy c_i = (c_{i-1} + S_i)/256 with EXACT division; + # floor toward −inf (>> 8) is therefore a sound monotone bound both ways. + lo = hi = 0 + wlo, whi = 0, 0 + for i in range(64): + iv = s_interval(name, sfn, ops, i) + lo = (lo + iv.lo) >> 8 + hi = (hi + iv.hi) >> 8 + wlo, whi = min(wlo, lo), max(whi, hi) + ok = (wlo >= -off) and (whi <= 65535 - off) + extremes[name] = (wlo, whi, off) + all_ok &= ok + if not quiet: + report(f"L2b window [{name}]", "PROVED" if ok else "FAIL", + f"honest-bound carries ⊂ [{wlo}, {whi}] vs window [{-off}, {65536-off})") + return all_ok, extremes + + +def l2b_controls(extremes): + # Tightness probe: shrink each offset to (−wlo − 1): window must now FAIL. + ok_all = True + for name, (wlo, whi, off) in extremes.items(): + tight_off = -wlo - 1 # one less than needed on the negative side + ok = not (wlo >= -tight_off and whi <= 65535 - tight_off) + ok_all &= ok + report("L2b audit-control [offset below necessity ⇒ audit fails]", + "PROVED" if ok_all else "FAIL", + f"per-relation minimal offsets: { {k: -v[0] for k, v in extremes.items()} } " + f"(repo offsets { {k: v[2] for k, v in extremes.items()} })") + + # Wrong-R probe: r = 2p ⇒ honest lambda-relation quotient can go negative + # (double branch: q = 2p + (2λyA − 3xA²)/p ≥ 2p − 3p + small < 0) ⇒ the + # nonneg 33-byte quotient can't exist for worst-case inputs. + worst_num = -3 * (P - 1) ** 2 # most negative honest numerator (double branch) + q_min_2p = 2 * P + worst_num // P + q_min_3p = 3 * P + worst_num // P + ok = (q_min_2p < 0) and (q_min_3p >= 0) + report("L2b audit-control [r=2p insufficient, r=3p sufficient]", + "PROVED" if ok else "FAIL", + f"q_min(r=2p)={q_min_2p} < 0 ≤ q_min(r=3p)={q_min_3p}") + + # Quotient headroom: honest q ≤ 3p + max(num)/p must fit 33 bytes (< 2^264); + # ECSM q1 ≤ p + max/p must fit its < 2^257 contract (32 bytes + top bit). + q_max_ecdas = 3 * P + (2 * (P - 1) ** 2) // P # xr rel: λ² dominates similarly + q_max_ecdas = max(q_max_ecdas, 3 * P + ((P - 1) ** 2) // P) + q1_max_ecsm = P + ((P - 1) ** 2) // P + ok = q_max_ecdas < 2**264 and q1_max_ecsm < 2**257 + report("L2b quotient headroom", "PROVED" if ok else "FAIL", + f"ECDAS q_max≈2^{q_max_ecdas.bit_length()}, ECSM q1_max≈2^{q1_max_ecsm.bit_length()}") + + +# ── L2c: overflow-chain lift (z3) ── + +def l2c_overflow_chain(): + t0 = time.time() + s = z3.Solver() + # One word step: A ≡ 2^32·c (mod p_g), |A| < 2^33, c ∈ {0,1} ⇒ A = 2^32·c over ℤ. + A, c, m = z3.Ints("A c m") + s.add(A > -(2**33), A < 2**33, z3.Or(c == 0, c == 1)) + s.add(A - 2**32 * c == m * PG) # the field equation, lifted with quotient m + s.add(A != 2**32 * c) # deny the integer conclusion + r1 = s.check() + report("L2c word-carry lift", "PROVED" if r1 == z3.unsat else str(r1).upper(), + f"{time.time()-t0:.1f}s") + + # Chained: const + witness_hl = value + 2^256·c7 with c7 = 1 ⇒ value < const. + t0 = time.time() + s = z3.Solver() + words_c = [z3.Int(f"kc{i}") for i in range(8)] # const words (symbolic ≤ 2^32-1) + words_w = [z3.Int(f"kw{i}") for i in range(8)] # halfword-addend words + words_v = [z3.Int(f"kv{i}") for i in range(8)] # value words + carr = [z3.Int(f"cc{i}") for i in range(8)] + for i in range(8): + s.add(words_c[i] >= 0, words_c[i] < 2**32) + s.add(words_w[i] >= 0, words_w[i] < 2**32) + s.add(words_v[i] >= 0, words_v[i] < 2**32) + s.add(z3.Or(carr[i] == 0, carr[i] == 1)) + prev = carr[i - 1] if i > 0 else 0 + s.add(words_c[i] + words_w[i] + prev - words_v[i] == 2**32 * carr[i]) + s.add(carr[7] == 1) + C = z3.Sum([2**(32 * i) * words_c[i] for i in range(8)]) + W = z3.Sum([2**(32 * i) * words_w[i] for i in range(8)]) + V = z3.Sum([2**(32 * i) * words_v[i] for i in range(8)]) + s.add(z3.Not(z3.And(V < C, C + W == V + 2**256))) + r2 = s.check() + report("L2c strict-inequality chain", "PROVED" if r2 == z3.unsat else str(r2).upper(), + f"{time.time()-t0:.1f}s") + + +if __name__ == "__main__": + l1_telescoping() + l2a_soundness() + l2a_corner_crosscheck() + ok, extremes = l2b_completeness() + l2b_controls(extremes) + l2c_overflow_chain() + print("\nSummary:") + for n, v, d in results: + print(f" {v:8} {n}") + if any(v not in ("PROVED",) for _, v, _ in results): + sys.exit(1) diff --git a/thoughts/ec-recover-opt/gate/l1_l5_port2.py b/thoughts/ec-recover-opt/gate/l1_l5_port2.py new file mode 100644 index 000000000..dc38d1719 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l1_l5_port2.py @@ -0,0 +1,253 @@ +"""L1-L5 for the lincomb2 chips — the port argument, and L5b's replacement. + +L1, L2a/b/c, L3a/L3b, L4a/b/c and L5a all speak ONLY about the three convolution +relations. They therefore transfer to ECDAS2 verbatim **if and only if** the +relation builders are the same function. That is checked mechanically here +rather than asserted (§1), which is a stronger port argument than re-deriving +the same lemmas against a re-transcribed model would be. + +L5b does NOT port. In the old chip it proved the incomplete-addition edge +unreachable from `k < N` plus the prefix structure; that argument has no analogue +in the joint chain, and the NUMS blinding proposed to replace it was broken +(`../lincomb2/FINDING-nums-blinding.log`). Its replacement is the unconditional +non-degeneracy relation `D_INV·(xB − xA) ≡ 1 (mod p)`, proved here (§3) to: + + (a) be imposed on exactly the addend-consuming rows — all three scalar addends + AND the correction row — and never on a doubling; + (b) be unsatisfiable exactly when `xA ≡ xB (mod p)`, including when the two + differ as byte strings but agree modulo p. + +Run: /bin/python l1_l5_port2.py +""" + +import sys +from pathlib import Path + +import z3 + +sys.path.insert(0, str(Path(__file__).parent)) +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "oracle")) + +from gate_common import OFF, P, PG +from gate2_common import ( + Ecdas2Row, chip_state, membership_bodies_identical, relation_bodies_identical, +) + +verdicts = [] + + +def report(name, ok, detail=""): + verdicts.append((name, ok)) + print(f"[{'PROVED' if ok else 'FAILED':^8}] {name}") + for line in detail.splitlines(): + if line: + print(f" {line}") + + +def hdr(t): + print() + print("=" * 78) + print(t) + print("=" * 78) + + +# ── §1 the port argument ──────────────────────────────────────────────────── + +def port_argument(): + hdr("§1 — L1 / L2 / L3 / L4 / L5a port by relation-body identity") + ident = relation_bodies_identical() + all_same = all(ident.values()) + detail = "\n".join(f"{k:14}: {'identical' if v else 'DIFFERS'}" + for k, v in ident.items()) + report("ECDAS2's relation builders are ECDAS's, modulo the XB/YB rename", + all_same, detail) + report("⇒ L1 (carry telescoping), L2a (per-limb widths), L3a (convolutions " + "capture\n the intended polynomial), L3b (chord/tangent stays on " + "curve), L4a/b/c\n (λ, xR, yR pinned mod p) and L5a (no 2-torsion) " + "port unchanged", all_same, + "These lemmas quantify over the relation's operands only; renaming an\n" + "operand column cannot affect them. The old gate's proofs stand as-is.\n" + "The comparison covers the s_i PROLOGUE and `conv_carry` as well as the\n" + "three arms: without the prologue a chip whose relations read the WRONG\n" + "columns still compares identical (TRANSCRIPTION-AUDIT.md F3).") + + # The membership port. The soundness theorem's "P2 is on the curve" clause + # rests on it and nothing used to check it (TRANSCRIPTION-AUDIT.md, gap 2). + mem = membership_bodies_identical() + mem_same = all(mem.values()) + report("ECSM2's P2-membership relations are ECSM's, modulo the column rename " + "and\n the µ → OK gate swap", mem_same, + "\n".join(f"{k:14}: {'identical' if v else 'DIFFERS'}" + for k, v in mem.items()) + + "\nOK is IS_BIT and OK·(1−MU) = 0 (ecsm2.rs idx 1, 2), so OK = 1 rows are" + "\na subset of MU = 1 rows and every ECSM membership lemma applies to" + "\nthem verbatim. `carry_chain` is excluded: ECSM2 has five" + "\nOverflowKinds to ECSM's three, so those bodies differ by design" + "\n(covered by L8 N3 / N7 instead).") + return all_same and mem_same + + +# ── §2 L2b — the carry windows for the NEW row population ─────────────────── + +def l2b_offsets(): + hdr("§2 — L2b: honest carries of the joint chain fit the existing windows") + import width_audit as wa + + print(" (measured in ../oracle/width_audit.py over 6,346 real rows of every") + print(" row type, and differentially checked against the prover's own") + print(" carries — 38,076 comparisons, 0 mismatches)") + print() + ranges = {"lambda": (-4303, 6728), "xr": (-112, 8308), "yr": (-465, 5914)} + ok = True + for rel, off_key in (("lambda", "ecdas_lambda"), ("xr", "ecdas_xr"), + ("yr", "ecdas_yr")): + off = OFF[off_key] + lo, hi = wa.carry_window(off) + clo, chi = ranges[rel] + fits = lo <= clo and chi <= hi + ok &= fits + print(f" {rel:7} honest [{clo}, {chi}] window [{lo}, {hi}] " + f"{'fits' if fits else 'DOES NOT FIT'}") + report("L2b: the joint chain's honest carries fit the unchanged offsets", ok, + "The varying addend does not move this: the relations have the same\n" + "term counts, and all four addends are canonical for an honest prover.") + return ok + + +# ── §3 L5b's replacement: the D_INV non-degeneracy relation ───────────────── + +def l5b_replacement(): + hdr("§3 — L5b REPLACED by D_INV·(xB − xA) ≡ 1 (mod p)") + st = chip_state() + gate = st["dinv_gate_detail"] + if not st["dinv_relation"]: + print(" NOTE: D_INV does not protect every addend-consuming row.") + print(f" reason: {gate['reason']}") + print(" What follows is then a SPECIFICATION rather than a check.") + print() + else: + print(" D_INV is present (ECDAS2 idx 223..=287), and its gate expression") + print(f" is PARSED from the `Relation::Dinv` arm: {sorted(gate['gate'])},") + print(f" which EQUALS the Addend receive's Multiplicity::Linear terms") + print(f" {sorted(gate['addend'])}. That equality is what (a1)/(a2) below") + print(" quantify over; before TRANSCRIPTION-AUDIT.md F1 nothing checked") + print(" it, and dropping S_CORR from the gate was a working forgery.") + print() + + # (a) imposed on exactly the addend-consuming rows. + # The Addend receive multiplicity IS ΣS, and idx 14 gives OP = ΣS, so + # gating by OP selects exactly the rows that consume an addend. + s = z3.Solver() + r = Ecdas2Row(s, "r") + s.add(r.mu == 1) + s.add(r.op != r.addend_receive()) + a_ok = s.check() == z3.unsat + report("(a1) OP = (Addend receive multiplicity) on every live row", a_ok, + "The chip gates D_INV by ΣS = S1+S2+S3+S_CORR — the very expression\n" + "that counts the Addend receive — so the check cannot drift away from\n" + "the rows that consume an addend. This lemma shows that gate coincides\n" + "with OP on every live row, so it fires exactly on the add rows.") + + # every add row type consumes an addend; doublings never do + covered = {} + for name, extra in ( + ("AddP1", lambda s, r: s.add(r.ph1 == 1, r.op == 1, r.d1 == 1, r.d2 == 0)), + ("AddP2", lambda s, r: s.add(r.ph1 == 1, r.op == 1, r.d1 == 0, r.d2 == 1)), + ("AddP12", lambda s, r: s.add(r.ph1 == 1, r.op == 1, r.d1 == 1, r.d2 == 1)), + ("Precompute", lambda s, r: s.add(r.ph1 == 0, r.ph2 == 0, r.op == 1)), + ("Correction", lambda s, r: s.add(r.ph2 == 1, r.op == 1)), + ("Double", lambda s, r: s.add(r.ph1 == 1, r.op == 0)), + ): + s = z3.Solver() + r = Ecdas2Row(s, name) + s.add(r.mu == 1) + extra(s, r) + s.push() + s.add(r.addend_receive() == 0) + no_addend = s.check() + s.pop() + covered[name] = no_addend + a2_ok = (all(covered[k] == z3.unsat + for k in ("AddP1", "AddP2", "AddP12", "Precompute", "Correction")) + and covered["Double"] == z3.sat) + report("(a2) all five addend-consuming row types are covered; doublings are not", + a2_ok, + "\n".join(f"{k:11}: consumes an addend = " + f"{'always' if v == z3.unsat else 'never'}" + for k, v in covered.items())) + + # (b) unsatisfiable exactly when xA ≡ xB (mod p) — including non-canonical + # encodings that agree mod p but differ as byte strings. + # + # Stated without `%` on symbolic terms (which makes the query nonlinear + # AND quantified, and z3 will not return): xB − xA = k·p for some integer + # k, and the relation asserts d·(xB − xA) − 1 = m·p for some integer m. + # Substituting gives p·(d·k − m) = 1, i.e. p divides 1. + d, k, m = z3.Int("d"), z3.Int("k"), z3.Int("m") + s = z3.Solver() + s.set("timeout", 60_000) + s.add(d >= 0, d < P) + s.add(P * (d * k - m) == 1) + v = s.check() + b_ok = v == z3.unsat + report("(b1) D_INV is unsatisfiable whenever xB ≡ xA (mod p)", b_ok, + f"z3: {v} — p·(d·k − m) = 1 has no integer solution for p > 1.\n" + "Covers the non-canonical case too: the relation is mod p, so a\n" + "byte-different xB congruent to xA still has (xB − xA) ≡ 0 and no\n" + "inverse. The degenerate add becomes UNPROVABLE, not merely unlikely.") + + # ...and satisfiable whenever they differ mod p (completeness). Constructive + # rather than solved-for: p is prime, so Fermat gives the witness directly. + import random + rng = random.Random(5150) + trials = [1, 2, P - 1, P - 2] + [rng.randrange(1, P) for _ in range(200)] + b2_ok = all((nz * pow(nz, P - 2, P)) % P == 1 for nz in trials) + report("(b2) D_INV is satisfiable whenever xB ≢ xA (mod p) (completeness)", + b2_ok, + f"{len(trials)} residues incl. 1, 2, p−1, p−2: the Fermat inverse is a\n" + "witness in every case. p is prime (A-PRIME), so the honest prover can\n" + "always build the column — the check costs no completeness.") + + # (c) the gated-off branch is not a hole: with g = 0 only `rq` survives, and + # L1's telescoping turns that into p·(µ·R − q3) = 0, which PINS q3 rather + # than leaving it free. Worth stating explicitly — "the check is gated + # off here" is exactly the shape a real hole takes. + q3 = z3.Int("q3") + mu = z3.Int("mu") + s = z3.Solver() + s.set("timeout", 60_000) + s.add(q3 >= 0, q3 < (1 << 264)) + s.add(z3.Or(mu == 0, mu == 1)) + s.add(P * (mu * (3 * P) - q3) == 0) # the telescoped gated-off relation + s.add(q3 != mu * (3 * P)) # can it be anything else? + v_c = s.check() + c_ok = v_c == z3.unsat + report("(c) the gated-off branch PINS q3 = µ·3p — a doubling is not a hole", + c_ok, + f"z3: {v_c}. With g = 0 the relation is µ·R·P − q3·P, which telescopes\n" + "to p·(µ·R − q3) = 0. Since p ≠ 0, q3 = 3p on a live doubling and 0 on\n" + "a padding row — not free. Confirmed on real witnesses too: every\n" + "doubling row's Q3 column is exactly 3p with zero carries\n" + "(positive_real_witness2.py).") + + # (d) what it discharges: the side condition L4a needs. + report("(d) L5b's obligation is discharged UNCONDITIONALLY", + b_ok and a_ok and c_ok, + "L4a pins λ given the side condition p ∤ (xB − xA). D_INV *is* that\n" + "side condition, witnessed in-circuit. No dlog assumption, no T₀\n" + "reduction, no appeal to the input distribution.") + return a_ok and a2_ok and b_ok and b2_ok and c_ok + + +def main(): + ok = [port_argument(), l2b_offsets(), l5b_replacement()] + hdr("SUMMARY") + for name, v in verdicts: + print(f" [{'PROVED' if v else 'FAILED'}] {name.splitlines()[0]}") + print() + print(f" {sum(1 for _, v in verdicts if v)}/{len(verdicts)} proved") + return 0 if all(ok) else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/gate/l3_l4_value.py b/thoughts/ec-recover-opt/gate/l3_l4_value.py new file mode 100644 index 000000000..b5b48d7b0 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l3_l4_value.py @@ -0,0 +1,243 @@ +"""L3 + L4: byte-level ⇒ value-level ⇒ step soundness. + +L3a (sympy, exact symbolic expansion): the composition identities — for each of + the five relations, Σ_i 256^i·S_i(bytes) is IDENTICALLY the intended + polynomial in the composed values. Together with L1+L2 this turns the chip's + field constraints into exact integer equations (gate_common.val_relations_*). + +L3b (sympy): on-curve preservation — the chord/tangent output of each branch + satisfies the curve equation, as a rational-function identity modulo + yA²=xA³+7, yG²=xG³+7. + +L4 (z3): value-level pinning. The ONLY lemma resting on primality (contract + A-PRIME, certified below): λ is pinned mod p by its relation given the side + condition (op=1: p∤(xG−xA); op=0: p∤2yA). xR/yR pinning then follows by the + easy divisibility direction (p|a ⇒ p|ab), no primality needed. + + Euclid use is split into machine-checked ring algebra + ONE assumed, + certified fact (see euclid_note in RESULTS.md): + (i) z3: relations ⇒ (λ−λ*)·d = T·p for an explicit T [UNSAT] + (ii) z3: (λ−λ*)·d = T·p ∧ λ−λ* = gq·p+gr ∧ d = dq·p+dr + ⇒ (gr·dr) ≡ 0 mod p [UNSAT] + (iii) certified assumption A-PRIME: 0= 0, lam < 2**256, lamstar >= 0, lamstar < P, + q0 >= 0, q0 < 2**264] + + # (i) ring algebra: (λ−λ*)·d == T·p with T explicit. + s = z3.Solver() + s.set("timeout", 120000) + s.add(base) + s.add((lam - lamstar) * d != T_expr * P) + r1 = s.check() + + # (ii) remainder decomposition forces p | gr·dr. + s = z3.Solver() + s.set("timeout", 120000) + s.add((lam - lamstar) * d == T * P) + s.add(lam - lamstar == gq * P + gr, gr > 0, gr < P) # negated goal: λ ≢ λ* + s.add(d == dq * P + dr, dr > 0, dr < P) # side condition: p ∤ d + s.add((gr * dr) % P != 0) + r2 = s.check() + return r1, r2 + + +def l4a(): + for op, side in [(1, "p∤(xG−xA)"), (0, "p∤2yA")]: + t0 = time.time() + r1, r2 = _lambda_pin(op) + v1 = "PROVED" if r1 == z3.unsat else str(r1).upper() + v2 = "PROVED" if r2 == z3.unsat else str(r2).upper() + verdict = "PROVED" if (v1 == v2 == "PROVED") else f"(i)={v1},(ii)={v2}" + report(f"L4a λ-pin [op={op}]", verdict, + f"side: {side}; + A-PRIME closes gr·dr ≡ 0; {time.time()-t0:.0f}s") + + +# ── L4b/L4c: xR, yR pinned mod p given λ pinned (no primality) ── + +def l4bc(): + lam, lamstar, q1, q2, m1, m2, gq = z3.Ints("lam lamstar q1 q2 m1 m2 gq") + xa, xg, xr, xrstar, yr, yrstar, ya = z3.Ints("xa xg xr xrstar yr yrstar ya") + hq, hr = z3.Ints("hq hr") + op = z3.Int("op") + + t0 = time.time() + s = z3.Solver() + s.set("timeout", 120000) + s.add(z3.Or(op == 0, op == 1)) + s.add(lam - lamstar == gq * P) # λ ≡ λ* (from L4a) + # chip xR relation (ℤ) and reference congruence: + s.add(lam * lam - xa - xg - xr - (1 - op) * (xa - xg) + R3P * P - q1 * P == 0) + s.add(lamstar * lamstar - xa - xg - xrstar - (1 - op) * (xa - xg) - m1 * P == 0) + s.add(xr - xrstar == hq * P + hr, hr > 0, hr < P) # negated goal + r1 = s.check() + report("L4b xR-pin", "PROVED" if r1 == z3.unsat else str(r1).upper(), + f"{time.time()-t0:.0f}s") + + t0 = time.time() + s = z3.Solver() + s.set("timeout", 120000) + s.add(lam - lamstar == gq * P) + s.add(xr - xrstar == m2 * P) # xR ≡ xR* (from L4b) + s.add(lam * (xa - xr) - ya - yr + R3P * P - q2 * P == 0) + s.add(lamstar * (xa - xrstar) - ya - yrstar - m1 * P == 0) + s.add(yr - yrstar == hq * P + hr, hr > 0, hr < P) + r2 = s.check() + report("L4c yR-pin", "PROVED" if r2 == z3.unsat else str(r2).upper(), + f"{time.time()-t0:.0f}s") + + +if __name__ == "__main__": + certify_primes() + l3a() + l3b() + l4a() + l4bc() + print("\nSummary:") + for n, v, d in results: + print(f" {v:8} {n}") + if any(v != "PROVED" for _, v, _ in results): + sys.exit(1) diff --git a/thoughts/ec-recover-opt/gate/l5_sides.py b/thoughts/ec-recover-opt/gate/l5_sides.py new file mode 100644 index 000000000..a0dde40ae --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l5_sides.py @@ -0,0 +1,103 @@ +"""L5: discharging the step lemma's side conditions. + +L5a (computation, certified): secp256k1 has NO point with y ≡ 0: such a point + would have order 2, impossible since |E(F_p)| = N is odd (cofactor 1). + Equivalently x³+7 has no root in F_p ⟺ −7 is a non-cube (p ≡ 1 mod 3). + Both routes computed and cross-checked. Covers the op=0 side condition + p∤2yA for ANY byte-bounded yA with A on-curve mod p (yA ≡ 0 mod p would be + a y=0 curve point). + +L5b (z3): the incomplete-addition edge is unreachable — at any add row the + incoming accumulator is c·G with c = 2t even, 3 ≤ u = 2t+1 = ⌊k/2^r⌋ (bit r + of k set), k < N ⇒ c ∈ [2, N−2] ⇒ c ≢ ±1 (mod N) ⇒ A ≠ ±G in the group. + (The identification A = c·G and u = ⌊k/2^r⌋ is the L6 chain induction; this + lemma discharges its arithmetic core.) + +L5c (z3): x-equality ⇒ same-or-negated point (needed to turn "A ≠ ±G" into the + algebraic side condition p∤(xG−xA)): if both points satisfy the curve + equation mod p and xA ≡ xG, then yA ≡ ±yG. Easy divisibility direction plus + ONE more A-PRIME Euclid instance for (yA−yG)(yA+yG) ≡ 0. +""" + +import sys +import time +from pathlib import Path + +import sympy as sp +import z3 + +sys.path.insert(0, str(Path(__file__).parent)) +from gate_common import B, N, P + +results = [] + + +def report(name, verdict, detail=""): + results.append((name, verdict, detail)) + print(f"[{verdict}] {name} {detail}", flush=True) + + +def l5a(): + assert P % 3 == 1 + cube_test = pow((-B) % P, (P - 1) // 3, P) + no_root = cube_test != 1 # −7 is a cube ⟺ x³+7 has a root + n_odd = N % 2 == 1 + # Independent cross-check via sympy's nthroot_mod on a few candidates is + # overkill; the two facts must agree: no y=0 point ⟺ no root ⟸ N odd. + report("L5a no-2-torsion", "PROVED" if (no_root and n_odd) else "FAIL", + f"(−7)^((p−1)/3) mod p ≠ 1: {no_root}; |E|=N odd: {n_odd}") + + +def l5b(): + t0 = time.time() + s = z3.Solver() + s.set("timeout", 120000) + k, u, ss, rem, t, c = z3.Ints("k u s rem t c") + s.add(k >= 1, k < N) + s.add(ss >= 1) # s = 2^r ≥ 1 (r ≥ 0) + s.add(k == u * ss + rem, rem >= 0, rem < ss) # u = ⌊k/2^r⌋ + s.add(u == 2 * t + 1) # bit r of k is set (add row, Bit balance) + s.add(t >= 1) # not the seed: at least one prior double + s.add(c == 2 * t) # incoming accumulator multiplier + s.add(z3.Or(c % N == 1, c % N == N - 1)) # A = ±G + r = s.check() + report("L5b incomplete-addition unreachable", "PROVED" if r == z3.unsat else str(r).upper(), + f"{time.time()-t0:.0f}s") + + +def l5c(): + t0 = time.time() + # (i) ring: curve equations + xA ≡ xG ⇒ (yA−yG)(yA+yG) = T·p explicit. + xa, ya, xg, yg, qa, qg, dq, T = z3.Ints("xa ya xg yg qa qg dq T") + s = z3.Solver() + s.set("timeout", 120000) + s.add(ya * ya - (xa * xa * xa + B) == qa * P) + s.add(yg * yg - (xg * xg * xg + B) == qg * P) + s.add(xa - xg == dq * P) + # (yA−yG)(yA+yG) = yA²−yG² = (xa³−xg³) + (qa−qg)p; xa³−xg³ = (xa−xg)(xa²+xa·xg+xg²). + s.add((ya - yg) * (ya + yg) != (dq * (xa * xa + xa * xg + xg * xg) + qa - qg) * P) + r1 = s.check() + + # (ii) remainder split: p | (yA−yG)(yA+yG) ∧ p∤(yA−yG) ∧ p∤(yA+yG) ⇒ p | gr·dr. + g1q, g1r, g2q, g2r, T2 = z3.Ints("g1q g1r g2q g2r T2") + s = z3.Solver() + s.set("timeout", 120000) + s.add((ya - yg) * (ya + yg) == T2 * P) + s.add(ya - yg == g1q * P + g1r, g1r > 0, g1r < P) + s.add(ya + yg == g2q * P + g2r, g2r > 0, g2r < P) + s.add((g1r * g2r) % P != 0) + r2 = s.check() + v = "PROVED" if (r1 == z3.unsat and r2 == z3.unsat) else f"(i)={r1},(ii)={r2}" + report("L5c x-equal ⇒ y = ±y (mod p)", v, + f"+ A-PRIME closes; {time.time()-t0:.0f}s") + + +if __name__ == "__main__": + l5a() + l5b() + l5c() + print("\nSummary:") + for n, v, d in results: + print(f" {v:8} {n}") + if any(v != "PROVED" for _, v, _ in results): + sys.exit(1) diff --git a/thoughts/ec-recover-opt/gate/l6_joint_counting.py b/thoughts/ec-recover-opt/gate/l6_joint_counting.py new file mode 100644 index 000000000..086bf8a93 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l6_joint_counting.py @@ -0,0 +1,377 @@ +"""L6 — the lincomb2 joint-schedule counting argument, checked against the chips. + +Model transcribed by READING `prover/src/tables/ecdas2.rs` (288 constraints, the +schedule-relevant ones are idx 0..=27) and `ecsm2.rs` (693 constraints; the bus +wiring at :543-923). Convolution carries are out of scope here — they are the +width audit's subject (`../lincomb2/WIDTH-AUDIT.md`) — this file is about the +SCHEDULE: which rows exist, in what order, and which digits they consume. + +Sections: + + L6-A per-row schedule constraints are consistent, and force the honest shape + on live rows (round monotonicity, the add/addend agreement table). + L6-B the 2x JointBit multiplicity is strictly stronger than 1x — the 1x + variant admits a WRONG ADDEND at a round where both digits are set. + L6-C *** THE BREAK, NOW CLOSED *** padding rows (MU = 0) could send live + JointBit digits, because the send's multiplicity is `Column(D1)` and no + constraint tied D1/D2 to MU. Two phantom rows satisfy a round's 2x + count with NO add row on the chain — a set bit of u1 is "consumed" + without ever being added. Reproduced here as the ABLATION of a defence + the chip now carries; L6-E is what it was worth. + L6-D the fix — `(1−MU)·{D1, D2, S1, S2, S3, S_CORR} = 0`, mirroring + `ecdas.rs` idx 4 `NEXT_OP·(1−MU) = 0` — turns L6-C UNSAT. It LANDED as + `ecdas2.rs:988-1003`, idx 22..=27; `gate2_common.chip_state()` parses + the emitted expression and cross-checks the gated column set against the + columns that actually supply a bus multiplicity. + +Note this file keeps its own `Row` class rather than using +`gate2_common.Ecdas2Row`: it is the historical derivation of the break, and it +must be able to model the pre-fix chip. + +Run: /bin/python l6_joint_counting.py +""" + +import sys + +from z3 import And, Bool, Distinct, If, Implies, Int, Not, Or, Solver, Sum, sat, unsat + + +def bit(s, name): + v = Int(name) + s.add(Or(v == 0, v == 1)) + return v + + +class Row: + """One ECDAS2 row's schedule columns.""" + + def __init__(self, s, tag, fix_padding_gate=False): + self.mu = bit(s, f"MU_{tag}") + self.op = bit(s, f"OP_{tag}") + self.nb = bit(s, f"NB_{tag}") + self.d1 = bit(s, f"D1_{tag}") + self.d2 = bit(s, f"D2_{tag}") + self.s1 = bit(s, f"S1_{tag}") + self.s2 = bit(s, f"S2_{tag}") + self.s3 = bit(s, f"S3_{tag}") + self.sc = bit(s, f"SC_{tag}") + self.ph1 = bit(s, f"PH1_{tag}") + self.ph2 = bit(s, f"PH2_{tag}") + self.round = Int(f"ROUND_{tag}") + s.add(self.round >= 0, self.round <= 255) # AreBytes(ROUND), MU-gated + + # --- ecdas2.rs constraint indices 11..=21, transcribed --- + s.add(self.ph1 * self.ph2 == 0) # 11 + s.add(self.op * self.nb == 0) # 12 + s.add((1 - self.op) * (self.nb - self.d1 - self.d2 + + self.d1 * self.d2) == 0) # 13 + s.add(self.op - self.s1 - self.s2 - self.s3 - self.sc == 0) # 14 + s.add((1 - self.ph1) * self.d1 == 0) # 15 + s.add((1 - self.ph1) * self.d2 == 0) # 16 + s.add(self.ph1 * self.sc == 0) # 17 + s.add(self.ph1 * (self.s1 + self.s3 - self.op * self.d1) == 0) # 18 + s.add(self.ph1 * (self.s2 + self.s3 - self.op * self.d2) == 0) # 19 + s.add(self.mu * (1 - self.ph1 - self.ph2) * (self.s2 - 1) == 0) # 20 + s.add(self.ph2 * (self.sc - 1) == 0) # 21 + + if fix_padding_gate: + # LANDED as ecdas2.rs idx 22, 23, mirroring ecdas.rs idx 4 + # (`NEXT_OP·(1−MU) = 0`). The chip also gates the four selectors + # (idx 24..=27); only the digit half matters to this file. + s.add((1 - self.mu) * self.d1 == 0) + s.add((1 - self.mu) * self.d2 == 0) + + def sends_stream(self, stream): + """Multiplicity of this row's JointBit send. NOT MU-gated in the chip: + `Multiplicity::Column(cols::D1)` (ecdas2.rs:601-612). What makes a + padding row inert is idx 22, 23, not the send.""" + return self.d1 if stream == 1 else self.d2 + + +def hdr(t): + print() + print("=" * 74) + print(t) + print("=" * 74) + + +# ── L6-A: the per-row add/addend agreement table ──────────────────────────── + +def l6_a(): + hdr("L6-A — per-row schedule constraints (live main-chain rows)") + results = [] + + # (a) On a live main-chain ADD, the digits select exactly one addend, and + # the (0,0) digit pair is unsatisfiable (no spurious add). + for d1v, d2v, want in [(1, 0, "S1"), (0, 1, "S2"), (1, 1, "S3"), (0, 0, None)]: + s = Solver() + r = Row(s, "add") + s.add(r.mu == 1, r.ph1 == 1, r.op == 1, r.d1 == d1v, r.d2 == d2v) + if want is None: + verdict = s.check() + ok = verdict == unsat + print(f" digits (0,0) on an add : {verdict} " + f"({'no spurious add possible' if ok else 'SPURIOUS ADD'})") + results.append(ok) + else: + # the intended selector must be forced: negating it is UNSAT + s.push() + s.add(Not(getattr(r, want.lower()) == 1)) + verdict = s.check() + s.pop() + ok = verdict == unsat + print(f" digits ({d1v},{d2v}) force {want:2} : " + f"{verdict} ({'forced' if ok else 'NOT FORCED'})") + results.append(ok) + + # (b) On a live main-chain DOUBLE, no addend is consumed. + s = Solver() + r = Row(s, "dbl") + s.add(r.mu == 1, r.ph1 == 1, r.op == 0) + s.add(r.s1 + r.s2 + r.s3 + r.sc > 0) + verdict = s.check() + ok = verdict == unsat + print(f" doubling consumes no addend : {verdict} " + f"({'forced' if ok else 'ADDEND LEAK'})") + results.append(ok) + + # (c) NB = D1 or D2 on a doubling: a set digit forces an add to follow. + s = Solver() + r = Row(s, "nb") + s.add(r.mu == 1, r.ph1 == 1, r.op == 0, Or(r.d1 == 1, r.d2 == 1), r.nb == 0) + verdict = s.check() + ok = verdict == unsat + print(f" set digit forces NB = 1 : {verdict} " + f"({'forced' if ok else 'ADD CAN BE DROPPED'})") + results.append(ok) + + # (d) Round monotonicity: successor round is round − 1 + NB, and an add + # (OP = 1) always has NB = 0, so two consecutive steps strictly decrease. + s = Solver() + r = Row(s, "mono") + s.add(r.mu == 1, r.op == 1, r.nb == 1) + verdict = s.check() + ok = verdict == unsat + print(f" add-after-add impossible (OP·NB) : {verdict} " + f"({'forced' if ok else 'ROUND CAN STALL'})") + results.append(ok) + + return all(results) + + +# ── L6-B: is the 2x JointBit multiplicity really stronger than 1x? ────────── + +def l6_b(): + hdr("L6-B — the 2x JointBit multiplicity vs 1x") + print(" Scenario: round r with u1_bit(r) = u2_bit(r) = 1. The honest chain") + print(" has a double and an add, both carrying (D1,D2) = (1,1), so the add") + print(" selects S3 = P12. Can a prover make the add select P2 instead?") + print() + + def scenario(mult): + s = Solver() + dbl = Row(s, "d") + add = Row(s, "a") + for r in (dbl, add): + s.add(r.mu == 1, r.ph1 == 1) + s.add(dbl.op == 0, add.op == 1) + s.add(dbl.round == add.round) # the add shares the double's round + s.add(dbl.nb == 1) # the add exists + # JointBit balance at this round, both streams, u1_bit = u2_bit = 1 + s.add(dbl.sends_stream(1) + add.sends_stream(1) == mult) + s.add(dbl.sends_stream(2) + add.sends_stream(2) == mult) + # the attack: the add consumes something other than P12 + s.add(add.s3 == 0) + return s.check() + + v1 = scenario(1) + v2 = scenario(2) + print(f" multiplicity 1x : {v1} " + f"{'<-- WRONG ADDEND REACHABLE' if v1 == sat else ''}") + print(f" multiplicity 2x : {v2} " + f"{'(blocked)' if v2 == unsat else '<-- STILL REACHABLE'}") + print() + print(" Reading: with 1x the prover splits the two digits across the two") + print(" rows (double takes D1, add takes D2), the counts still balance, and") + print(" the add adds P2 where the schedule calls for P12 — a wrong Q.") + print(" 2x forces BOTH rows to carry BOTH digits, which pins S3. The 2x") + print(" claim is CONFIRMED: 2 = 1+1 is the only decomposition because each") + print(" row's multiplicity is a single IS_BIT column.") + return v1 == sat and v2 == unsat + + +# ── L6-C: the break ───────────────────────────────────────────────────────── + +def l6_c(fix=False): + hdr(f"L6-{'D' if fix else 'C'} — padding rows as phantom digit senders" + f"{' (WITH the proposed fix)' if fix else ''}") + + # Step 1: is a padding row with a live digit send even satisfiable? + s = Solver() + ph = Row(s, "pad", fix_padding_gate=fix) + s.add(ph.mu == 0, ph.d1 == 1) + v_row = s.check() + print(f" a MU=0 row with D1=1 satisfies all row constraints : {v_row}") + + # Step 2: the schedule-level consequence. Round r, u1_bit(r) = 1, and the + # prover wants NO add at round r (so u1's bit is never added to the chain). + s = Solver() + dbl = Row(s, "d", fix_padding_gate=fix) + s.add(dbl.mu == 1, dbl.ph1 == 1, dbl.op == 0) + s.add(dbl.nb == 0) # <-- no add follows at this round + phantoms = [Row(s, f"p{i}", fix_padding_gate=fix) for i in range(4)] + for p in phantoms: + s.add(p.mu == 0) # padding rows + s.add(p.round == dbl.round) # aimed at the victim round + # JointBit balance for stream 1 at this round must equal 2·u1_bit(r) = 2. + total = dbl.sends_stream(1) + Sum([p.sends_stream(1) for p in phantoms]) + s.add(total == 2) + v_sched = s.check() + + print(f" round r: u1_bit(r)=1 balanced with NO add on chain : {v_sched}") + if v_sched == sat: + m = s.model() + live = [i for i, p in enumerate(phantoms) if m.evaluate(p.d1).as_long() == 1] + print(f" witness: double has D1={m.evaluate(dbl.d1)}, NB=0 (no add), " + f"phantom rows {live} each send D1=1 at the same ROUND") + print() + if not fix: + print(" *** BREAK (ablation) *** The JointBit send's multiplicity is") + print(" `Multiplicity::Column(cols::D1)` (ecdas2.rs:601-612) and, before") + print(" idx 22..=27, NOTHING tied D1/D2 to MU. A padding row is otherwise") + print(" inert (its Ecdas, AreBytes and IsHalfword interactions are all") + print(" MU-gated, its Addend receive is ΣS-gated) but its digit send was") + print(" LIVE. Two phantom rows per targeted round satisfy the 2x count") + print(" while the chain skips the add entirely.") + else: + print(" With `(1−MU)·{D1, D2, S1, S2, S3, S_CORR} = 0` — the exact shape") + print(" of `ecdas.rs` idx 4 `NEXT_OP·(1−MU) = 0` — both queries go UNSAT.") + print(" This is `ecdas2.rs:988-1003`, idx 22..=27, in the chip today.") + + if fix: + return v_row == unsat and v_sched == unsat + return v_row == sat and v_sched == sat + + +# ── L6-E: what the break is worth — an ARBITRARY chosen recovered key ─────── + +def l6_e(): + hdr("L6-E — exploitability: steering the recovered key to a chosen target") + sys.path.insert(0, "../oracle") + from ec_ref import GX, GY, N, P, pt_add, pt_double, recover_even_y, scalar_mul + import lincomb2_ref + + T0, _ = lincomb2_ref.t0_ref() + G = (GX, GY) + + def chain(u1_eff, u2_eff, p1, p2, length): + """The chain as it executes when the adds for the dropped bits are + absent: the effective multipliers are u1_eff / u2_eff.""" + p12 = pt_add(p1, p2) + acc = T0 + for r in range(length - 1, -1, -1): + acc = pt_double(acc) + e1, e2 = (u1_eff >> r) & 1, (u2_eff >> r) & 1 + if not (e1 or e2): + continue + addend = p12 if (e1 and e2) else (p1 if e1 else p2) + acc = pt_add(acc, addend) + tpow = T0 + for _ in range(length): + tpow = pt_double(tpow) + return pt_add(acc, (tpow[0], (P - tpow[1]) % P)) + + # The attacker names the public key it wants `ecrecover` to return. + victim_sk = 0xC0FFEE1234567890ABCDEF0011223344556677889900AABBCCDDEEFF01020304 + target = scalar_mul(victim_sk, G) + print(f" target pubkey (a key the attacker does NOT hold):") + print(f" ({target[0]:#x},") + print(f" {target[1]:#x})") + + # Choose effective multipliers, then solve for R. u1' = u2' = 1 gives + # R = target − G, which is a plain point subtraction — no discrete log. + u1_eff, u2_eff = 1, 1 + neg_g = (GX, (P - GY) % P) + R = pt_add(target, neg_g) # R = target − G + + # Now inflate u1 with one extra set bit that the chain will be made to skip. + m = 8 # any bit unset in u1' and u2' + u1 = u1_eff | (1 << m) + u2 = u2_eff + length = max(u1.bit_length(), u2.bit_length()) + + forged = chain(u1_eff, u2_eff, G, R, length) + honest = lincomb2_ref.lincomb2(u1, G, u2, R) + print() + print(f" u1 = {u1} (bit {m} will be dropped), u2 = {u2}, len = {length}") + print(f" honest chain Q = ({honest[0]:#x}, ...)") + print(f" forged chain Q' = ({forged[0]:#x}, ...)") + print(f" Q' == target : {forged == target}") + print(f" Q' != honest Q : {forged != honest}") + + # Package it as a real ecrecover input: r = x(R), and z, s back-solved. + r_sig = R[0] + ok_pkg = r_sig < N and r_sig != 0 + if ok_pkg: + v = R[1] & 1 + rinv = pow(r_sig, N - 2, N) + z = (-u1 * r_sig) % N + s_sig = (u2 * r_sig) % N + gu1, gu2 = (-(rinv * z)) % N, (rinv * s_sig) % N + ye = recover_even_y(r_sig) + lifted = (r_sig, ye if v == 0 else (P - ye) % P) + print() + print(f" ecrecover packaging: z={z:#x}") + print(f" r={r_sig:#x}") + print(f" s={s_sig:#x} v={v}") + print(f" guest recomputes u1: {gu1 == u1} u2: {gu2 == u2} " + f"lifts R: {lifted == R}") + print() + print(" Reading: u1' and u2' are free, so R = target − u1'·G is a plain") + print(" point subtraction — NO discrete log is needed. The attacker gets an") + print(" ARBITRARY chosen recovered public key, i.e. an arbitrary chosen") + print(" transaction sender. This is strictly worse than the NUMS finding,") + print(" which only yielded a one-parameter family.") + return forged == target and forged != honest and ok_pkg + + +def main(): + a = l6_a() + b = l6_b() + c = l6_c(fix=False) + d = l6_c(fix=True) + e = l6_e() + + from gate2_common import chip_state + st = chip_state() + pad = st["padding_gate_detail"] + hdr("SUMMARY") + print(f" chip state: (1−MU)·X gate present = {st['padding_digit_gate']}, " + f"D_INV present = {st['dinv_relation']}") + print(f" gated columns {sorted(pad['gated'])}") + print(f" == raw bus multiplicities {sorted(pad['raw_multiplicity'])}: " + f"{pad['exact']}") + if pad["ungated_multiplicities"]: + print(" *** A BUS MULTIPLICITY HAS ESCAPED THE GATE: " + f"{sorted(pad['ungated_multiplicities'])} ***") + print() + print(f" L6-A per-row schedule forcing : {'PASS' if a else 'FAIL'}") + print(f" L6-B 2x multiplicity load-bearing : {'CONFIRMED' if b else 'NOT CONFIRMED'}") + print(f" L6-C padding-row digit forgery : {'REPRODUCED' if c else 'not reproduced'}") + print(f" L6-D proposed fix closes it : {'YES' if d else 'NO'}") + print(f" L6-E arbitrary chosen sender : {'DEMONSTRATED' if e else 'not demonstrated'}") + print() + if c and not st["padding_digit_gate"]: + print(" VERDICT: L6 does NOT hold — the (1−MU)·D gate is absent from the") + print(" chip, so L6-C is the CURRENT STATE, not an ablation.") + elif c: + print(" VERDICT: L6 HOLDS. L6-C is now a genuine ablation of a check the") + print(" chip carries (idx 22..=27); with it present the forgery is UNSAT") + print(" (L6-D). The break this file was written to demonstrate is closed.") + else: + print(" VERDICT: inconclusive — L6-C did not reproduce.") + return 0 if (a and b and c and d and e) else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/gate/l7_pin.py b/thoughts/ec-recover-opt/gate/l7_pin.py new file mode 100644 index 000000000..12bd50c74 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l7_pin.py @@ -0,0 +1,144 @@ +"""L7: end-to-end — the constraint system pins the chip output to the ORACLE's +x(k·P), for concrete (P, k) with symbolic witnesses. + +Method (mod-p class propagation; all z3 queries LINEAR): + Leave every quotient q as a FREE integer (strictly weaker hypothesis than the + chip's q ∈ [0,2^264) — so the pinning conclusion is strictly stronger, and it + makes each relation constrain values mod p only). Then a step's output classes + depend only on the input classes mod p, so the whole chain state is one + (xa, ya) class pair per seed sign. Per step, three z3 UNSAT queries prove + λ / xR / yR ≡ the reference values mod p for ANY byte-representable witness + (the denominators are concrete ⇒ relations linear in the unknown; unknown + ranges [0,2^256) from the AreBytes contracts). + + Seed: xG is canonical (XG_SUB_P, L2c); yG is pinned by the ECSM curve + relations only up to sign — BOTH sign classes are propagated and must + converge to the same drain x (they do: x-only contract). + + Drain: the ECSM row's XR bytes equal the chain's final xR bytes (Ecdas tuple + equality), and XR_SUB_P forces xR < p (L2c) ⇒ the pinned class has exactly + one admissible representative, compared against the oracle. + + Schedule shape is the honest one for k (justified by L6's Bit-balance + argument; l8's N4 probes tampered schedules). + +Reference: thoughts/ec-recover-opt/oracle/ec_ref.py (independent lineage). +""" + +import sys +import time +from pathlib import Path + +import z3 + +sys.path.insert(0, str(Path(__file__).parent)) +sys.path.insert(0, str(Path(__file__).parent.parent / "oracle")) +import ec_ref # the oracle's independent reference +from gate_common import B, N, P, R3P, GEN_X, ref_step + +results = [] +n_queries = 0 +n_unsat = 0 + + +def report(name, verdict, detail=""): + results.append((name, verdict, detail)) + print(f"[{verdict}] {name} {detail}", flush=True) + + +def pin(constraint_fn, expected_mod_p, tag, tamper_note=""): + """UNSAT query: relation(x, q free) ∧ x ∈ [0,2^256) ∧ x ≢ expected (mod P).""" + global n_queries, n_unsat + x, q, gq, gr = z3.Ints("x q gq gr") + s = z3.Solver() + s.set("timeout", 60000) + s.add(constraint_fn(x, q)) + s.add(x >= 0, x < 2**256) # q intentionally FREE (see module docstring) + s.add(x - expected_mod_p == gq * P + gr, gr > 0, gr < P) + r = s.check() + n_queries += 1 + if r == z3.unsat: + n_unsat += 1 + return True + print(f" !! not pinned: {tag} -> {r} {tamper_note}") + return False + + +def schedule(k): + """Honest double/add schedule (round, op, next_op) — mirrors curve.rs:128-148.""" + m = k.bit_length() - 1 + sched = [] + round_, op = m - 1, 0 + while round_ >= 0: + next_op = (1 if (k >> round_) & 1 else 0) if op == 0 else 0 + sched.append((round_, op, next_op)) + rs = round_ - (1 - next_op) + if rs < 0: + break + round_, op = rs, next_op + return sched + + +def run_chain(xg, k, sign, tamper=None): + """Propagate one seed sign class; returns final xR class mod p (or None).""" + y0 = ec_ref.recover_even_y(xg) + yg = y0 if sign == 0 else (-y0) % P + if k == 1: + return xg # drain == seed tuple ⇒ xR = xG bytes (echo) + xa, ya = xg, yg + for t, (rnd, op, next_op) in enumerate(schedule(k)): + lam_s, xr_s, yr_s = ref_step(op, xa, ya, xg, yg) + if op == 1: + rel = lambda x, q: x * (xg - xa) + ya - yg + R3P * P - q * P == 0 + else: + rel = lambda x, q: 2 * x * ya - 3 * xa * xa + R3P * P - q * P == 0 + if not pin(rel, lam_s, f"k={k} t={t} λ"): + return None + lam = lam_s + swap = tamper == ("swap_xa_xg_yr", t) + relx = lambda x, q: (lam * lam - xa - xg - x + - (1 - op) * (xa - xg) + R3P * P - q * P == 0) + if not pin(relx, xr_s, f"k={k} t={t} xR"): + return None + xr = xr_s + ysrc = xg if swap else xa + rely = lambda x, q: lam * (ysrc - xr) - ya - x + R3P * P - q * P == 0 + if not pin(rely, yr_s, f"k={k} t={t} yR", "(tampered)" if swap else ""): + return None + xa, ya = xr, yr_s + return xa + + +def main(): + t0 = time.time() + ks = [1, 2, 3, 5, 6, 7, 11, 21, 33, 42, 45, 63] + points = [GEN_X, + ec_ref.x_only_mul_ints(GEN_X, 2), + ec_ref.x_only_mul_ints(GEN_X, 7)] + all_ok = True + for xg in points: + for k in ks: + finals = set() + for sign in (0, 1): + f = run_chain(xg, k, sign) + if f is None: + all_ok = False + else: + finals.add(f) + expect = ec_ref.x_only_mul_ints(xg, k) + if finals != {expect}: + all_ok = False + report(f"L7 pin [xG=…{xg % 10**6} k={k}]", "FAIL", + f"classes {sorted(finals)} vs oracle {expect}") + if all_ok: + report("L7 end-to-end pinning vs oracle", "PROVED", + f"{len(points)} points × {len(ks)} scalars × 2 sign classes; " + f"{n_queries} linear UNSAT queries all unsat; both sign classes " + f"converge; drain (XR_SUB_P) unique == oracle; {time.time()-t0:.0f}s") + print(f"queries: {n_queries}, unsat: {n_unsat}") + if not all_ok: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/thoughts/ec-recover-opt/gate/l8_negative.py b/thoughts/ec-recover-opt/gate/l8_negative.py new file mode 100644 index 000000000..42277b115 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l8_negative.py @@ -0,0 +1,298 @@ +"""L8: negative + sensitivity controls. + +Two kinds of entry, per the gate methodology: + * GENUINE FORGERIES (non-vacuity): dropping a soundness-load-bearing check + lets a WRONG value pass. Demonstrated CONSTRUCTIVELY (fixed numerals), + never by full-system search. If z3 appears it only CHECKS a concrete + assignment. Establishes the gate is non-vacuous — it catches real bugs. + * REDUNDANCY PROBES: dropping a check does NOT admit a wrong value because + other checks already pin it (keccak IS_BIT-style finding). Reported honestly + as UNSAT/REDUNDANT — not a failure, a finding. + +The N1/N3 carry-check probes use a LINEAR carry gadget (no convolutions): +S_i are free bounded integers (over-approximation of the real per-limb +convolution values, L2a bound 2^22 for the yR relation), the field carry +recurrence is 256·c_i = c_{i−1} + S_i + p_g·m_i (m_i = wrap count), present +checks constrain the c_i, and the attack goal is a decoded value V = Σ256^i·S_i +with V ≢ 0 (mod p_secp) — i.e. a point wrong mod p. This is exactly the +Goldilocks-wrap threat model. Because S is free, UNSAT here is a STRONG +redundancy result (holds even for the over-approx); SAT means the wrap MECHANISM +survives the remaining checks (the dropped check is load-bearing), with the +realizability-by-actual-bytes caveat noted. +""" + +import subprocess +import sys +import time +from pathlib import Path + +import z3 + +sys.path.insert(0, str(Path(__file__).parent)) +sys.path.insert(0, str(Path(__file__).parent.parent / "oracle")) +import ec_ref +from gate_common import ( + N, P, PG, R3P, GEN_X, OFF, P_BYTES, compose, load_witness_json, ref_step, +) + +HARNESS = Path(__file__).parent.parent / "oracle/repo-harness/target/release/ecsm-oracle-harness" +S_BOUND = 2**22 # L2a per-limb |S| bound for the yR relation (measured 4.07e6) +OFF_YR = OFF["ecdas_yr"] +results = [] + + +def report(name, verdict, detail=""): + results.append((name, verdict, detail)) + print(f"[{verdict:16}] {name} {detail}", flush=True) + + +def get_witness(k): + cmd = f"witness {format(GEN_X, 'x')} {format(k, 'x')}\n" + out = subprocess.run([str(HARNESS)], input=cmd, capture_output=True, text=True) + return load_witness_json(out.stdout.strip()) + + +# ── Linear carry gadget for N1 / N3 ────────────────────────────────────────── + +def carry_gadget(dropped): + """dropped ∈ {'c40_window', 'c63_zero'}. Present checks: all c_i windowed for + i in 0..62 and c_63 == 0, MINUS the dropped one. Attack goal: decoded value + V = Σ256^i S_i with V ≢ 0 mod p_secp.""" + s = z3.Solver() + s.set("timeout", 90000) + S = [z3.Int(f"S{i}") for i in range(64)] + c = [z3.Int(f"c{i}") for i in range(64)] + m = [z3.Int(f"m{i}") for i in range(64)] + for i in range(64): + s.add(S[i] >= -S_BOUND, S[i] <= S_BOUND) + s.add(m[i] >= -4, m[i] <= 4) # bounded wrap count + prev = c[i - 1] if i > 0 else 0 + s.add(256 * c[i] == prev + S[i] + PG * m[i]) # field recurrence, lifted + for i in range(63): # window checks c_0..c_62 + if dropped == "c40_window" and i == 40: + continue + s.add(c[i] >= -OFF_YR, c[i] < 65536 - OFF_YR) + if dropped != "c63_zero": # closing constraint + s.add(c[63] == 0) + V = z3.Sum([256**i * S[i] for i in range(64)]) + t, r = z3.Ints("t r") + s.add(V - P * t == r, r >= 1, r <= P - 1) # V mod p ≠ 0 + return s.check() + + +def n1_c40_window(): + t0 = time.time() + res = carry_gadget("c40_window") + if res == z3.unsat: + report("N1 drop IsHalfword(c[40])", "UNSAT/REDUNDANT", + f"mid carry window individually redundant given c₆₃=0 + neighbours " + f"(strong: S free); {time.time()-t0:.0f}s") + elif res == z3.sat: + report("N1 drop IsHalfword(c[40])", "SAT(FORGES)", + f"Goldilocks-wrap at limb 40 survives remaining checks; {time.time()-t0:.0f}s") + else: + report("N1 drop IsHalfword(c[40])", "OPEN(TIMEOUT)", f"{time.time()-t0:.0f}s") + + +def n3_c63_zero(): + t0 = time.time() + res = carry_gadget("c63_zero") + if res == z3.sat: + report("N3 drop ColIsZero(c[63])", "SAT(FORGES)", + f"top overflow unconstrained ⇒ decoded value ≢ 0 mod p; c₆₃=0 LOAD-BEARING; " + f"{time.time()-t0:.0f}s (realizability caveat: gadget over-approx)") + elif res == z3.unsat: + report("N3 drop ColIsZero(c[63])", "UNSAT/REDUNDANT", f"{time.time()-t0:.0f}s") + else: + report("N3 drop ColIsZero(c[63])", "OPEN(TIMEOUT)", f"{time.time()-t0:.0f}s") + + +def gadget_baseline(): + """Sanity: with ALL checks present the gadget is UNSAT (can't decode wrong).""" + t0 = time.time() + s = z3.Solver() + s.set("timeout", 90000) + S = [z3.Int(f"S{i}") for i in range(64)] + c = [z3.Int(f"c{i}") for i in range(64)] + m = [z3.Int(f"m{i}") for i in range(64)] + for i in range(64): + s.add(S[i] >= -S_BOUND, S[i] <= S_BOUND, m[i] >= -4, m[i] <= 4) + prev = c[i - 1] if i > 0 else 0 + s.add(256 * c[i] == prev + S[i] + PG * m[i]) + for i in range(63): + s.add(c[i] >= -OFF_YR, c[i] < 65536 - OFF_YR) + s.add(c[63] == 0) + V = z3.Sum([256**i * S[i] for i in range(64)]) + t, r = z3.Ints("t r") + s.add(V - P * t == r, r >= 1, r <= P - 1) + res = s.check() + report("N1/N3 baseline (all checks ⇒ no wrong decode)", + "UNSAT(OK)" if res == z3.unsat else f"UNEXPECTED-{res}", + f"full window set + c₆₃=0 forces V ≡ 0 mod p; {time.time()-t0:.0f}s") + + +# ── N6: XR_SUB_P drop → non-canonical drain (genuine forgery) ──────────────── + +def n6_xr_sub_p(): + def block(with_check): + s = z3.Solver() + s.set("timeout", 60000) + v = z3.Int("v") + words = [z3.Int(f"w{i}") for i in range(8)] + s.add(v >= 0, v < 2**32) # a small drain x-value + for w in words: + s.add(w >= 0, w < 2**32) + X = z3.Sum([2**(32 * i) * words[i] for i in range(8)]) + mq = z3.Int("mq") + s.add(X - v == mq * P) # bus binds xR ≡ chain x (mod p) + s.add(X >= 0, X < 2**256) + if with_check: + hw = [z3.Int(f"h{i}") for i in range(8)] + carr = [z3.Int(f"cc{i}") for i in range(8)] + for i in range(8): + s.add(hw[i] >= 0, hw[i] < 2**32, z3.Or(carr[i] == 0, carr[i] == 1)) + pw = sum(P_BYTES[4 * i + b] << (8 * b) for b in range(4)) + prev = carr[i - 1] if i > 0 else 0 + s.add(pw + hw[i] + prev - words[i] == 2**32 * carr[i]) + s.add(carr[7] == 1) + s.add(X != v) # non-canonical acceptance + return s.check() + r_with, r_without = block(True), block(False) + ok = r_with == z3.unsat and r_without == z3.sat + report("N6 drop XR_SUB_P", "SAT(FORGES)" if ok else f"UNEXPECTED w={r_with} wo={r_without}", + "present⇒UNSAT (canonical forced); dropped⇒SAT (xR=v+p accepted, v<2^32+977). LOAD-BEARING") + + +# ── NSW: transcription tamper xA↔xG in yR relation (genuine forgery) ───────── + +def nsw(): + st = get_witness(5)["steps"][1] # an ADD step where xA = 2G ≠ G + lam, xa, xg, xr = (compose(st["lambda"]), compose(st["x_a"]), + compose(st["x_g"]), compose(st["x_r"])) + ya, yr = compose(st["y_a"]), compose(st["y_r"]) + x, q, gq, gr = z3.Ints("x q gq gr") + s = z3.Solver() + s.set("timeout", 60000) + s.add(x >= 0, x < 2**256) + s.add(lam * (xg - xr) - ya - x + R3P * P - q * P == 0, q >= 0, q < 2**264) # swapped xA→xG + s.add(x - yr == gq * P + gr, gr > 0, gr < P) # forged yR ≢ honest (mod p) + r = s.check() + if r == z3.sat: + m = s.model() + report("NSW transcription tamper (xA↔xG in yR)", "SAT(FORGES)", + f"tampered relation admits yR=0x{m[x].as_long():x} ≠ honest 0x{yr:x}") + else: + report("NSW transcription tamper", f"UNEXPECTED-{r}") + + +# ── N-CONST: wrong prime rejects the honest witness (genuine, constant-binding) ─ + +def n_const(): + st = get_witness(5)["steps"][1] + lam, xa, xr = compose(st["lambda"]), compose(st["x_a"]), compose(st["x_r"]) + ya, yr, q2 = compose(st["y_a"]), compose(st["y_r"]), compose(st["q2"]) + good = (lam * (xa - xr) - ya - yr + R3P * P - q2 * P) % PG + Pw = P + 2 + bad = (lam * (xa - xr) - ya - yr + (3 * Pw) * Pw - q2 * Pw) % PG + ok = good == 0 and bad != 0 + report("N-CONST wrong-prime (p→p+2)", "SAT(CATCHES)" if ok else f"UNEXPECTED good={good} bad={bad}", + "honest witness: value≡0 under p ✓, value≢0 under p+2 ✓ ⇒ constraints bind the constant") + + +# ── N4: OP·NEXT_OP redundancy (schedule model) ─────────────────────────────── + +def n4_schedule(k, drop_bit_balance): + T = 8 + s = z3.Solver() + s.set("timeout", 120000) + act = [z3.Bool(f"a{t}") for t in range(T)] + rnd = [z3.Int(f"r{t}") for t in range(T)] + op = [z3.Int(f"o{t}") for t in range(T)] + nop = [z3.Int(f"n{t}") for t in range(T)] + m = [z3.Int(f"mm{t}") for t in range(T + 1)] + len_k = z3.Int("len_k") + s.add(len_k >= 0, len_k <= 7, m[0] == 1, act[0]) + s.add(z3.Implies(act[0], z3.And(op[0] == 0, rnd[0] == len_k - 1))) + for t in range(T): + s.add(z3.Or(op[t] == 0, op[t] == 1), z3.Or(nop[t] == 0, nop[t] == 1)) + s.add(rnd[t] >= 0, rnd[t] <= 255) # ROUND byte contract + # OP·NEXT_OP == 0 intentionally OMITTED (the tamper). + out = z3.If(op[t] == 1, m[t] + 1, 2 * m[t]) + s.add(m[t + 1] == z3.If(act[t], out, m[t])) + if t + 1 < T: + s.add(z3.Implies(z3.And(act[t], act[t + 1]), + z3.And(rnd[t + 1] == rnd[t] - 1 + nop[t], op[t + 1] == nop[t]))) + s.add(z3.Implies(z3.Not(act[t]), z3.Not(act[t + 1]))) + s.add(z3.Implies(z3.And(act[t], z3.Not(act[t + 1])), + z3.And(rnd[t] == 0, nop[t] == 0))) + s.add(z3.Implies(act[T - 1], z3.And(rnd[T - 1] == 0, nop[T - 1] == 0))) + if not drop_bit_balance: + for i in range(8): + sends = z3.Sum([z3.If(z3.And(act[t], nop[t] == 1, rnd[t] == i), 1, 0) + for t in range(T)]) + z3.If(len_k == i, 1, 0) + s.add(sends == ((k >> i) & 1)) + s.add(m[T] != k) + return s.check() + + +def n4(): + for k in (6, 11): + t0 = time.time() + r1, r2 = n4_schedule(k, False), n4_schedule(k, True) + if r1 == z3.unsat and r2 == z3.sat: + report(f"N4 drop OP·NEXT_OP [k={k}]", "UNSAT/REDUNDANT", + f"Bit-balance alone blocks AA schedules; +drop balance ⇒ SAT forgery; " + f"{time.time()-t0:.0f}s") + else: + report(f"N4 drop OP·NEXT_OP [k={k}]", f"UNEXPECTED r1={r1} r2={r2}", f"{time.time()-t0:.0f}s") + + +# ── N5: IS_BIT(q1[32]) redundancy (ECSM curve relation) ────────────────────── + +def n5_q1_bit(): + t0 = time.time() + xg = GEN_X + yg, q0m, q1, x2, gq, gr = z3.Ints("yg q0m q1 x2 gq gr") + s = z3.Solver() + s.set("timeout", 90000) + s.add(yg >= 0, yg < 2**256, x2 >= 0, x2 < 2**256) + s.add(q1 >= 0, q1 < 2**264) # FAT quotient (IS_BIT dropped) + s.add(xg * xg - x2 - q0m * P == 0, q0m >= 0, q0m < 2**256) + s.add(yg * yg + P * P - x2 * xg - 7 - q1 * P == 0) + s.add(yg * yg - (pow(xg, 3, P) + 7) == gq * P + gr, gr > 0, gr < P) # deny on-curve + r = s.check() + report("N5 drop IS_BIT(q1[32])", + "UNSAT/REDUNDANT" if r == z3.unsat else f"UNEXPECTED-{r}", + f"curve relation still pins yG²≡xG³+7 with q1<2^264; {time.time()-t0:.0f}s") + + +# ── N7: KBitsZeroOnPadding — rejection-only argument (recorded verdict) ─────── + +def n7(): + report("N7 drop KBitsZeroOnPadding", "UNSAT/REDUNDANT", + "rejection-only: padding k_bits (mult∈{0,1}) can only add unmatched Bit-receives " + "(all padding senders µ/next_op-dead, ecsm.rs:529-540 / ecdas.rs:217-221) ⇒ imbalance; " + "soundness-redundant, keep as completeness hygiene (argument, not search)") + + +if __name__ == "__main__": + gadget_baseline() + n1_c40_window() + n3_c63_zero() + n6_xr_sub_p() + nsw() + n_const() + n4() + n5_q1_bit() + n7() + print("\nSummary:") + for n_, v, d in results: + print(f" {v:16} {n_}") + bad = [v for _, v, _ in results if v.startswith("UNEXPECTED") or v.startswith("OPEN")] + forges = [n_ for n_, v, _ in results if "FORGES" in v or "CATCHES" in v] + redun = [n_ for n_, v, _ in results if "REDUNDANT" in v] + print(f"\nGenuine forgeries/catches (non-vacuity): {len(forges)} -> {forges}") + print(f"Redundancy findings: {len(redun)}") + if bad: + print("UNEXPECTED/OPEN:", bad) + sys.exit(1) diff --git a/thoughts/ec-recover-opt/gate/l8_negative2.py b/thoughts/ec-recover-opt/gate/l8_negative2.py new file mode 100644 index 000000000..060d70bf7 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/l8_negative2.py @@ -0,0 +1,450 @@ +"""L8 (phase E) — negative + sensitivity controls for the lincomb2 chips. + +Methodology carried over from `l8_negative.py`: + + * GENUINE FORGERIES are CONSTRUCTIVE. Fixed numerals; z3 only CHECKS the + assignment. A control that "went SAT" via unbounded search would prove + nothing about realizability. + * REDUNDANCY PROBES that come back UNSAT are findings, not failures. + * Every control is first shown to be BLOCKED on the untampered system, then + re-run with the check ablated. A control that is SAT both ways is broken. + +Two of these controls are not hypothetical: controls 1 and 2 describe holes that +were open in the chip when this gate was written. `chip_state()` is consulted at +run time, and when a check is still missing the control is reported as +**LIVE HOLE** rather than as a passing ablation — the gate refuses to score a +real forgery as an expected result. + +Run: /bin/python l8_negative2.py +""" + +import sys +from pathlib import Path + +import z3 + +sys.path.insert(0, str(Path(__file__).parent)) +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "oracle")) + +import lincomb2_ref +from ec_ref import GX, GY, N, P, pt_add, pt_double, recover_even_y, scalar_mul +from gate2_common import Ecdas2Row, chip_state, print_chip_state + +results = [] +STATE = None + + +def report(name, verdict, detail=""): + results.append((name, verdict, detail)) + print(f"[{verdict:^14}] {name}") + if detail: + for line in detail.splitlines(): + print(f" {line}") + + +def hdr(t): + print() + print("=" * 78) + print(t) + print("=" * 78) + + +# ── control 1: the padding-row phantom digit ──────────────────────────────── + +def control_1(): + """Drop `(1−MU)·D = 0` ⇒ a set scalar bit is consumed with no add on chain. + Driver: the construction in `l6_joint_counting.py` / L6-COUNTING.md §2.3.""" + def query(padding_gate): + s = z3.Solver() + dbl = Ecdas2Row(s, "d", padding_gate=padding_gate) + s.add(dbl.mu == 1, dbl.ph1 == 1, dbl.op == 0, dbl.nb == 0) # no add follows + ph = [Ecdas2Row(s, f"p{i}", padding_gate=padding_gate) for i in range(4)] + for p in ph: + s.add(p.mu == 0, p.round == dbl.round) + s.add(dbl.digit_send(1) + z3.Sum([p.digit_send(1) for p in ph]) == 2) + return s.check() + + with_gate = query(True) + without = query(False) + ok = with_gate == z3.unsat and without == z3.sat + pad = STATE["padding_gate_detail"] + + if not STATE["padding_digit_gate"]: + verdict = "LIVE HOLE" + detail = ("the `(1−MU)·X` gate is NOT in the chip — parsed from the emitted\n" + f"expression, reason: {pad['reason']}\n" + "so this is the current state rather than an ablation.\n" + f"blocked when the gate is added: {with_gate} " + f"reachable without it: {without}") + elif pad["ungated_multiplicities"]: + # The gate exists but a bus multiplicity has escaped it. That is the + # original JointBit bug's exact shape, caught from the multiplicity side. + verdict = "LIVE HOLE" + detail = ("the gate is present but does NOT cover every raw bus\n" + f"multiplicity. UNGATED: {sorted(pad['ungated_multiplicities'])}\n" + "A MU=0 row can still fire those interactions.") + else: + verdict = "SAT — FORGES" if ok else "CONTROL BROKEN" + detail = ("untampered (gate present, chip idx 22..=27): " + f"{with_gate} — blocked\n" + f"ablated: {without} — two MU=0 rows supply a round's 2x JointBit\n" + "count while the chain skips the add entirely.\n" + f"gated columns == raw bus multiplicities: {pad['exact']} " + f"({sorted(pad['gated'])})") + report("N1 drop (1−MU)·D1/D2 — padding-row phantom digit", verdict, detail) + return ok + + +# ── control 2: the degenerate add ─────────────────────────────────────────── + +def control_2(): + """Drop `D_INV·(xB − xA) ≡ 1` ⇒ an add row with xA = xB has an unconstrained + λ. Driver: `nums_blinding_probe.py` — a real, cheap construction.""" + T0, _ = lincomb2_ref.t0_ref() + G = (GX, GY) + # The probe's smallest instance, re-derived here rather than quoted. + length, r_target, u1, u2 = 8, 3, 1, 0b10001000 + alpha, b1, b2 = 1, 0, 0 + for r in range(length - 1, -1, -1): + alpha, b1, b2 = 2 * alpha % N, 2 * b1 % N, 2 * b2 % N + e1, e2 = (u1 >> r) & 1, (u2 >> r) & 1 + if r == r_target: + break + if e1 or e2: + b1, b2 = (b1 + e1) % N, (b2 + e2) % N + mu_scalar = (-alpha * pow((b2 - 1) % N, N - 2, N)) % N + P2 = scalar_mul(mu_scalar, T0) + + # Run the real schedule and find the collision. + acc, hit = T0, None + P12 = pt_add(G, P2) + for r in range(length - 1, -1, -1): + acc = pt_double(acc) + e1, e2 = (u1 >> r) & 1, (u2 >> r) & 1 + if not (e1 or e2): + continue + addend = P12 if (e1 and e2) else (G if e1 else P2) + if acc[0] == addend[0]: + hit = (r, acc, addend) + break + acc = pt_add(acc, addend) + + if hit is None: + report("N2 drop D_INV — degenerate add", "CONTROL BROKEN", + "could not reproduce the collision") + return False + r, acc, addend = hit + same_point = acc == addend + + # With xA = xB and yA = yB the λ relation degenerates: check that the + # relation value is identically zero for TWO different λ (z3 only checks). + lam1, lam2 = 12345, 67890 + def lambda_rel(lam): + return (lam * (addend[0] - acc[0]) + acc[1] - addend[1]) % P + free = lambda_rel(lam1) == 0 and lambda_rel(lam2) == 0 + + # ...and that D_INV would make the row unsatisfiable: no d with + # d·(xB − xA) ≡ 1 (mod p) exists when xB = xA. + d = z3.Int("d") + s = z3.Solver() + s.add(d >= 0, d < P) + s.add((d * ((addend[0] - acc[0]) % P) - 1) % P == 0) + dinv_blocks = s.check() == z3.unsat + + ok = same_point and free and dinv_blocks + gate = STATE["dinv_gate_detail"] + if not STATE["dinv_relation"]: + verdict = "LIVE HOLE" + detail = ("`D_INV` does not protect every addend-consuming row — parsed\n" + f"from the Dinv arm, reason: {gate['reason']}\n" + f"gate columns {sorted(gate['gate'])} vs Addend receive " + f"{sorted(gate['addend'])}\n" + f"collision at round {r}: acc == addend as points: {same_point}\n" + f"λ relation satisfied by two different λ (unconstrained): {free}\n" + f"with a correct D_INV gate the row is unsatisfiable: {dinv_blocks}\n" + "cost to construct: one modular inversion + one scalar mul.\n" + "NOTE a narrowed gate is a DIFFERENT forgery on whichever row\n" + "type it drops — see TRANSCRIPTION-AUDIT.md F1 for the S_CORR\n" + "case, which needs only one point subtraction.") + else: + verdict = "SAT — FORGES" if ok else "CONTROL BROKEN" + detail = ("untampered (D_INV present, chip idx 223..=287): the row is\n" + f"unsatisfiable at the collision ({dinv_blocks}) — blocked\n" + f"ablated: acc == addend as points ({same_point}) and the λ\n" + f"relation admits two different λ ({free}) — forgery reappears\n" + "cost: one modular inversion + one scalar mul\n" + f"gate expression == Addend receive multiplicity: " + f"{gate['matches_addend']} ({sorted(gate['gate'])})") + report("N2 drop D_INV — degenerate add / unconstrained λ", verdict, detail) + return ok + + +# ── control 3: output canonicalisation ────────────────────────────────────── + +def control_3(): + """Drop `xQ < p` (or `yQ < p`) ⇒ the chip may write a +p-shifted coordinate, + which is the same field element but a different 32-byte string, so the guest + keccaks a different address. Same class as the old gate's N6.""" + # Constructive: any v < 2^256 − p = 2^32 + 977 has a second 32-byte encoding. + slack = 2**256 - P + v = 1234 + alt = v + P + both_fit = alt < 2**256 and v < slack + same_mod_p = (alt - v) % P == 0 + different_bytes = v.to_bytes(32, "little") != alt.to_bytes(32, "little") + # the overflow witness 2^256 + v − p is what the check demands; for the + # non-canonical encoding it would have to be 2^256 + alt − p >= 2^256. + witness_ok_for_v = (2**256 + v - P) < 2**256 + witness_fails_for_alt = (2**256 + alt - P) >= 2**256 + + ok = all([both_fit, same_mod_p, different_bytes, witness_ok_for_v, + witness_fails_for_alt]) + report("N3 drop xQ/yQ < p — non-canonical output encoding", + "SAT — FORGES" if ok else "CONTROL BROKEN", + f"v = {v} and v + p both encode in 32 bytes and agree mod p, but differ\n" + f"as bytes, so the guest hashes a different address. The check's\n" + f"overflow witness rejects the shifted form ({witness_fails_for_alt}).\n" + f"reachable for any coordinate below 2^256 − p = 2^32 + 977.") + return ok + + +# ── control 4: addend-selector tamper ─────────────────────────────────────── + +def control_4(): + """Drop idx 18/19 ⇒ a main-chain add may consume an addend its digits do not + select (e.g. digits (1,0) but S2 = 1, adding P2 instead of P1).""" + def query(ablate): + s = z3.Solver() + r = Ecdas2Row(s, "a", ablate=ablate) + s.add(r.mu == 1, r.ph1 == 1, r.op == 1, r.d1 == 1, r.d2 == 0) + s.add(r.s2 == 1) # the wrong addend + return s.check() + + blocked = query(()) + ablated = query((18, 19)) + ok = blocked == z3.unsat and ablated == z3.sat + report("N4 drop PH1·(S1+S3−OP·D1) / (S2+S3−OP·D2) — selector tamper", + "SAT — FORGES" if ok else "CONTROL BROKEN", + f"untampered: {blocked} (digits pin the addend) " + f"ablated: {ablated} (add consumes P2 with digits (1,0))") + return ok + + +def control_4b(): + """Drop `OP = ΣS` on a LIVE off-chain-phase row (precompute or correction). + + Corrected per `TRANSCRIPTION-AUDIT.md` F4. This control used to aim at a + `MU = 0` padding row and build it with `padding_gate=False`, i.e. against a + chip WITHOUT idx 22..=27; it reported `SAT — FORGES` for a forgery the real + chip blocks, because idx 24..=27 zero every selector on a padding row + regardless of idx 14. On the chip's real constraint set that query is UNSAT + both ways — recorded below as the `MU = 0` control line. + + Where idx 14 IS load-bearing is the two live `PH1 = 0` phases, where idx + 17/18/19 are vacuous: without it the precompute or correction row can be an + `OP = 0` doubling that still consumes its addend. + """ + def query(ablate, mu, extra, padding_gate=True, want_model=False): + s = z3.Solver() + r = Ecdas2Row(s, "r", ablate=ablate, padding_gate=padding_gate) + s.add(r.mu == mu) + extra(s, r) + s.add(r.op == 0, r.addend_receive() > 0) # a doubling that eats an addend + v = s.check() + if want_model and v == z3.sat: + m = s.model() + cols = ("mu", "op", "nb", "d1", "d2", "s1", "s2", "s3", "sc", "ph1", "ph2") + return v, " ".join(f"{c.upper()}={m.evaluate(getattr(r, c))}" + for c in cols) + return v, None + + live = { + "precompute (MU=1, PH1=PH2=0)": lambda s, r: s.add(r.ph1 == 0, r.ph2 == 0), + "correction (MU=1, PH2=1)": lambda s, r: s.add(r.ph2 == 1), + } + rows, ok = [], True + for name, extra in live.items(): + blocked, _ = query((), 1, extra) + ablated, witness = query((14,), 1, extra, want_model=True) + rows.append(f"{name:28} untampered {blocked} ablated {ablated}") + if witness: + rows.append(f" forged row: {witness}") + ok &= (blocked == z3.unsat and ablated == z3.sat) + + # the old target, kept as evidence rather than deleted + pad_no_gate, _ = query((14,), 0, lambda s, r: s.add(r.ph1 == 0, r.ph2 == 0), + padding_gate=False) + pad_real, _ = query((14,), 0, lambda s, r: s.add(r.ph1 == 0, r.ph2 == 0), + padding_gate=True) + + report("N4b drop OP = ΣS — addend on a non-add row (live PH1 = 0 phases)", + "SAT — FORGES" if ok else "CONTROL BROKEN", + "\n".join(rows) + "\n" + "Load-bearing on the two LIVE off-chain phases: idx 17/18/19 are\n" + "vacuous at PH1 = 0, so only idx 14 stops an OP = 0 row consuming an\n" + "addend (idx 20 / 21 still force S2 / S_CORR = 1 there).\n" + f"MU = 0 padding row, same ablation: {pad_real} on the real chip " + f"(was {pad_no_gate}\nwithout idx 22..=27) — idx 24..=27 cover that " + "case, not idx 14.") + return ok + + +def control_4c(): + """The same ablation on a LIVE MAIN-CHAIN doubling. Expected UNSAT: idx + 17/18/19 already force ΣS = 0 when PH1 = 1 and OP = 0, so idx 14 is + redundant there. A finding, not a failure — recorded like the old gate's + N1/N4/N5/N7 redundancies.""" + def query(ablate): + s = z3.Solver() + r = Ecdas2Row(s, "d", ablate=ablate) + s.add(r.mu == 1, r.ph1 == 1, r.op == 0) + s.add(r.addend_receive() > 0) + return s.check() + + blocked = query(()) + ablated = query((14,)) + ok = blocked == z3.unsat and ablated == z3.unsat + report("N4c drop OP = ΣS — on a live main-chain doubling", + "UNSAT — REDUNDANT" if ok else "UNEXPECTED", + f"untampered: {blocked} ablated: {ablated}\n" + "PH1 = 1 makes idx 18 (S1+S3 = OP·D1 = 0), idx 19 (S2+S3 = 0) and\n" + "idx 17 (S_CORR = 0) force every selector to zero on their own.\n" + "Keep idx 14 — N4b shows it is what covers the two LIVE PH1 = 0\n" + "phases (padding rows are covered by idx 22..=27, not by idx 14).") + return ok + + +# ── control 5: the status contract ────────────────────────────────────────── + +def control_5(): + """`OK = 0` with `status = 0`. The guest USES the result when status is 0, + so a row that claims success while proving no chain is a forgery. + ECSM2 idx 4 is `MU·(STATUS·S_INV − (1 − OK))`.""" + def query(ablate_idx4): + s = z3.Solver() + mu, ok_c, status, s_inv = (z3.Int(n) for n in ("MU", "OK", "STATUS", "S_INV")) + s.add(z3.Or(mu == 0, mu == 1), z3.Or(ok_c == 0, ok_c == 1)) + s.add(status >= 0, status < (1 << 64)) + s.add(s_inv >= 0, s_inv < (1 << 64)) + s.add(ok_c * (1 - mu) == 0) # idx 2 + s.add(ok_c * status == 0) # idx 3 + if not ablate_idx4: + s.add(mu * (status * s_inv - (1 - ok_c)) == 0) # idx 4 + s.add(mu == 1, ok_c == 0, status == 0) # the attack + return s.check() + + blocked = query(False) + ablated = query(True) + ok = blocked == z3.unsat and ablated == z3.sat + report("N5 drop MU·(STATUS·S_INV − (1−OK)) — status-contract mismatch", + "SAT — FORGES" if ok else "CONTROL BROKEN", + f"untampered: {blocked} (status 0 forces OK = 1, hence a proven chain)\n" + f"ablated: {ablated} (guest consumes an unproven result)") + return ok + + +# ── control 6: the correction constant ────────────────────────────────────── + +def control_6(): + """Drop the `EcT0` lookup ⇒ the correction addend is free, so the prover can + land the chain on any Q it likes. Constructive: solve for the addend that + maps the true accumulator onto a chosen target.""" + T0, _ = lincomb2_ref.t0_ref() + G = (GX, GY) + u1, u2 = 5, 9 + P2 = scalar_mul(7, G) + _q, length, rows = lincomb2_ref.lincomb2_rows(u1, G, u2, P2, T0) + acc = rows[-1]["a"] # accumulator entering the correction + honest = rows[-1]["r"] + target = scalar_mul(0xDEADBEEF, G) # any point the attacker names + + # The addend W with acc + W = target is W = target − acc. + neg_acc = (acc[0], (P - acc[1]) % P) + W = pt_add(target, neg_acc) if target[0] != neg_acc[0] else None + forged = pt_add(acc, W) if W else None + ok = W is not None and forged == target and forged != honest + # and the correct table entry is the only one that yields the honest Q + honest_W = rows[-1]["addend"] + distinct = W != honest_W + report("N6 drop the EcT0 lookup — free correction constant", + "SAT — FORGES" if (ok and distinct) else "CONTROL BROKEN", + f"acc + W = chosen target for W = target − acc: {forged == target}\n" + f"W differs from the table's −2^len·T₀: {distinct}\n" + f"the lookup is what pins the correction addend to `len`.") + return ok and distinct + + +# ── control 7: yP2 < p — expected REDUNDANT ───────────────────────────────── + +def control_7(): + """Drop `yP2 < p`. EXPECTED UNSAT (IMPL-PLAN §11 risk 7): the column is + defence in depth, not a closed forgery. Do not "fix" this result.""" + # The only encodings congruent to yP2 mod p that fit in 32 bytes are yP2 + # itself and yP2 + p, and the latter needs yP2 < 2^256 − p = 2^32 + 977. + slack = 2**256 - P + # For a point on the curve, is a y below the slack even reachable? + reachable = any( + (y * y - (x * x % P) * x - 7) % P == 0 + for x in () + for y in () + ) # not enumerated; the binding argument below is what closes it. + # Binding: the bytes are MEMW-bound to what the guest wrote (contract C4), + # and the guest computes y by field arithmetic, hence < p. So the prover has + # no second encoding available at all. + memw_bound = True + # And crucially, a `< p` test does NOT separate a point from its negation: + y = 0x1234567890ABCDEF + neg = (P - y) % P + both_below_p = y < P and neg < P + report("N7 drop yP2 < p — expected redundancy probe", + "UNSAT — REDUNDANT" if (memw_bound and both_below_p) else "UNEXPECTED", + "EXPECTED result, recorded as evidence not as a failure.\n" + "1. The bytes are MEMW-bound to the guest's write (C4), and the guest\n" + " derives y by field arithmetic, so y < p already holds.\n" + "2. The only other 32-byte encoding congruent mod p is y + p, which\n" + f" needs y < 2^256 − p = {slack}; and it denotes the SAME point.\n" + "3. A `< p` test cannot separate a point from its negation anyway:\n" + f" both y and p − y are below p ({both_below_p}).\n" + " Parity is the guest's authority, backed by MEMW — not this column.\n" + "Keep it as defence in depth (it keeps the chip's argument standing on\n" + "its own constraints), but it closes no forgery.") + return memw_bound and both_below_p + + +def main(): + global STATE + hdr("L8 (phase E) — negative controls for ECSM2 / ECDAS2") + STATE = print_chip_state() + print() + + outcomes = [control_1(), control_2(), control_3(), control_4(), + control_4b(), control_4c(), control_5(), control_6(), control_7()] + + hdr("SUMMARY") + live = [n for n, v, _ in results if v == "LIVE HOLE"] + forge = [n for n, v, _ in results if v == "SAT — FORGES"] + redun = [n for n, v, _ in results if v.startswith("UNSAT")] + broken = [n for n, v, _ in results if v == "CONTROL BROKEN"] + print(f" genuine forgeries (ablation ⇒ SAT) : {len(forge)}") + print(" (was 6 before TRANSCRIPTION-AUDIT F4: the old N4b aimed at a") + print(" MU=0 padding row and was built WITHOUT idx 22..=27, so its SAT") + print(" came from the model, not the chip. Re-pointed at the two live") + print(" PH1=0 phases it is a real forgery again — hence 7, for a") + print(" different reason than the board previously claimed.)") + print(f" redundancy probes (UNSAT) : {len(redun)}") + print(f" LIVE HOLES in the chip right now : {len(live)}") + for n in live: + print(f" - {n}") + print(f" broken controls : {len(broken)}") + for n in broken: + print(f" - {n}") + print() + if live: + print(" The gate is NOT green: the checks that controls 1 and 2 ablate are") + print(" not present in the chip. Re-run once they land; both should flip") + print(" to 'SAT — FORGES' (i.e. genuine ablations of a real defence).") + return 0 if (all(outcomes) and not broken) else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/gate/logs/audit_transcription.log b/thoughts/ec-recover-opt/gate/logs/audit_transcription.log new file mode 100644 index 000000000..bf43304cb --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/audit_transcription.log @@ -0,0 +1,130 @@ + +============================================================================== +A — Ecdas2Row vs an independent transcription of idx 0..=27 (2^11 cases) +============================================================================== + model 11 / chip 11 admitted assignments + [ PASS ] model ⊆ chip (no over-strong boolean constraint) + [ PASS ] chip ⊆ model (no omitted boolean constraint) + [ PASS ] `padding_gate` defaults to the chip (True), not to a weaker model + padding_gate=False still models the pre-fix chip (22 assignments vs 11) — ablations must now opt in explicitly. + +============================================================================== +B — F4: where `OP = ΣS` (idx 14) is actually load-bearing +============================================================================== + [ PASS ] the OLD N4b target (MU=0 padding row) is NOT a forgery on the chip + padding_gate=False (as N4b used to run): sat + padding_gate=True (the chip as written): unsat + idx 24..=27 zero every selector on a MU=0 row regardless of idx 14. + [ PASS ] the NEW N4b target (live PH1=0 phases) IS a forgery + precompute (MU=1, PH1=PH2=0) untampered unsat ablate-14 sat + correction (MU=1, PH2=1) untampered unsat ablate-14 sat + idx 14 stays — the conclusion survives; only the justification was wrong. + +============================================================================== +C — F3: the PORT lemma now covers the prologue, conv_carry, and ECSM2 +============================================================================== + [ PASS ] untampered ECDAS/ECDAS2 port is clean + s_i::Lambda s_i::Xr s_i::Yr s_i::prologue conv_carry rq p_byte_expr r_byte_expr byte_at + [ PASS ] untampered ECSM/ECSM2 membership port is clean + s_i::X2 s_i::Yg s_i::prologue conv_carry p_byte_expr byte_at + This pair was never compared before; the soundness theorem's "P2 is on the curve" clause depends on it. + [ PASS ] a rebound operand column (xa → cols::XR) is DETECTED + flagged: ['s_i::prologue'] + Every value lemma (L3a, L4a/b/c) is false on that chip. This tamper used to report all-identical. + [ PASS ] a broken carry recurrence (dropped c_prev) is DETECTED + L1's telescoping IS this recurrence; conv_carry was never compared before. + [ PASS ] a tampered ECSM2 membership relation is DETECTED + flagged: ['s_i::Yg'] + Without `b` the y² relation no longer pins P2 to the curve. + +============================================================================== +D — F2: the padding gate is parsed, and matched against the multiplicities +============================================================================== + [ PASS ] untampered: gate present, and gated set == raw multiplicity set + gated ['D1', 'D2', 'S1', 'S2', 'S3', 'S_CORR'] + raw multiplicities ['D1', 'D2', 'S1', 'S2', 'S3', 'S_CORR'] + unparsed [] + [ PASS ] deleting the defence while KEEPING its comment is DETECTED + reason: no `(1 - mu) * ` emission found + The old detector matched the comment, so this reported the defence present and scored N1 as a passing ablation. + [ PASS ] a digit send escaping the gate is DETECTED (the original bug's shape) + gated ['S1', 'S2', 'S3', 'S_CORR'] + UNGATED MULTIPLICITY: ['D1', 'D2'] + [ PASS ] a NEW ungated multiplicity column (NB) is DETECTED + UNGATED MULTIPLICITY: ['NB'] + The invariant is an EQUALITY, so it fires on a new raw multiplicity as well as on a deleted gate. That is the direction the original JointBit bug arrived from. + [ PASS ] dropping Dinv from the emit loop is DETECTED + reason: the Dinv block is never emitted by `eval` + The old detector was `"D_INV" in src and "Dinv" in src`, which survives this untouched. + +============================================================================== +E — F1: the D_INV gate is parsed and matched to the Addend receive +============================================================================== + [ PASS ] untampered: gate expression == Addend receive multiplicity + gate ['S1', 'S2', 'S3', 'S_CORR'] + addend ['S1', 'S2', 'S3', 'S_CORR'] + applied as `g * s`: True emitted: True + [ PASS ] dropping S_CORR from the gate is DETECTED + reason: gate ['S1', 'S2', 'S3'] != Addend receive ['S1', 'S2', 'S3', 'S_CORR'] + gate ['S1', 'S2', 'S3'] vs addend ['S1', 'S2', 'S3', 'S_CORR'] + (the PORT check still reports all-identical: True — it excludes the Dinv arm by design, which is exactly why the gate needed an invariant of its own.) + + THE FORGERY (no discrete log — one point subtraction): + u1 = u2 = 1, len = 1, P2 = -2^(len+1)*T0 - G + P2 = (0x6d2601d3ba4652d07eec0066ed211b5cdbdf3c1cf8d0cbe07877b0871e15eb14, + 0x15d65f47ef5cb786daaf7273f57fd2d9d80c4d9a8ac63e0bd716c5bad616431c) + correction row: xA == xB True, yA == yB True + lambda relation identically 0 (free lambda): True + honest Q = (0x3f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b, ...) + forged Q' family: 5 distinct, none honest: True + [ PASS ] with the real gate, the forged correction row is UNSATISFIABLE + d·(xB − xA) = 1 with xB = xA has no solution — the chip as written blocks it. + +============================================================================== +F — the `JointSel → phase_bits/selector_bits` mapping, arm for arm +============================================================================== + [ PASS ] the anchor's hand copy matches the chip's `match` arms + phase_bits : MATCHES + selector_bits : MATCHES + JointSel variants : MATCHES 6 variants, all mapped + [ PASS ] a changed phase_bits arm is DETECTED + chip now maps Correction → (1, 1) while the anchor's dict still says (0, 1), so `check_sel_maps` fails. + RESULTS §7 called this the anchor's last modelled step; it is now machine-checked. + +============================================================================== +G — the detectors fail CLOSED on an unrecognised chip shape +============================================================================== + [ PASS ] an unparsed gate shape reports ABSENT, not present + reason: no `(1 - mu) * ` emission found + A detector that guesses 'probably fine' is the failure mode this file exists to prevent. + [ PASS ] an opaque D_INV gate helper is not silently accepted + present=False reason: the gate is not a plain sum of columns: `gate_expr(b) * b.main(0, cols::S1) + b.main(0, cols::S2) + b.main(0, cols::S3) + b.main(0,` + parsed gate columns ['S1', 'S2', 'S3', 'S_CORR'] + +============================================================================== +SUMMARY +============================================================================== + [ PASS ] model ⊆ chip (no over-strong boolean constraint) + [ PASS ] chip ⊆ model (no omitted boolean constraint) + [ PASS ] `padding_gate` defaults to the chip (True), not to a weaker model + [ PASS ] the OLD N4b target (MU=0 padding row) is NOT a forgery on the chip + [ PASS ] the NEW N4b target (live PH1=0 phases) IS a forgery + [ PASS ] untampered ECDAS/ECDAS2 port is clean + [ PASS ] untampered ECSM/ECSM2 membership port is clean + [ PASS ] a rebound operand column (xa → cols::XR) is DETECTED + [ PASS ] a broken carry recurrence (dropped c_prev) is DETECTED + [ PASS ] a tampered ECSM2 membership relation is DETECTED + [ PASS ] untampered: gate present, and gated set == raw multiplicity set + [ PASS ] deleting the defence while KEEPING its comment is DETECTED + [ PASS ] a digit send escaping the gate is DETECTED (the original bug's shape) + [ PASS ] a NEW ungated multiplicity column (NB) is DETECTED + [ PASS ] dropping Dinv from the emit loop is DETECTED + [ PASS ] untampered: gate expression == Addend receive multiplicity + [ PASS ] dropping S_CORR from the gate is DETECTED + [ PASS ] with the real gate, the forged correction row is UNSATISFIABLE + [ PASS ] the anchor's hand copy matches the chip's `match` arms + [ PASS ] a changed phase_bits arm is DETECTED + [ PASS ] an unparsed gate shape reports ABSENT, not present + [ PASS ] an opaque D_INV gate helper is not silently accepted + + 22/22 checks pass diff --git a/thoughts/ec-recover-opt/gate/logs/c9_constants.log b/thoughts/ec-recover-opt/gate/logs/c9_constants.log new file mode 100644 index 000000000..5494c9fac --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/c9_constants.log @@ -0,0 +1,69 @@ +============================================================================== +C9 PROBE — compile-time curve constants of the joint chain +============================================================================== +T0 (NUMS, tag counter 1) = (0xaf319aa90f91a86b..., 0x1481a038143c0732...) +instance: u1=0xb3d57a1e u2=0x4f2c9e07 P2=7*G len=32 rows=61 + +[baseline] honest EC_T0 table + per-row: 61 rows x (4 relations + 17 schedule) OK + Ecdas bus: 3 segments telescope seed -> drain, round hits -1 + JointBit bus: 512 receives at 2*bit, balanced by the digit sends + Addend bus: N1=11 N2=9 N3=8, correction receive = 1 = OK + EcT0 bus: send key len=32 matches the table row it looks up + chain drains Q = MATCHES u1*G + u2*P2 + => ACCEPTED, correct + +[tamper] A. SIGN FLIP (table stores +2^len*T0; ec_t0.rs:28-41 warns about exactly this) + per-row: 61 rows x (4 relations + 17 schedule) OK + Ecdas bus: 3 segments telescope seed -> drain, round hits -1 + JointBit bus: 512 receives at 2*bit, balanced by the digit sends + Addend bus: N1=11 N2=9 N3=8, correction receive = 1 = OK + EcT0 bus: send key len=32 matches the table row it looks up + Q_chain != Q_true : True + Q_chain is a canonical point : True + Q_true x = 0x722639f922da5252efe11c7444ad4a7071cb313f7d4ac68b16a5b18a9a5f7ba7 + Q_chain x = 0xf2529f1a363bfe05e53f84ce9e375edce112b65f52d32c65246b509dcc4044eb + => ACCEPTED with a WRONG Q. Every constraint and every bus is + satisfied; the only thing that would have caught it is the + correctness of the preprocessed EC_T0 table itself. + +[tamper] B. OFF-BY-ONE (table row for len holds -2^(len+1)*T0; ec_t0.rs:143 index) + per-row: 61 rows x (4 relations + 17 schedule) OK + Ecdas bus: 3 segments telescope seed -> drain, round hits -1 + JointBit bus: 512 receives at 2*bit, balanced by the digit sends + Addend bus: N1=11 N2=9 N3=8, correction receive = 1 = OK + EcT0 bus: send key len=32 matches the table row it looks up + Q_chain != Q_true : True + Q_chain is a canonical point : True + Q_true x = 0x722639f922da5252efe11c7444ad4a7071cb313f7d4ac68b16a5b18a9a5f7ba7 + Q_chain x = 0x6c083e021ea8a269a1d3ff97b6a0601eee4fe6e00d267aa216c31a3770ca4d3a + => ACCEPTED with a WRONG Q. Every constraint and every bus is + satisfied; the only thing that would have caught it is the + correctness of the preprocessed EC_T0 table itself. + +[contrast] wrong GENERATOR_LE — anchored, therefore NOT a forgery + ecsm2.rs:612-629 reads P1 as 8 MEMW doublewords with CONSTANT values. + The tuple must match the memory token the guest wrote at a1, so a + GENERATOR_LE != G makes the Memw bus unbalance: rejection, not forgery. + (Executor-side it returns status 7 -> software fallback -> correct.) + T0 and the EC_T0 rows have NO such anchor: no guest write, no executor + read, no in-circuit curve check. They are pure AIR constants. + +============================================================================== +RESULT: 2/2 tampered constant sets produce an accepted, wrong Q. +The joint chain therefore rests on a contract the board does not name: + C9 the compile-time EC constants (T0, and the 256 EC_T0 rows bound by + the verifier's compiled-in preprocessed commitment) are the + intended, on-curve, mutually consistent values. +Discharged today by TESTS + a static commitment, never by a constraint: + crypto/ecsm/src/tests/lincomb2_tests.rs::t0_is_on_curve_and_pinned + crypto/ecsm/src/tests/lincomb2_tests.rs::t0_derivation_matches + prover/src/tests/ec_t0_tests.rs::every_entry_is_on_curve_and_canonical + prover/src/tests/ec_t0_tests.rs::trace_rows_recompute_from_t0_by_doubling + prover/src/tests/ec_t0_tests.rs::table_matches_lincomb2_witness_correction_row + prover/src/tests/ec_t0_tests.rs::commitment_is_stable_and_matches_the_shipped_static_bytes +Those tests are good and they close BOTH constructions above. The finding +is not that the constants are wrong — it is that the board's contract list +does not say they are load-bearing, so nothing tells a future reader that +those tests are part of the soundness argument rather than hygiene. +============================================================================== diff --git a/thoughts/ec-recover-opt/gate/logs/l1_l2.log b/thoughts/ec-recover-opt/gate/logs/l1_l2.log new file mode 100644 index 000000000..0dc14e0e7 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l1_l2.log @@ -0,0 +1,46 @@ +[PROVED] L1 telescoping [ecsm_x2] 0.0s +[PROVED] L1 telescoping [ecsm_yg] 0.0s +[PROVED] L1 telescoping [ecdas_lambda] 0.0s +[PROVED] L1 telescoping [ecdas_xr] 0.0s +[PROVED] L1 telescoping [ecdas_yr] 0.0s +[PROVED] L2a width [ecsm_x2] max|LHS| = 16826432 = 2^24.. < p_g=2^63.99 (9.12e-13·p_g) +[PROVED] L2a width [ecsm_yg] max|LHS| = 16702249 = 2^23.. < p_g=2^63.99 (9.05e-13·p_g) +[PROVED] L2a width [ecdas_lambda] max|LHS| = 14730340 = 2^23.. < p_g=2^63.99 (7.99e-13·p_g) +[PROVED] L2a width [ecdas_xr] max|LHS| = 18820530 = 2^24.. < p_g=2^63.99 (1.02e-12·p_g) +[PROVED] L2a width [ecdas_yr] max|LHS| = 16723412 = 2^23.. < p_g=2^63.99 (9.07e-13·p_g) +[PROVED] L2a width [ColIsZero/IS_BIT/deg-1 constraints] single-column values < 2^17 < p_g by their own contracts +[PROVED] L2a corner cross-check 9000 sampled corner evaluations inside interval bounds +[PROVED] L2b window [ecsm_x2] honest-bound carries ⊂ [-7949, 8159] vs window [-8160, 57376) +[PROVED] L2b window [ecsm_yg] honest-bound carries ⊂ [-8371, 15894] vs window [-16319, 49217) +[PROVED] L2b window [ecdas_lambda] honest-bound carries ⊂ [-24605, 24137] vs window [-32636, 32900) +[PROVED] L2b window [ecdas_xr] honest-bound carries ⊂ [-256, 15979] vs window [-8161, 57375) +[PROVED] L2b window [ecdas_yr] honest-bound carries ⊂ [-8289, 15978] vs window [-16320, 49216) +[PROVED] L2b audit-control [offset below necessity ⇒ audit fails] per-relation minimal offsets: {'ecsm_x2': 7949, 'ecsm_yg': 8371, 'ecdas_lambda': 24605, 'ecdas_xr': 256, 'ecdas_yr': 8289} (repo offsets {'ecsm_x2': 8160, 'ecsm_yg': 16319, 'ecdas_lambda': 32636, 'ecdas_xr': 8161, 'ecdas_yr': 16320}) +[PROVED] L2b audit-control [r=2p insufficient, r=3p sufficient] q_min(r=2p)=-115792089237316195423570985008687907853269984665640564039457584007908834671658 < 0 ≤ q_min(r=3p)=5 +[PROVED] L2b quotient headroom ECDAS q_max≈2^259, ECSM q1_max≈2^257 +[PROVED] L2c word-carry lift 0.0s +[PROVED] L2c strict-inequality chain 0.0s + +Summary: + PROVED L1 telescoping [ecsm_x2] + PROVED L1 telescoping [ecsm_yg] + PROVED L1 telescoping [ecdas_lambda] + PROVED L1 telescoping [ecdas_xr] + PROVED L1 telescoping [ecdas_yr] + PROVED L2a width [ecsm_x2] + PROVED L2a width [ecsm_yg] + PROVED L2a width [ecdas_lambda] + PROVED L2a width [ecdas_xr] + PROVED L2a width [ecdas_yr] + PROVED L2a width [ColIsZero/IS_BIT/deg-1 constraints] + PROVED L2a corner cross-check + PROVED L2b window [ecsm_x2] + PROVED L2b window [ecsm_yg] + PROVED L2b window [ecdas_lambda] + PROVED L2b window [ecdas_xr] + PROVED L2b window [ecdas_yr] + PROVED L2b audit-control [offset below necessity ⇒ audit fails] + PROVED L2b audit-control [r=2p insufficient, r=3p sufficient] + PROVED L2b quotient headroom + PROVED L2c word-carry lift + PROVED L2c strict-inequality chain diff --git a/thoughts/ec-recover-opt/gate/logs/l1_l5_port2.log b/thoughts/ec-recover-opt/gate/logs/l1_l5_port2.log new file mode 100644 index 000000000..17a8b6632 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l1_l5_port2.log @@ -0,0 +1,107 @@ + +============================================================================== +§1 — L1 / L2 / L3 / L4 / L5a port by relation-body identity +============================================================================== +[ PROVED ] ECDAS2's relation builders are ECDAS's, modulo the XB/YB rename + s_i::Lambda : identical + s_i::Xr : identical + s_i::Yr : identical + s_i::prologue : identical + conv_carry : identical + rq : identical + p_byte_expr : identical + r_byte_expr : identical + byte_at : identical +[ PROVED ] ⇒ L1 (carry telescoping), L2a (per-limb widths), L3a (convolutions capture + the intended polynomial), L3b (chord/tangent stays on curve), L4a/b/c + (λ, xR, yR pinned mod p) and L5a (no 2-torsion) port unchanged + These lemmas quantify over the relation's operands only; renaming an + operand column cannot affect them. The old gate's proofs stand as-is. + The comparison covers the s_i PROLOGUE and `conv_carry` as well as the + three arms: without the prologue a chip whose relations read the WRONG + columns still compares identical (TRANSCRIPTION-AUDIT.md F3). +[ PROVED ] ECSM2's P2-membership relations are ECSM's, modulo the column rename and + the µ → OK gate swap + s_i::X2 : identical + s_i::Yg : identical + s_i::prologue : identical + conv_carry : identical + p_byte_expr : identical + byte_at : identical + OK is IS_BIT and OK·(1−MU) = 0 (ecsm2.rs idx 1, 2), so OK = 1 rows are + a subset of MU = 1 rows and every ECSM membership lemma applies to + them verbatim. `carry_chain` is excluded: ECSM2 has five + OverflowKinds to ECSM's three, so those bodies differ by design + (covered by L8 N3 / N7 instead). + +============================================================================== +§2 — L2b: honest carries of the joint chain fit the existing windows +============================================================================== + (measured in ../oracle/width_audit.py over 6,346 real rows of every + row type, and differentially checked against the prover's own + carries — 38,076 comparisons, 0 mismatches) + + lambda honest [-4303, 6728] window [-32636, 32899] fits + xr honest [-112, 8308] window [-8161, 57374] fits + yr honest [-465, 5914] window [-16320, 49215] fits +[ PROVED ] L2b: the joint chain's honest carries fit the unchanged offsets + The varying addend does not move this: the relations have the same + term counts, and all four addends are canonical for an honest prover. + +============================================================================== +§3 — L5b REPLACED by D_INV·(xB − xA) ≡ 1 (mod p) +============================================================================== + D_INV is present (ECDAS2 idx 223..=287), and its gate expression + is PARSED from the `Relation::Dinv` arm: ['S1', 'S2', 'S3', 'S_CORR'], + which EQUALS the Addend receive's Multiplicity::Linear terms + ['S1', 'S2', 'S3', 'S_CORR']. That equality is what (a1)/(a2) below + quantify over; before TRANSCRIPTION-AUDIT.md F1 nothing checked + it, and dropping S_CORR from the gate was a working forgery. + +[ PROVED ] (a1) OP = (Addend receive multiplicity) on every live row + The chip gates D_INV by ΣS = S1+S2+S3+S_CORR — the very expression + that counts the Addend receive — so the check cannot drift away from + the rows that consume an addend. This lemma shows that gate coincides + with OP on every live row, so it fires exactly on the add rows. +[ PROVED ] (a2) all five addend-consuming row types are covered; doublings are not + AddP1 : consumes an addend = always + AddP2 : consumes an addend = always + AddP12 : consumes an addend = always + Precompute : consumes an addend = always + Correction : consumes an addend = always + Double : consumes an addend = never +[ PROVED ] (b1) D_INV is unsatisfiable whenever xB ≡ xA (mod p) + z3: unsat — p·(d·k − m) = 1 has no integer solution for p > 1. + Covers the non-canonical case too: the relation is mod p, so a + byte-different xB congruent to xA still has (xB − xA) ≡ 0 and no + inverse. The degenerate add becomes UNPROVABLE, not merely unlikely. +[ PROVED ] (b2) D_INV is satisfiable whenever xB ≢ xA (mod p) (completeness) + 204 residues incl. 1, 2, p−1, p−2: the Fermat inverse is a + witness in every case. p is prime (A-PRIME), so the honest prover can + always build the column — the check costs no completeness. +[ PROVED ] (c) the gated-off branch PINS q3 = µ·3p — a doubling is not a hole + z3: unsat. With g = 0 the relation is µ·R·P − q3·P, which telescopes + to p·(µ·R − q3) = 0. Since p ≠ 0, q3 = 3p on a live doubling and 0 on + a padding row — not free. Confirmed on real witnesses too: every + doubling row's Q3 column is exactly 3p with zero carries + (positive_real_witness2.py). +[ PROVED ] (d) L5b's obligation is discharged UNCONDITIONALLY + L4a pins λ given the side condition p ∤ (xB − xA). D_INV *is* that + side condition, witnessed in-circuit. No dlog assumption, no T₀ + reduction, no appeal to the input distribution. + +============================================================================== +SUMMARY +============================================================================== + [PROVED] ECDAS2's relation builders are ECDAS's, modulo the XB/YB rename + [PROVED] ⇒ L1 (carry telescoping), L2a (per-limb widths), L3a (convolutions capture + [PROVED] ECSM2's P2-membership relations are ECSM's, modulo the column rename and + [PROVED] L2b: the joint chain's honest carries fit the unchanged offsets + [PROVED] (a1) OP = (Addend receive multiplicity) on every live row + [PROVED] (a2) all five addend-consuming row types are covered; doublings are not + [PROVED] (b1) D_INV is unsatisfiable whenever xB ≡ xA (mod p) + [PROVED] (b2) D_INV is satisfiable whenever xB ≢ xA (mod p) (completeness) + [PROVED] (c) the gated-off branch PINS q3 = µ·3p — a doubling is not a hole + [PROVED] (d) L5b's obligation is discharged UNCONDITIONALLY + + 10/10 proved diff --git a/thoughts/ec-recover-opt/gate/logs/l3_l4.log b/thoughts/ec-recover-opt/gate/logs/l3_l4.log new file mode 100644 index 000000000..fe17143aa --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l3_l4.log @@ -0,0 +1,26 @@ +[PROVED] A-PRIME certificate isprime(p)=True, isprime(N)=True, N odd=True +[PROVED] L3a composition [ecsm_x2] 3s cumulative +[PROVED] L3a composition [ecsm_yg] 3s cumulative +[PROVED] L3a composition [ecdas_lambda] 3s cumulative +[PROVED] L3a composition [ecdas_xr] 3s cumulative +[PROVED] L3a composition [ecdas_yr] 4s cumulative +[PROVED] L3b on-curve preservation [add] +[PROVED] L3b on-curve preservation [double] +[PROVED] L4a λ-pin [op=1] side: p∤(xG−xA); + A-PRIME closes gr·dr ≡ 0; 0s +[PROVED] L4a λ-pin [op=0] side: p∤2yA; + A-PRIME closes gr·dr ≡ 0; 0s +[PROVED] L4b xR-pin 0s +[PROVED] L4c yR-pin 0s + +Summary: + PROVED A-PRIME certificate + PROVED L3a composition [ecsm_x2] + PROVED L3a composition [ecsm_yg] + PROVED L3a composition [ecdas_lambda] + PROVED L3a composition [ecdas_xr] + PROVED L3a composition [ecdas_yr] + PROVED L3b on-curve preservation [add] + PROVED L3b on-curve preservation [double] + PROVED L4a λ-pin [op=1] + PROVED L4a λ-pin [op=0] + PROVED L4b xR-pin + PROVED L4c yR-pin diff --git a/thoughts/ec-recover-opt/gate/logs/l5.log b/thoughts/ec-recover-opt/gate/logs/l5.log new file mode 100644 index 000000000..11c1f0a49 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l5.log @@ -0,0 +1,8 @@ +[PROVED] L5a no-2-torsion (−7)^((p−1)/3) mod p ≠ 1: True; |E|=N odd: True +[PROVED] L5b incomplete-addition unreachable 0s +[PROVED] L5c x-equal ⇒ y = ±y (mod p) + A-PRIME closes; 5s + +Summary: + PROVED L5a no-2-torsion + PROVED L5b incomplete-addition unreachable + PROVED L5c x-equal ⇒ y = ±y (mod p) diff --git a/thoughts/ec-recover-opt/gate/logs/l6.log b/thoughts/ec-recover-opt/gate/logs/l6.log new file mode 100644 index 000000000..706c6f746 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l6.log @@ -0,0 +1,87 @@ + +========================================================================== +L6-A — per-row schedule constraints (live main-chain rows) +========================================================================== + digits (1,0) force S1 : unsat (forced) + digits (0,1) force S2 : unsat (forced) + digits (1,1) force S3 : unsat (forced) + digits (0,0) on an add : unsat (no spurious add possible) + doubling consumes no addend : unsat (forced) + set digit forces NB = 1 : unsat (forced) + add-after-add impossible (OP·NB) : unsat (forced) + +========================================================================== +L6-B — the 2x JointBit multiplicity vs 1x +========================================================================== + Scenario: round r with u1_bit(r) = u2_bit(r) = 1. The honest chain + has a double and an add, both carrying (D1,D2) = (1,1), so the add + selects S3 = P12. Can a prover make the add select P2 instead? + + multiplicity 1x : sat <-- WRONG ADDEND REACHABLE + multiplicity 2x : unsat (blocked) + + Reading: with 1x the prover splits the two digits across the two + rows (double takes D1, add takes D2), the counts still balance, and + the add adds P2 where the schedule calls for P12 — a wrong Q. + 2x forces BOTH rows to carry BOTH digits, which pins S3. The 2x + claim is CONFIRMED: 2 = 1+1 is the only decomposition because each + row's multiplicity is a single IS_BIT column. + +========================================================================== +L6-C — padding rows as phantom digit senders +========================================================================== + a MU=0 row with D1=1 satisfies all row constraints : sat + round r: u1_bit(r)=1 balanced with NO add on chain : sat + witness: double has D1=0, NB=0 (no add), phantom rows [2, 3] each send D1=1 at the same ROUND + + *** BREAK *** The JointBit send's multiplicity is + `Multiplicity::Column(cols::D1)` (ecdas2.rs:459-470) and NOTHING + ties D1/D2 to MU. A padding row is otherwise inert (its Ecdas, + Addend, AreBytes and IsHalfword interactions are all MU-gated) + but its digit send is LIVE. Two phantom rows per targeted round + satisfy the 2x count while the chain skips the add entirely. + +========================================================================== +L6-D — padding rows as phantom digit senders (WITH the proposed fix) +========================================================================== + a MU=0 row with D1=1 satisfies all row constraints : unsat + round r: u1_bit(r)=1 balanced with NO add on chain : unsat + + With `D1·(1−MU) = 0` / `D2·(1−MU) = 0` added — the exact shape of + `ecdas.rs` idx 4 `NEXT_OP·(1−MU) = 0` — both queries go UNSAT. + +========================================================================== +L6-E — exploitability: steering the recovered key to a chosen target +========================================================================== + target pubkey (a key the attacker does NOT hold): + (0x23bf4e1744fdfd156a2341064785ec43dc87c1b4f2d43b7d6a13594e4efaac14, + 0x8c16a140c01fe7f9cc58cefa98f98fe3777427784aaab244c380f618aa56d8c7) + + u1 = 257 (bit 8 will be dropped), u2 = 1, len = 9 + honest chain Q = (0xe96c41125ef76e4ae487b0184b40a3d0f11f1e4ecc77e0161aa3b3699f72a5a9, ...) + forged chain Q' = (0x23bf4e1744fdfd156a2341064785ec43dc87c1b4f2d43b7d6a13594e4efaac14, ...) + Q' == target : True + Q' != honest Q : True + + ecrecover packaging: z=0xda55048488a946f1f890b1303a55d50a83b37332e24791aa6744d786f806181 + r=0x4ea3b6f8bef87ceea23e38bc30cb8f1337bbfef507e16395bfcbab34c70a338e + s=0x4ea3b6f8bef87ceea23e38bc30cb8f1337bbfef507e16395bfcbab34c70a338e v=0 + guest recomputes u1: True u2: True lifts R: True + + Reading: u1' and u2' are free, so R = target − u1'·G is a plain + point subtraction — NO discrete log is needed. The attacker gets an + ARBITRARY chosen recovered public key, i.e. an arbitrary chosen + transaction sender. This is strictly worse than the NUMS finding, + which only yielded a one-parameter family. + +========================================================================== +SUMMARY +========================================================================== + L6-A per-row schedule forcing : PASS + L6-B 2x multiplicity load-bearing : CONFIRMED + L6-C padding-row digit forgery : REPRODUCED + L6-D proposed fix closes it : YES + L6-E arbitrary chosen sender : DEMONSTRATED + + VERDICT: L6 does NOT hold for ECDAS2 as written. See + ../lincomb2/L6-COUNTING.md. diff --git a/thoughts/ec-recover-opt/gate/logs/l6_joint_counting.log b/thoughts/ec-recover-opt/gate/logs/l6_joint_counting.log new file mode 100644 index 000000000..eb2f132ba --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l6_joint_counting.log @@ -0,0 +1,94 @@ + +========================================================================== +L6-A — per-row schedule constraints (live main-chain rows) +========================================================================== + digits (1,0) force S1 : unsat (forced) + digits (0,1) force S2 : unsat (forced) + digits (1,1) force S3 : unsat (forced) + digits (0,0) on an add : unsat (no spurious add possible) + doubling consumes no addend : unsat (forced) + set digit forces NB = 1 : unsat (forced) + add-after-add impossible (OP·NB) : unsat (forced) + +========================================================================== +L6-B — the 2x JointBit multiplicity vs 1x +========================================================================== + Scenario: round r with u1_bit(r) = u2_bit(r) = 1. The honest chain + has a double and an add, both carrying (D1,D2) = (1,1), so the add + selects S3 = P12. Can a prover make the add select P2 instead? + + multiplicity 1x : sat <-- WRONG ADDEND REACHABLE + multiplicity 2x : unsat (blocked) + + Reading: with 1x the prover splits the two digits across the two + rows (double takes D1, add takes D2), the counts still balance, and + the add adds P2 where the schedule calls for P12 — a wrong Q. + 2x forces BOTH rows to carry BOTH digits, which pins S3. The 2x + claim is CONFIRMED: 2 = 1+1 is the only decomposition because each + row's multiplicity is a single IS_BIT column. + +========================================================================== +L6-C — padding rows as phantom digit senders +========================================================================== + a MU=0 row with D1=1 satisfies all row constraints : sat + round r: u1_bit(r)=1 balanced with NO add on chain : sat + witness: double has D1=0, NB=0 (no add), phantom rows [1, 3] each send D1=1 at the same ROUND + + *** BREAK (ablation) *** The JointBit send's multiplicity is + `Multiplicity::Column(cols::D1)` (ecdas2.rs:601-612) and, before + idx 22..=27, NOTHING tied D1/D2 to MU. A padding row is otherwise + inert (its Ecdas, AreBytes and IsHalfword interactions are all + MU-gated, its Addend receive is ΣS-gated) but its digit send was + LIVE. Two phantom rows per targeted round satisfy the 2x count + while the chain skips the add entirely. + +========================================================================== +L6-D — padding rows as phantom digit senders (WITH the proposed fix) +========================================================================== + a MU=0 row with D1=1 satisfies all row constraints : unsat + round r: u1_bit(r)=1 balanced with NO add on chain : unsat + + With `(1−MU)·{D1, D2, S1, S2, S3, S_CORR} = 0` — the exact shape + of `ecdas.rs` idx 4 `NEXT_OP·(1−MU) = 0` — both queries go UNSAT. + This is `ecdas2.rs:988-1003`, idx 22..=27, in the chip today. + +========================================================================== +L6-E — exploitability: steering the recovered key to a chosen target +========================================================================== + target pubkey (a key the attacker does NOT hold): + (0x23bf4e1744fdfd156a2341064785ec43dc87c1b4f2d43b7d6a13594e4efaac14, + 0x8c16a140c01fe7f9cc58cefa98f98fe3777427784aaab244c380f618aa56d8c7) + + u1 = 257 (bit 8 will be dropped), u2 = 1, len = 9 + honest chain Q = (0xe96c41125ef76e4ae487b0184b40a3d0f11f1e4ecc77e0161aa3b3699f72a5a9, ...) + forged chain Q' = (0x23bf4e1744fdfd156a2341064785ec43dc87c1b4f2d43b7d6a13594e4efaac14, ...) + Q' == target : True + Q' != honest Q : True + + ecrecover packaging: z=0xda55048488a946f1f890b1303a55d50a83b37332e24791aa6744d786f806181 + r=0x4ea3b6f8bef87ceea23e38bc30cb8f1337bbfef507e16395bfcbab34c70a338e + s=0x4ea3b6f8bef87ceea23e38bc30cb8f1337bbfef507e16395bfcbab34c70a338e v=0 + guest recomputes u1: True u2: True lifts R: True + + Reading: u1' and u2' are free, so R = target − u1'·G is a plain + point subtraction — NO discrete log is needed. The attacker gets an + ARBITRARY chosen recovered public key, i.e. an arbitrary chosen + transaction sender. This is strictly worse than the NUMS finding, + which only yielded a one-parameter family. + +========================================================================== +SUMMARY +========================================================================== + chip state: (1−MU)·X gate present = True, D_INV present = True + gated columns ['D1', 'D2', 'S1', 'S2', 'S3', 'S_CORR'] + == raw bus multiplicities ['D1', 'D2', 'S1', 'S2', 'S3', 'S_CORR']: True + + L6-A per-row schedule forcing : PASS + L6-B 2x multiplicity load-bearing : CONFIRMED + L6-C padding-row digit forgery : REPRODUCED + L6-D proposed fix closes it : YES + L6-E arbitrary chosen sender : DEMONSTRATED + + VERDICT: L6 HOLDS. L6-C is now a genuine ablation of a check the + chip carries (idx 22..=27); with it present the forgery is UNSAT + (L6-D). The break this file was written to demonstrate is closed. diff --git a/thoughts/ec-recover-opt/gate/logs/l7.log b/thoughts/ec-recover-opt/gate/logs/l7.log new file mode 100644 index 000000000..2fa6d8cd6 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l7.log @@ -0,0 +1,2 @@ +[PROVED] L7 end-to-end pinning vs oracle 3 points × 12 scalars × 2 sign classes; 990 linear UNSAT queries all unsat; both sign classes converge; drain (XR_SUB_P) unique == oracle; 3s +queries: 990, unsat: 990 diff --git a/thoughts/ec-recover-opt/gate/logs/l8.log b/thoughts/ec-recover-opt/gate/logs/l8.log new file mode 100644 index 000000000..47e335b81 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l8.log @@ -0,0 +1,25 @@ +[UNSAT(OK) ] N1/N3 baseline (all checks ⇒ no wrong decode) full window set + c₆₃=0 forces V ≡ 0 mod p; 76s +[UNSAT/REDUNDANT ] N1 drop IsHalfword(c[40]) mid carry window individually redundant given c₆₃=0 + neighbours (strong: S free); 59s +[SAT(FORGES) ] N3 drop ColIsZero(c[63]) top overflow unconstrained ⇒ decoded value ≢ 0 mod p; c₆₃=0 LOAD-BEARING; 49s (realizability caveat: gadget over-approx) +[SAT(FORGES) ] N6 drop XR_SUB_P present⇒UNSAT (canonical forced); dropped⇒SAT (xR=v+p accepted, v<2^32+977). LOAD-BEARING +[SAT(FORGES) ] NSW transcription tamper (xA↔xG in yR) tampered relation admits yR=0x10e944847da1b419c87b4edc147f2bab568e273a3adba1de07e85b07bf8fa2dd ≠ honest 0x51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922 +[SAT(CATCHES) ] N-CONST wrong-prime (p→p+2) honest witness: value≡0 under p ✓, value≢0 under p+2 ✓ ⇒ constraints bind the constant +[UNSAT/REDUNDANT ] N4 drop OP·NEXT_OP [k=6] Bit-balance alone blocks AA schedules; +drop balance ⇒ SAT forgery; 0s +[UNSAT/REDUNDANT ] N4 drop OP·NEXT_OP [k=11] Bit-balance alone blocks AA schedules; +drop balance ⇒ SAT forgery; 0s +[UNSAT/REDUNDANT ] N5 drop IS_BIT(q1[32]) curve relation still pins yG²≡xG³+7 with q1<2^264; 0s +[UNSAT/REDUNDANT ] N7 drop KBitsZeroOnPadding rejection-only: padding k_bits (mult∈{0,1}) can only add unmatched Bit-receives (all padding senders µ/next_op-dead, ecsm.rs:529-540 / ecdas.rs:217-221) ⇒ imbalance; soundness-redundant, keep as completeness hygiene (argument, not search) + +Summary: + UNSAT(OK) N1/N3 baseline (all checks ⇒ no wrong decode) + UNSAT/REDUNDANT N1 drop IsHalfword(c[40]) + SAT(FORGES) N3 drop ColIsZero(c[63]) + SAT(FORGES) N6 drop XR_SUB_P + SAT(FORGES) NSW transcription tamper (xA↔xG in yR) + SAT(CATCHES) N-CONST wrong-prime (p→p+2) + UNSAT/REDUNDANT N4 drop OP·NEXT_OP [k=6] + UNSAT/REDUNDANT N4 drop OP·NEXT_OP [k=11] + UNSAT/REDUNDANT N5 drop IS_BIT(q1[32]) + UNSAT/REDUNDANT N7 drop KBitsZeroOnPadding + +Genuine forgeries/catches (non-vacuity): 4 -> ['N3 drop ColIsZero(c[63])', 'N6 drop XR_SUB_P', 'NSW transcription tamper (xA↔xG in yR)', 'N-CONST wrong-prime (p→p+2)'] +Redundancy findings: 5 diff --git a/thoughts/ec-recover-opt/gate/logs/l8_negative2.log b/thoughts/ec-recover-opt/gate/logs/l8_negative2.log new file mode 100644 index 000000000..6ce4b8192 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/l8_negative2.log @@ -0,0 +1,84 @@ + +============================================================================== +L8 (phase E) — negative controls for ECSM2 / ECDAS2 +============================================================================== +chip state (PARSED from prover/src/tables/ at run time): + ECDAS2 : 658 columns, 288 constraints + ECSM2 : 1155 columns + JointBit send multiplicity : Multiplicity::Column + (1−MU)·X padding gate present : True + gated columns : ['D1', 'D2', 'S1', 'S2', 'S3', 'S_CORR'] + raw bus multiplicities : ['D1', 'D2', 'S1', 'S2', 'S3', 'S_CORR'] + sets are EQUAL : True + D_INV non-degeneracy present : True + gate expression columns : ['S1', 'S2', 'S3', 'S_CORR'] + Addend receive multiplicity : ['S1', 'S2', 'S3', 'S_CORR'] + gate == Addend receive : True + +[ SAT — FORGES ] N1 drop (1−MU)·D1/D2 — padding-row phantom digit + untampered (gate present, chip idx 22..=27): unsat — blocked + ablated: sat — two MU=0 rows supply a round's 2x JointBit + count while the chain skips the add entirely. + gated columns == raw bus multiplicities: True (['D1', 'D2', 'S1', 'S2', 'S3', 'S_CORR']) +[ SAT — FORGES ] N2 drop D_INV — degenerate add / unconstrained λ + untampered (D_INV present, chip idx 223..=287): the row is + unsatisfiable at the collision (True) — blocked + ablated: acc == addend as points (True) and the λ + relation admits two different λ (True) — forgery reappears + cost: one modular inversion + one scalar mul + gate expression == Addend receive multiplicity: True (['S1', 'S2', 'S3', 'S_CORR']) +[ SAT — FORGES ] N3 drop xQ/yQ < p — non-canonical output encoding + v = 1234 and v + p both encode in 32 bytes and agree mod p, but differ + as bytes, so the guest hashes a different address. The check's + overflow witness rejects the shifted form (True). + reachable for any coordinate below 2^256 − p = 2^32 + 977. +[ SAT — FORGES ] N4 drop PH1·(S1+S3−OP·D1) / (S2+S3−OP·D2) — selector tamper + untampered: unsat (digits pin the addend) ablated: sat (add consumes P2 with digits (1,0)) +[ SAT — FORGES ] N4b drop OP = ΣS — addend on a non-add row (live PH1 = 0 phases) + precompute (MU=1, PH1=PH2=0) untampered unsat ablated sat + forged row: MU=1 OP=0 NB=0 D1=0 D2=0 S1=0 S2=1 S3=0 SC=0 PH1=0 PH2=0 + correction (MU=1, PH2=1) untampered unsat ablated sat + forged row: MU=1 OP=0 NB=0 D1=0 D2=0 S1=0 S2=0 S3=0 SC=1 PH1=0 PH2=1 + Load-bearing on the two LIVE off-chain phases: idx 17/18/19 are + vacuous at PH1 = 0, so only idx 14 stops an OP = 0 row consuming an + addend (idx 20 / 21 still force S2 / S_CORR = 1 there). + MU = 0 padding row, same ablation: unsat on the real chip (was sat + without idx 22..=27) — idx 24..=27 cover that case, not idx 14. +[UNSAT — REDUNDANT] N4c drop OP = ΣS — on a live main-chain doubling + untampered: unsat ablated: unsat + PH1 = 1 makes idx 18 (S1+S3 = OP·D1 = 0), idx 19 (S2+S3 = 0) and + idx 17 (S_CORR = 0) force every selector to zero on their own. + Keep idx 14 — N4b shows it is what covers the two LIVE PH1 = 0 + phases (padding rows are covered by idx 22..=27, not by idx 14). +[ SAT — FORGES ] N5 drop MU·(STATUS·S_INV − (1−OK)) — status-contract mismatch + untampered: unsat (status 0 forces OK = 1, hence a proven chain) + ablated: sat (guest consumes an unproven result) +[ SAT — FORGES ] N6 drop the EcT0 lookup — free correction constant + acc + W = chosen target for W = target − acc: True + W differs from the table's −2^len·T₀: True + the lookup is what pins the correction addend to `len`. +[UNSAT — REDUNDANT] N7 drop yP2 < p — expected redundancy probe + EXPECTED result, recorded as evidence not as a failure. + 1. The bytes are MEMW-bound to the guest's write (C4), and the guest + derives y by field arithmetic, so y < p already holds. + 2. The only other 32-byte encoding congruent mod p is y + p, which + needs y < 2^256 − p = 4294968273; and it denotes the SAME point. + 3. A `< p` test cannot separate a point from its negation anyway: + both y and p − y are below p (True). + Parity is the guest's authority, backed by MEMW — not this column. + Keep it as defence in depth (it keeps the chip's argument standing on + its own constraints), but it closes no forgery. + +============================================================================== +SUMMARY +============================================================================== + genuine forgeries (ablation ⇒ SAT) : 7 + (was 6 before TRANSCRIPTION-AUDIT F4: the old N4b aimed at a + MU=0 padding row and was built WITHOUT idx 22..=27, so its SAT + came from the model, not the chip. Re-pointed at the two live + PH1=0 phases it is a real forgery again — hence 7, for a + different reason than the board previously claimed.) + redundancy probes (UNSAT) : 2 + LIVE HOLES in the chip right now : 0 + broken controls : 0 + diff --git a/thoughts/ec-recover-opt/gate/logs/positive_real_witness2.log b/thoughts/ec-recover-opt/gate/logs/positive_real_witness2.log new file mode 100644 index 000000000..f7e452432 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/logs/positive_real_witness2.log @@ -0,0 +1,9 @@ +POSITIVE ANCHOR + L7 — real lincomb2 witnesses vs the transcribed model + + cases : 265 (256 L7-small, 6 random, 3 edge) + ECDAS2 rows : 5,960 + constraint/range checks : 3,317,087 + L7 Q comparisons : 265 (0 mismatches) + + ALL CHECKS PASS — the transcription is faithful on honest data, + and every drained Q matches enumerated / independent ground truth. diff --git a/thoughts/ec-recover-opt/gate/pairing-equivalence.md b/thoughts/ec-recover-opt/gate/pairing-equivalence.md new file mode 100644 index 000000000..7db20c304 --- /dev/null +++ b/thoughts/ec-recover-opt/gate/pairing-equivalence.md @@ -0,0 +1,87 @@ +# Paired ARE_BYTES rewrite — soundness-preservation argument + +The `feat/ec-arebytes-pairing` rewrite repacks the single-byte range-check sends +of ECSM/ECDAS. This note argues the gate's soundness theorem (RESULTS.md) is +preserved verbatim — no lemma re-run is required — and records the layout. + +## The change (bus repacking only) + +Before: every byte-range check was one `AreBytes` send shaped `[b, 0]` +(196/row in ECDAS, 129/row in ECSM). After: adjacent bytes share one send +`[b_even, b_odd]`: + +| Table | Block | Pairing | +|---|---|---| +| ECDAS | LAMBDA, XR, YR, Q0[..32], Q1[..32], Q2[..32] | (2i, 2i+1), i = 0..16 → 96 sends | +| ECDAS | odd bytes ROUND, Q0[32], Q1[32], Q2[32] | (ROUND, Q0[32]), (Q1[32], Q2[32]) → 2 sends | +| ECSM | X2, Q0, YG, Q1[..32] | (2i, 2i+1), i = 0..16 → 64 sends | +| ECSM | odd byte Q1[32] | rides alone as [Q1[32], 0] → 1 send | + +Interactions/row: **ECDAS 388 → 290, ECSM 579 → 515** (pinned by +`bus_interaction_counts` in prover/src/tests/ecsm_tests.rs). Constraint counts +(413 / 200), NUM_COLUMNS (667 / 521), and every witness value are UNCHANGED — +the diff touches only `bus_interactions()` in ecsm.rs/ecdas.rs and the +mirrored multiplicity collectors `collect_bitwise_from_{ecsm,ecdas}` in +trace_builder.rs (sends and BITWISE multiplicities move together, in the same +tuple order). + +## Why the soundness theorem is unaffected + +1. **The contract is unchanged and covers pairs by construction.** Contract C1 + (RESULTS.md) states: each element of an `AreBytes[x, y]` send is in + [0, 256). Authority: the BITWISE receiver matches BOTH tuple elements + against the precomputed table's X and Y columns (bitwise.rs:783-796), and + `generate_bitwise_row` (bitwise.rs:117-156) enumerates the full 2^20 index + space — every (x, y) with x < 256 ∧ y < 256 exists, and ONLY those. A send + `[a, b]` therefore matches a table row iff a AND b are bytes. The old + `[b, 0]` form was already the special case y = 0 of the same contract + (bitwise.rs:646). +2. **Every gate lemma consumes the contract per column, not per send.** The + width audit (L2), the value lemmas (L3/L4), and the chain argument (L6) + assume exactly "each of these named byte columns is in [0, 255]". The set of + byte columns covered is IDENTICAL before and after (every previously-checked + byte appears in exactly one paired send). No lemma's hypothesis mentions the + [b, 0] shape; the only [b, 0] references in the gate were citation comments, + updated in place (l1_l2_lift.py docstring). Hence no re-run: the models + never encoded send shapes, only the per-column range hypotheses they induce. +3. **Bus balance is preserved by symmetric edits.** Sender side (chip) and + multiplicity side (trace_builder collectors) were changed to the SAME pair + layout and tuple order; the ethrex 5/20-transfer e2e proofs (LogUp balance + over the whole VM) are the executable check of this. +4. **Cross-block pairs are sound.** (ROUND, Q0[32]) and (Q1[32], Q2[32]) pair + bytes from different logical operands. The contract constrains each element + independently — no relation between the two elements is asserted or implied + by an `AreBytes` row (all 2^16 combinations exist in the table), so pairing + unrelated bytes adds no coupling. +5. **Multiplicity aggregation is unchanged in kind.** Multiplicities remain + µ-gated columns; padding rows (µ = 0) still send nothing. The pairs map to + table row index a + 256·b (+ 0·2^16), all of which exist; the honest + collector increments exactly those rows. + +## Effect on cost (the point of the rewrite) + +Aux columns = ⌈interactions/2⌉ ext-3 columns (split_interactions): +- ECDAS: ⌈388/2⌉ = 194 → ⌈290/2⌉ = 145 aux cols ⇒ −49 ext cols = **−147 base + cells/row** of 1103 committed ⇒ **−13.3% ECDAS committed cells**. +- ECSM: ⌈579/2⌉ = 290 → ⌈515/2⌉ = 258 ⇒ −32 ext cols = −96 base cells/row + (4 rows/ecrecover — negligible but free). +- Per ecrecover (~1528 ECDAS rows): ≈ **−225k committed base cells (−13%)**, + plus the matching reduction in LDE/Merkle/FRI work on those aux columns + (keccak precedent: wall-clock beat the cell prediction because removed cells + were all cubic-ext aux). +- BITWISE receiver side: unchanged (same static table; multiplicity counts per + row change, column count doesn't). + +## Verification ledger for this rewrite + +- `bus_interaction_counts` test pins 515/290. +- ECSM battery 15/15 (incl. `test_prove_elfs_ecsm_forged_result_rejected` and + `test_prove_elfs_ecsm_forged_ecdas_mu_rejected` — tamper-reject e2e), + trace_builder 28/28, bitwise 41/41. +- `test_prove_ethrex_5_transfers` (added): real ecrecover workload proves and + verifies with the pairing (44s). 20-transfer variant likewise (see log). +- Full `-p lambda-vm-prover` suite + `make lint` + `cargo fmt`: see final + report / CI. +- NOT wire-identical (aux layout changes) ⇒ cross-version verification does + not apply; the gates above + bench are the evidence, per the keccak + hwsl-inline precedent. diff --git a/thoughts/ec-recover-opt/gate/positive_real_witness.py b/thoughts/ec-recover-opt/gate/positive_real_witness.py new file mode 100644 index 000000000..4aff68d8c --- /dev/null +++ b/thoughts/ec-recover-opt/gate/positive_real_witness.py @@ -0,0 +1,218 @@ +"""Positive control: REAL prover witnesses (crypto/ecsm compute_witness, dumped by +the extended oracle harness) must satisfy every transcribed constraint mod p_g, +every range contract, and every bus-side chaining relation. + +This is the transcription-faithfulness anchor: any sign/index error in +gate_common's S_i builders or in this file's constraint enumeration fails HERE, +on honest data, before any UNSAT verdict is trusted. + +Constraint enumeration mirrors: + ECSM : ecsm.rs eval() idx 0..412 (413 total) [ecsm.rs:829-899] + ECDAS: ecdas.rs eval() idx 0..199 (200 total) [ecdas.rs:416-451] +""" + +import subprocess +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +from gate_common import ( + B, N, P, PG, P_BYTES, N_BYTES, OFF, compose, load_witness_json, + s_ecsm_x2, s_ecsm_yg, s_ecdas_lambda, s_ecdas_xr, s_ecdas_yr, conv_carry, + GEN_X, +) + +HARNESS = Path(__file__).parent.parent / "oracle/repo-harness/target/release/ecsm-oracle-harness" +INV32 = pow(1 << 32, PG - 2, PG) + +checks = 0 +failures = [] + + +def ck(cond, what): + global checks + checks += 1 + if not cond: + failures.append(what) + + +def fe(x): + """Integer -> Goldilocks field element (negatives wrap).""" + return x % PG + + +def eval_ecsm(w): + """All 413 ECSM constraints (µ=1 live row) + range/consistency contracts.""" + n_constraints = 0 + kbits = [(w["k"][b // 8] >> (b % 8)) & 1 for b in range(256)] + mu = 1 + + # idx 0: IS_BIT(MU); idx 1..256: IS_BIT(k); idx 257: KBitsZeroOnPadding. + ck(fe(mu * (1 - mu)) == 0, "ecsm idx0") + n_constraints += 1 + for i in range(256): + ck(fe(kbits[i] * (1 - kbits[i])) == 0, f"ecsm kbit {i}") + n_constraints += 1 + ck(fe(sum(kbits) * (1 - mu)) == 0, "ecsm idx257") + n_constraints += 1 + + # X2 convolution: 64 ConvCarry + ColIsZero(c0[63]). + v = {"xg": w["x_g"], "x2": w["x2"], "q0": w["q0"], "yg": w["y_g"], "q1": w["q1"]} + for i in range(64): + ck(fe(conv_carry(w["c0"], s_ecsm_x2(v, i), i)) == 0, f"ecsm x2 carry {i}") + n_constraints += 1 + ck(w["c0"][63] == 0, "ecsm c0[63]") + n_constraints += 1 + + # Yg convolution: 64 ConvCarry + ColIsZero(c1[63]). + for i in range(64): + ck(fe(conv_carry(w["c1"], s_ecsm_yg(v, i, mu=mu), i)) == 0, f"ecsm yg carry {i}") + n_constraints += 1 + ck(w["c1"][63] == 0, "ecsm c1[63]") + n_constraints += 1 + + # idx 388: IS_BIT(q1[32]). + ck(fe(w["q1"][32] * (1 - w["q1"][32])) == 0, "ecsm q1[32] bit") + n_constraints += 1 + + # Overflow chains (ecsm.rs:786-820, 883-897): xG/bin/python positive_real_witness2.py +""" + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "oracle")) + +import lincomb2_ref +from ec_ref import GX, GY, N, P, pt_add, pt_double, recover_even_y, scalar_mul +from gate_common import OFF, PG, s_ecdas_lambda, s_ecdas_xr, s_ecdas_yr +from gate2_common import joint_sel_maps, lincomb2_witness + +checks = 0 +failures = [] + + +def ck(cond, what): + global checks + checks += 1 + if not cond: + failures.append(what) + + +P_LIMBS = list(P.to_bytes(32, "little")) +R_LIMBS = list((3 * P).to_bytes(33, "little")) + + +def _rq_int(q_limbs, i, mu=1): + """µ·Σ R_j·P_{i−j} − Σ q_j·P_{i−j}, the shared offset term.""" + rp = qp = 0 + for j in range(i + 1): + pij = P_LIMBS[i - j] if i - j < 32 else 0 + rp += (R_LIMBS[j] if j < 33 else 0) * pij + qp += (q_limbs[j] if j < len(q_limbs) else 0) * pij + return mu * rp - qp + + +def le_bytes(int_hex, n=32): + return list(int(int_hex, 16).to_bytes(n, "little")) + + +def hex_bytes(s): + return list(bytes.fromhex(s)) + + +# `Ecdas2Operation::phase_bits` / `selector_bits`, reproduced by hand. +PHASE = {"Precompute": (0, 0), "Correction": (0, 1), + "Double": (1, 0), "AddP1": (1, 0), "AddP2": (1, 0), "AddP12": (1, 0)} +SELECT = {"Double": (0, 0, 0, 0), "AddP1": (1, 0, 0, 0), + "AddP2": (0, 1, 0, 0), "Precompute": (0, 1, 0, 0), + "AddP12": (0, 0, 1, 0), "Correction": (0, 0, 0, 1)} + + +def check_sel_maps(): + """The hand copy above vs the chip's own `match` arms, parsed. + + RESULTS §7 called this "the one remaining modelled gap in the anchor". It no + longer is: the two dicts are compared arm for arm against + `Ecdas2Operation::phase_bits` / `selector_bits`, and against the `JointSel` + variant list, so a changed OR added arm fails here instead of silently + re-deriving a different chip. + """ + chip = joint_sel_maps() + rows = [] + for name, mine, theirs in (("phase_bits", PHASE, chip["phase_bits"]), + ("selector_bits", SELECT, chip["selector_bits"])): + ok = mine == theirs + rows.append((name, ok, "" if ok else f"model {mine} != chip {theirs}")) + ck(ok, f"{name}: hand copy == chip `match` arms") + missing = set(chip["variants"]) - set(PHASE) - set() + unknown = set(PHASE) - set(chip["variants"]) + ck(not missing, f"JointSel variants absent from the model: {sorted(missing)}") + ck(not unknown, f"model names that are not JointSel variants: {sorted(unknown)}") + rows.append(("JointSel variants", not (missing or unknown), + f"{len(chip['variants'])} variants, all mapped")) + return rows + + +def check_row(row, tag): + """All 288 ECDAS2 constraints on one live (MU = 1) row, plus the ranges.""" + sel = row["sel"] + ph1, ph2 = PHASE[sel] + s1, s2, s3, sc = SELECT[sel] + op, nb, d1, d2 = row["op"], row["nb"], row["d1"], row["d2"] + mu = 1 + + # idx 0..=10 — IS_BIT + for nm, val in (("MU", mu), ("OP", op), ("NB", nb), ("D1", d1), ("D2", d2), + ("S1", s1), ("S2", s2), ("S3", s3), ("S_CORR", sc), + ("PH1", ph1), ("PH2", ph2)): + ck(val in (0, 1), f"{tag}: IS_BIT({nm}) = {val}") + + # idx 11..=21 — the schedule constraints, evaluated as integers (all are + # products of small values, so mod p_g is the same as over Z here). + ck(ph1 * ph2 == 0, f"{tag}: idx11 PH1·PH2") + ck(op * nb == 0, f"{tag}: idx12 OP·NB") + ck((1 - op) * (nb - d1 - d2 + d1 * d2) == 0, f"{tag}: idx13 NB = D1∨D2") + ck(op - s1 - s2 - s3 - sc == 0, f"{tag}: idx14 OP = ΣS") + ck((1 - ph1) * d1 == 0, f"{tag}: idx15 (1−PH1)·D1") + ck((1 - ph1) * d2 == 0, f"{tag}: idx16 (1−PH1)·D2") + ck(ph1 * sc == 0, f"{tag}: idx17 PH1·S_CORR") + ck(ph1 * (s1 + s3 - op * d1) == 0, f"{tag}: idx18 addend vs u1 digit") + ck(ph1 * (s2 + s3 - op * d2) == 0, f"{tag}: idx19 addend vs u2 digit") + ck(mu * (1 - ph1 - ph2) * (s2 - 1) == 0, f"{tag}: idx20 precompute adds P2") + ck(ph2 * (sc - 1) == 0, f"{tag}: idx21 correction adds −2^len·T₀") + + # Range contracts: bytes and the byte-checked ROUND. + v = { + "lam": le_bytes(row["lambda"]), "xa": le_bytes(row["x_a"]), + "ya": le_bytes(row["y_a"]), "xg": le_bytes(row["x_b"]), + "yg": le_bytes(row["y_b"]), "xr": le_bytes(row["x_r"]), + "yr": le_bytes(row["y_r"]), + "q0": hex_bytes(row["q0"]), "q1": hex_bytes(row["q1"]), + "q2": hex_bytes(row["q2"]), + } + for nm in ("lam", "xa", "ya", "xg", "yg", "xr", "yr", "q0", "q1", "q2"): + ck(all(0 <= b < 256 for b in v[nm]), f"{tag}: AreBytes({nm})") + ck(0 <= row["round"] < 256, f"{tag}: AreBytes(ROUND)") + + # idx 22..=27 — (1−MU)·x for every column that is a bus multiplicity. + for nm, val in (("D1", d1), ("D2", d2), ("S1", s1), ("S2", s2), + ("S3", s3), ("S_CORR", sc)): + ck((1 - mu) * val == 0, f"{tag}: idx22-27 (1−MU)·{nm}") + + # idx 28..=287 — the four convolution relations. + for relation, builder, cs, off in ( + ("lambda", s_ecdas_lambda, row["c0"], OFF["ecdas_lambda"]), + ("xr", s_ecdas_xr, row["c1"], OFF["ecdas_xr"]), + ("yr", s_ecdas_yr, row["c2"], OFF["ecdas_yr"]), + ): + for i in range(64): + s_i = builder(v, i, op) if relation != "yr" else builder(v, i) + c_i = cs[i] + c_prev = cs[i - 1] if i else 0 + ck((256 * c_i - c_prev - s_i) % PG == 0, + f"{tag}: ConvCarry({relation}, {i})") + ck(cs[63] == 0, f"{tag}: ColIsZero(c_63, {relation})") + for i in range(63): + ck(0 <= cs[i] + off < (1 << 16), + f"{tag}: IsHalfword(c_{i} + {off}, {relation})") + + # The Dinv block (idx 223..=287). `dinv_witness` now lives in + # `crypto/ecsm/src/witness.rs`, so the harness dumps the PROVER'S OWN + # columns: this is a genuine transcription check, not merely a completeness + # check. The group-law derivation is kept alongside as a differential. + # gated: g·(Σ d_j·(xB − xA)_{i−j} − [i=0]) + rq(q3), g = ΣS + g = s1 + s2 + s3 + sc + ck(g == op, f"{tag}: D_INV gate ΣS equals OP") + xb_v = int(row["x_b"], 16) + xa_v = int(row["x_a"], 16) + dl_p = hex_bytes(row["d_inv"]) # prover's columns + q3b_p = hex_bytes(row["q3"]) + c3_p = row["c3"] + ck(all(0 <= b < 256 for b in dl_p + q3b_p), f"{tag}: AreBytes(D_INV, Q3)") + + if g == 1: + delta = (xb_v - xa_v) % P + ck(delta != 0, f"{tag}: D_INV — the add is a genuine chord (xB ≢ xA)") + # independent derivation, then a differential against the prover + d_inv = pow(delta, P - 2, P) + q3 = 3 * P + (d_inv * (xb_v - xa_v) - 1) // P + ck((d_inv * (xb_v - xa_v) - 1) % P == 0, f"{tag}: D_INV numerator ÷ p") + ck(0 <= q3 < (1 << 264), f"{tag}: D_INV quotient fits 33 bytes") + ck(dl_p == list(d_inv.to_bytes(32, "little")), + f"{tag}: D_INV column == independently derived inverse") + ck(q3b_p == list(q3.to_bytes(33, "little")), + f"{tag}: Q3 column == independently derived quotient") + else: + # gated off: only rq survives. It does NOT leave q3 free — telescoping + # gives p·(µ·R − q3) = 0, so q3 is PINNED to 3p on a live doubling. + ck(q3b_p == list((3 * P).to_bytes(33, "little")), + f"{tag}: D_INV gated-off pins Q3 = 3p") + ck(all(c == 0 for c in c3_p), f"{tag}: D_INV gated-off has zero carries") + + # the relation itself, on the prover's columns + at = lambda a, m: a[m] if m < len(a) else 0 + for i in range(64): + si = g * (sum(at(dl_p, j) * (at(v["xg"], i - j) - at(v["xa"], i - j)) + for j in range(i + 1)) - (1 if i == 0 else 0)) + si += _rq_int(q3b_p, i) + c_i = c3_p[i] + c_prev = c3_p[i - 1] if i else 0 + ck((256 * c_i - c_prev - si) % PG == 0, f"{tag}: ConvCarry(dinv, {i})") + ck(c3_p[63] == 0, f"{tag}: ColIsZero(c_63, dinv)") + for i in range(63): + ck(0 <= c3_p[i] + OFF["ecdas_xr"] < (1 << 16), + f"{tag}: IsHalfword(c_{i} + {OFF['ecdas_xr']}, dinv)") + + return 288 + + +def main(): + T0, _ = lincomb2_ref.t0_ref() + G = (GX, GY) + print("POSITIVE ANCHOR + L7 — real lincomb2 witnesses vs the transcribed model") + print() + print(" JointSel → PH*/S* derivation, parsed from the chip:") + for name, ok, note in check_sel_maps(): + print(f" {name:18}: {'MATCHES' if ok else 'DIFFERS'} {note}") + print() + + # ── the corpus ─────────────────────────────────────────────────────────── + cases = [] + # L7: small joint scalars, ground truth by repeated group addition + P2_small = scalar_mul(7, G) + for u1 in range(1, 17): + for u2 in range(1, 17): + cases.append(("L7-small", u1, u2, G, P2_small)) + # random + edge, for the positive anchor's volume + import random + rng = random.Random(90210) + for _ in range(6): + while True: + x = rng.randrange(P) + y = recover_even_y(x) + if y is not None: + break + cases.append(("random", rng.randrange(1, N), rng.randrange(1, N), G, + (x, y if rng.random() < 0.5 else (P - y) % P))) + for u1, u2 in [(1, 1), (N - 1, N - 1), (2**255, 2**255 - 1)]: + cases.append(("edge", u1, u2, G, P2_small)) + + def enumerated_mul(u, pt): + acc = pt + for _ in range(u - 1): + acc = pt_double(acc) if acc == pt else pt_add(acc, pt) + return acc + + rows_seen = 0 + l7_checked = 0 + l7_fail = 0 + for kind, u1, u2, p1, p2 in cases: + w = lincomb2_witness(u1, u2, p1, p2) + q = (int(w["x_q"], 16), int(w["y_q"], 16)) + + for idx, row in enumerate(w["rows"]): + check_row(row, f"{kind} u1={u1:x} u2={u2:x} row{idx}") + rows_seen += 1 + + # ── L7 ─────────────────────────────────────────────────────────────── + if kind == "L7-small": + a, b = enumerated_mul(u1, p1), enumerated_mul(u2, p2) + truth = pt_double(a) if a == b else pt_add(a, b) + l7_checked += 1 + if truth != q: + l7_fail += 1 + failures.append(f"L7: enumerated ground truth != chip Q " + f"(u1={u1}, u2={u2})") + else: + ref = lincomb2_ref.lincomb2(u1, p1, u2, p2) + l7_checked += 1 + if ref != q: + l7_fail += 1 + failures.append(f"L7: reference != chip Q (u1={u1:x}, u2={u2:x})") + + # the drained Q must be canonical (the chip's X_Q_SUB_P / Y_Q_SUB_P) + ck(q[0] < P and q[1] < P, f"{kind}: Q canonical") + # and on the curve + ck((q[1] * q[1] - q[0] ** 3 - 7) % P == 0, f"{kind}: Q on curve") + + print(f" cases : {len(cases)} " + f"({sum(1 for c in cases if c[0] == 'L7-small')} L7-small, " + f"{sum(1 for c in cases if c[0] == 'random')} random, " + f"{sum(1 for c in cases if c[0] == 'edge')} edge)") + print(f" ECDAS2 rows : {rows_seen:,}") + print(f" constraint/range checks : {checks:,}") + print(f" L7 Q comparisons : {l7_checked} ({l7_fail} mismatches)") + print() + if failures: + print(f" FAILURES: {len(failures)}") + for f in failures[:20]: + print(f" {f}") + else: + print(" ALL CHECKS PASS — the transcription is faithful on honest data,") + print(" and every drained Q matches enumerated / independent ground truth.") + return 1 if failures else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/gen_ec_bench.sh b/thoughts/ec-recover-opt/gen_ec_bench.sh new file mode 100755 index 000000000..526638e20 --- /dev/null +++ b/thoughts/ec-recover-opt/gen_ec_bench.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Generate + compile a pure-EC guest: N chained full-ladder ECSM ecalls +# (k = N_secp − 1, the largest valid scalar → ~255 doubles + ~254 adds per call, +# ~509 ECDAS rows), feeding each xR back as the next base point, then commits +# the final xR. N is arg 1; output ELF is arg 2. +# +# A/B usage (mirrors thoughts/keccak-hwsl-inline methodology): build the same +# ELF once, prove it with the baseline and the paired-AreBytes prover builds on +# the bench box, alternating A/B runs. ~2000 calls ≈ 1M ECDAS rows ≈ one 2^20 +# table. Do NOT run benches locally — hand the command to the bench server. +# +# ./gen_ec_bench.sh 2000 /tmp/ec_bench_2000.elf +# +set -euo pipefail +N="${1:?usage: gen_ec_bench.sh N out.elf}" +OUT="${2:?usage: gen_ec_bench.sh N out.elf}" +SRC="$(mktemp /tmp/ec_bench.XXXXXX.s)" +trap 'rm -f "$SRC"' EXIT + +cat > "$SRC" < ecsm_lincomb2 -> ECSM2/ECDAS2 -> keccak(pk) — through the bench +# guest at executor/programs/bench/ecrecover/. +# +# ONE ELF serves every configuration: the workload is chosen by private input, +# so an A/B never compares two different binaries. +# +# *** RUN THIS ON THE BENCH SERVER, NOT LOCALLY. *** A local run on a box that +# has already OOMed on ethrex-20tx produces a misleading number. See BENCH.md. +# +# Subcommands: +# build compile the bench guest ELF +# input write a private-input file (case: mean|worst) +# cells count committed cells (no proving) — the primary +# measurement; prints main, aux and total base cells +# slope cells per ecrecover, from the two-point slope +# (this is the number that answers phase H) +# share EC share of a real block: total cells, and the EC +# contribution implied by the measured slope +# +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +ELF="$ROOT/executor/program_artifacts/bench/ecrecover.elf" +CLI=(cargo run --release -q -p cli --) + +usage() { sed -n '2,28p' "${BASH_SOURCE[0]}"; exit 1; } + +case_byte() { + case "$1" in + mean) echo 0 ;; + worst) echo 1 ;; + *) echo "case must be 'mean' or 'worst'" >&2; exit 1 ;; + esac +} + +# +write_input() { + local c n out + c="$(case_byte "$1")"; n="$2"; out="$3" + if [ "$n" -lt 1 ] || [ "$n" -gt 65535 ]; then + echo "count must be in [1, 65535] (u16 in the guest ABI)" >&2; exit 1 + fi + printf "$(printf '\\x%02x\\x%02x\\x%02x' \ + "$c" "$((n & 0xFF))" "$(((n >> 8) & 0xFF))")" > "$out" +} + +# Total committed BASE field elements. `count-elements` reports main elements and +# aux EXTENSION columns; one extension element is 3 base elements, which is the +# same 1.5-base-cells-per-interaction rule the cost model uses (LogUp packs two +# interactions per aux column). +cells_for() { + local inp out main aux + inp="$(mktemp)"; trap 'rm -f "$inp"' RETURN + write_input "$1" "$2" "$inp" + out="$("${CLI[@]}" count-elements "$ELF" --private-input "$inp")" + main="$(echo "$out" | awk '/^Elements:/ {print $2}')" + aux="$(echo "$out" | awk '/^Aux elements/ {print $4}')" + echo "$main $aux $((main + 3 * aux))" +} + +cmd="${1:-}"; shift || usage +case "$cmd" in + build) + cd "$ROOT" && make compile-bench + ls -l "$ELF" + ;; + + input) + [ $# -eq 3 ] || usage + write_input "$1" "$2" "$3" + echo "wrote $3 (case=$1, n=$2)" + ;; + + cells) + [ $# -eq 2 ] || usage + read -r main aux total <<<"$(cells_for "$1" "$2")" + printf 'case=%s n=%s main=%s aux_ef_cols=%s total_base_cells=%s\n' \ + "$1" "$2" "$main" "$aux" "$total" + ;; + + slope) + [ $# -eq 3 ] || usage + c="$1"; n1="$2"; n2="$3" + read -r _ _ t1 <<<"$(cells_for "$c" "$n1")" + read -r _ _ t2 <<<"$(cells_for "$c" "$n2")" + if [ "$n2" -le "$n1" ]; then echo "n2 must exceed n1" >&2; exit 1; fi + python3 - "$t1" "$t2" "$n1" "$n2" "$c" <<'PY' +import sys +t1, t2, n1, n2, c = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4]), sys.argv[5] +slope = (t2 - t1) / (n2 - n1) +base = 1_467_000 # post-pairing 4x-ecsm_mul baseline, cells/ecrecover +print(f"case={c} n={n1}->{n2} cells {t1} -> {t2}") +print(f" cells per ecrecover : {slope:,.0f} ({slope/1e6:.3f}M)") +print(f" vs 1.467M baseline : {100*(slope-base)/base:+.1f}%") +print(f" fixed overhead : {t1 - slope*n1:,.0f} cells " + f"(EC_T0 + preprocessed + CPU/keccak floor)") +PY + ;; + + share) + [ $# -eq 2 ] || usage + blk="$1"; blk_in="$2" + out="$("${CLI[@]}" count-elements "$blk" --private-input "$blk_in")" + main="$(echo "$out" | awk '/^Elements:/ {print $2}')" + aux="$(echo "$out" | awk '/^Aux elements/ {print $4}')" + echo "block total base cells: $((main + 3 * aux)) (main=$main aux_ef_cols=$aux)" + echo + echo "EC share = n_ecrecover * / total." + echo "n_ecrecover for an ethrex block = one per transaction with a signature;" + echo "read it from the fixture rather than assuming it equals the tx count." + ;; + + *) usage ;; +esac diff --git a/thoughts/ec-recover-opt/lincomb2/BENCH.md b/thoughts/ec-recover-opt/lincomb2/BENCH.md new file mode 100644 index 000000000..d08df84a4 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/BENCH.md @@ -0,0 +1,296 @@ +# Phase H — bench harness + +**Preparation only. Nothing here has been run.** Benches in this project run on +the remote bench server; a local run on a box that has already OOMed on +ethrex-20tx produces a misleading number. + +The harness is built. Below: what each measurement answers, the exact commands +to paste on the bench server, what a good result looks like, and what would +falsify the claim. + +## 0. The headline, and the number NOT to quote + +> **The claim to confirm is −61.9% EC cells at the mean, against the live +> post-pairing baseline.** +> +> | | rows | cells/ecrecover | vs baseline | +> |---|---|---|---| +> | baseline (4× `ecsm_mul`, post-pairing `42ba68ff`) | 4 × 382 | **1.467M** | — | +> | lincomb2, mean | **449.1** | **0.559M** | **−61.9%** | +> | lincomb2, worst case | **514** | **0.640M** | **−56.4%** | + +**Do not quote DESIGN's −74.3%, and do not quote IMPL-PLAN §9's −70.2% either.** +Both are stale, for two different reasons: + +- **−74.3%** is denominated against the *pre-pairing* 1.69M baseline. The + AreBytes pairing already shipped in `42ba68ff`, so quoting it re-banks a win + that is already in the bank. +- **−70.2%** (IMPL-PLAN §9, and its 0.437M figure) is *post-pairing but + pre-`D_INV`*. The non-degeneracy relation that closes the degenerate-add + forgery landed afterwards and costs ~129 logic columns plus ~96 interactions + per ECDAS2 row. **§9 should be updated**; I have not edited it (not mine). + +Recomputing from the chips as they stand: + +``` +ECDAS2 : 658 logic + ⌈388 interactions⌉ ×1.5 = 658 + 582 = 1,240 cells/row +mean : 449.1 × 1,240 + ECSM2 (1 row, ~2.9k) = 0.559M +worst : 514 × 1,240 + ECSM2 = 0.640M +baseline: 4×382×956 + 4×1,439 = 1.466M +``` + +−61.9% is still better than 3× the 2× bar, so the engineering verdict does not +change — but the honest headline moved, and it moved because we bought +unconditional soundness with it. That trade is worth stating explicitly when the +number is reported. + +## 1. What exists + +| | path | what it is | +|---|---|---| +| guest | `executor/programs/bench/ecrecover/` | drives the **real** shipping path: `LambdaVmEcsmCrypto::secp256k1_ecrecover` → guest `(r,v)` decompression → `ecsm_lincomb2` → ECSM2/ECDAS2 → `keccak256(pk)`. Not a synthetic ladder. | +| driver | `thoughts/ec-recover-opt/gen_ecrecover_bench.sh` | `build` / `input` / `cells` / `slope` / `share` | +| (existing) | `thoughts/ec-recover-opt/gen_ec_bench.sh` | the *synthetic* ECSM ladder from the pairing work — left alone | + +**One ELF serves every configuration.** The workload is selected by private +input, so an A/B never compares two different binaries: + +``` +byte 0 case: 0 = mean corpus (8 real RFC 6979 signatures, cycled) + 1 = worst case (u1,u2) = (2^255, 2^255−1), 514 chain rows +bytes 1..3 signature count, little-endian u16 +``` + +The guest commits the XOR of every recovered address — a deterministic function +of the workload, so **the two A/B arms must commit identical bytes.** That is +the cross-check that the switch did not change results. + +The mean corpus is 8 real signatures whose chain lengths average **451.8 rows** +(population mean 449.1; an 8-sample mean scatters). Cycling 8 rather than +repeating 1 keeps the measurement near the mean instead of pinning it to one +signature's bit pattern. + +### Build status + +**The guest compiles and links for the real target** — 228,344-byte ELF at +`executor/program_artifacts/bench/ecrecover.elf`. Compiling is not benching, so +this was done locally; no measurement was taken. + +Two things the build surfaced, both now fixed in-tree and worth knowing if the +guest is ever moved: + +- A guest crate needs its own **`.cargo/config.toml`**. Without + `--cfg getrandom_backend="custom"` the build dies in `getrandom` with + *"target is not supported"* — `lambda-vm-syscalls` pulls it transitively. This + guest uses the `bench/ecsm` form (no `[env]` block); the `rust/ethrex` form + additionally hardcodes `--sysroot=/opt/lambda-vm-sysroot`, which is only + needed for guests with C dependencies and would be a stale path elsewhere. +- If `/opt` is not writable, `make` wants `sudo` for the sysroot. The Makefile's + own tip works: prefix with `SYSROOT_DIR=$HOME/.lambda-vm-sysroot`. + +## 2. The A/B — and an honest problem with it + +**Arm A (old path) cannot be built from the working tree.** As of 18:34 today, +`crypto/ethrex-crypto/src/lib.rs` contains zero occurrences of +`lincomb2_with_oracle`, `solve_y` or `ecsm_oracle` — phase G has switched the +guest. `HEAD` still has them. That file is phase G's; I did not touch it, and +I am not reconstructing the deleted code. + +So the A/B is **across two checkouts, not two branches of one file** — which is +the honest form anyway, since it also captures the executor and chip changes: + +```sh +# find the last commit that still had the old path +OLD=$(git log -1 --format=%H -S 'fn lincomb2_with_oracle' -- crypto/ethrex-crypto/src/lib.rs) +git worktree add /tmp/lincomb2-before "$OLD" + +# the bench guest is new, so copy it into the old checkout (it calls only the +# stable `Crypto::secp256k1_ecrecover` entry point, which exists in both) +cp -r executor/programs/bench/ecrecover /tmp/lincomb2-before/executor/programs/bench/ + +( cd /tmp/lincomb2-before && make compile-bench ) # arm A +( cd . && make compile-bench ) # arm B +``` + +Then run §3 against each. If `$OLD` turns out to be the tip (phase G is still +uncommitted at bench time), arm A is simply `HEAD` — check before assuming. + +**Shortcut**: phase G already saved both guest ELFs — `ethrex_old.elf` and +`ethrex_new.elf` in its scratchpad, verified md5-identical to the installed +build. If they are still around, they spare you the worktree for the *ethrex* +guest. They do not cover the `ecrecover` bench guest (which is new), so the +recipe above is still the reproducible form and the one to use if the artifacts +have been cleaned up. + +**Cycle delta — use the measurement, not DESIGN's estimate.** Phase G measured +**−78,823 guest cycles per ecrecover** on the 5-transfer block and **−78,493** +on the 20-transfer, agreeing to 0.4%. DESIGN predicted 100–150k; the measurement +is **~21% below the low end**. Quote ~78.5k. The secondary win is real but +smaller than advertised, and that belongs in the writeup rather than being +rounded up to the prediction. + +**CI caveat for any before/after that uses a cached ELF.** Five `pr_main.yaml` +cache keys hashed `executor/programs/rust/**` and `syscalls/**` but not +`crypto/ethrex-crypto/**`, which the ethrex guest depends on by path — so CI +would restore a stale `ethrex.elf` and keep proving the old x-only path. Fixed +(cache-key only), but any CI-side comparison taken before that fix landed was +measuring the old path on both arms. Re-run rather than trust such a number. + +**If you would rather not carry a second checkout**, the fallback is a +documented before-number: the baseline row/cell counts are already measured and +recorded (`chips-map.md` census, gate-confirmed), so arm B alone plus the 1.467M +constant answers the question. That is weaker — it infers rather than measures +the baseline — and should be labelled as such if used. + +## 3. Commands to paste on the bench server + +```sh +cd +SYSROOT_DIR=$HOME/.lambda-vm-sysroot \ + ./thoughts/ec-recover-opt/gen_ecrecover_bench.sh build # omit SYSROOT_DIR if /opt is writable + +# (a) the headline: cells per ecrecover, from a two-point slope. +# The slope cancels the fixed overhead (CPU floor, EC_T0, preprocessed +# tables), which a single-point measurement would wrongly attribute to EC. +./thoughts/ec-recover-opt/gen_ecrecover_bench.sh slope mean 64 512 + +# (b) the adversarial shape — 514 rows, not the mean +./thoughts/ec-recover-opt/gen_ecrecover_bench.sh slope worst 64 512 + +# (c) the always-on cost of EC_T0 and the rest of the fixed floor: +# n = 1 is (almost) all overhead; compare against the slope's intercept +./thoughts/ec-recover-opt/gen_ecrecover_bench.sh cells mean 1 + +# (d) the EC share of a real block — the multiplier that turns −61.9% EC cells +# into a whole-prover number. MUST be a real block: see section 4.1. +(cd thoughts/ec-recover-opt/bench-harness && cargo build --release) +./thoughts/ec-recover-opt/bench-harness/target/release/ec-bench-harness \ + executor/program_artifacts/rust/ethrex.elf +``` + +(d) prints every table's committed base cells sorted by cost, marks the EC +tables, and reports the share directly — no `n_ecrecover` bookkeeping. The +harness is standalone, so its first build compiles the prover into its own +target dir (one-time, minutes). + +`slope`, `cells` and `share` all use `cli count-elements`, which builds the trace +and counts committed field elements **without running the STARK proof** — so +they are minutes, not hours, and are not memory-bound the way proving is. Only +run a full `prove` if you want wall-clock as well; the cell count is what the +−61.9% claim is about. + +Total committed base cells = `main + 3 × aux_ef_cols` (one extension element is +3 base elements; LogUp packs two interactions per aux column, which is the same +1.5-base-cells-per-interaction rule the cost model uses). + +## 4.1 The EC share is ONLY meaningful on a real ethrex block + +**Read this before quoting any EC-share number.** Two of the VM's tables are +**fixed size regardless of workload** — BITWISE is a flat 2^16 rows, and PAGE is +fixed per page. On a small guest they swamp everything, and the EC share you +measure is an artefact of the harness rather than a property of the design: + +``` +test_ecsm_lincomb2_full 19.3M cells EC share 4.59% (BITWISE 81.6%, PAGE 13.6%, ECDAS2 4.5%) +fib_iterative_372k 61.1M cells EC share 0.03% +``` + +Neither number is interpretable. On a real block, CPU and MEMW scale with the +work and those fixed costs amortise away. + +**Reading 4.59% off a unit test and reporting it as the whole-prover multiplier +would understate the win by an order of magnitude**, and it would be very hard +to unpick later — the number looks like an answer. This is the same family as +the fallback trap in §5: a harness artefact wearing the shape of a result. + +So: run §3(d) against `ethrex.elf` with a real block fixture, and if you only +have a unit-test guest to hand, **report no share at all** rather than a small +one. + +A smoke run of the §3(d) harness on `ecsm.elf` (a trivial unit-test guest, run +only to check the tool prints — **not** a measurement) reproduces the artefact +exactly: BITWISE 78.34% + PAGE 21.15% = 99.5% of the trace, every EC table under +0.03%. That output is worthless as a share and useful only as a demonstration of +why. + +**One thing to confirm on the real block rather than assume**: the per-table view +also reports `EC_T0` directly, which answers §3(c)'s always-on question — but on +the smoke run it shows ~1k cells, far below the 256 rows × ~66 columns the table +holds. That suggests preprocessed columns are accounted differently from witness +columns (committed once, not per proof). Check how `count_elements_by_table` +treats preprocessed tables before concluding EC_T0 is free. + +## 4. What a good result looks like + +| measurement | expected | tolerance | +|---|---|---| +| (a) mean slope | **≈ 0.559M cells/ecrecover**, **−61.9%** vs 1.467M | ±3% on the slope | +| (b) worst slope | **≈ 0.640M**, **−56.4%** | ±3% | +| (b)/(a) ratio | **≈ 1.145** (514/449.1) | ±2% | +| (c) n=1 overhead | small vs 512× the slope; EC_T0 contributes 256 rows × ~66 cols | — | +| A/B committed output | **byte-identical between arms** | exact | + +The ratio check in row 3 is the cheapest sanity test: it depends only on row +counts, not on the cell model, so if it holds while the absolute numbers miss, +the row schedule is right and the cell model is wrong. + +## 5. What would falsify the claim + +- **Mean slope materially above ~0.6M.** That is the cell model being wrong, not + noise. Report it plainly rather than reframing the target — the same rule + IMPL-PLAN §9 states. +- **Slope ≈ 1.4M, i.e. no improvement.** Almost certainly the *fallback trap* + below rather than a real result. +- **Ratio (b)/(a) ≉ 1.145.** The worst case is not costing what the row model + says, so the row model is wrong somewhere. +- **A/B outputs differ.** A correctness regression in the switch — stop and + escalate; that outranks any performance number. +- **n=1 overhead comparable to the per-signature slope.** The always-on EC_T0 + + preprocessed floor would then be a real cost on every proof, EC or not, and + IMPL-PLAN §9's `include_halt` precedent for a conditionally-included AIR + becomes live. + +### The fallback trap — read this before trusting any number + +`LambdaVmEcsmCrypto` falls back to pure-Rust `ProjectivePoint::lincomb` whenever +the accelerator returns a non-zero status. **The fallback returns the same +answer**, so the committed output cannot detect it — a silently-degraded run +looks correct and benches the wrong path. + +Two ways to catch it, both cheap: + +1. **The slope.** The software path spends its cost in CPU rows, not EC rows. + A slope anywhere near the baseline, or a mean/worst ratio near 1.0 (the + software path does not care about joint digit density), means the precompile + is not being exercised. +2. **Force the issue.** Temporarily make the fallback panic in a scratch build + and confirm the bench still runs. Do not commit that. + +## 6. What I could not do from here + +- ~~A per-table cell breakdown would make §3(d) exact.~~ **CLOSED.** + `prover::count_elements_by_table(elf, private_inputs) -> Vec<(&'static str, + u64, u64)>` now exists (`prover/src/lib.rs:1075`), so §3(d) is direct rather + than inferred. One wrinkle: it is a **library function with no CLI + subcommand**, so `cli count-elements` cannot reach it. Rather than edit shared + code I added `thoughts/ec-recover-opt/bench-harness/` — a standalone crate + (same pattern as `oracle/repo-harness/`) that calls it and prints the sorted + breakdown plus the EC share. **If you would rather have it in the CLI, a + `CountElementsByTable` subcommand is ~15 lines and would build against the + shared target dir instead of a private one** — worth doing if this gets used + more than once. +- **IMPL-PLAN §9's targets are stale** (§0 above). Not my file to edit. +- **The guest joins `make compile-bench`**, which `make compile-programs` and + hence `make test` depend on. It pulls the same pinned ethrex git rev the + `ethrex` guest already uses, so the marginal build cost should be small — but + it is a shared-build side effect, and worth a look before this lands. + +## 7. Provenance of the bench vectors + +Generated with the phase-D0 oracle (`thoughts/ec-recover-opt/oracle/`), not by +hand: 8 RFC 6979 signatures from the `ecdsa` package, recid chosen by checking +which parity recovers the signer, and the worst case constructed by fixing +`(u1, u2) = (2^255, 2^255 − 1)`, picking `R = 3·G`, and back-solving +`z = −u1·r`, `s = u2·r`. The round trip +(`u1 = −z/r`, `u2 = s/r`, `R = lift_x(r)`) is asserted in the generator, so the +guest's own decomposition reproduces the intended scalars. diff --git a/thoughts/ec-recover-opt/lincomb2/CHIP-LAYOUT.md b/thoughts/ec-recover-opt/lincomb2/CHIP-LAYOUT.md new file mode 100644 index 000000000..ff00632a3 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/CHIP-LAYOUT.md @@ -0,0 +1,825 @@ +# lincomb2 chip layout — ECSM′ / ECDAS′ / Addend bus (phase D de-risk) + +Concrete layout spec for phase D, derived by reading the implemented witness +(`crypto/ecsm/src/witness.rs`) and the two live chips +(`prover/src/tables/{ecsm,ecdas}.rs`) line by line. **Doc only — no code changed.** + +Everything below is either (a) read out of the source, or (b) a *proposal* +explicitly labelled as such. Where the witness and a design doc disagree, the +witness wins (IMPL-PLAN §0.2). Where I could not determine something, §7 says so +instead of guessing. + +Baseline read: `ecsm.rs` 911 lines / 667 cols / 413 constraints; `ecdas.rs` 463 +lines / 521 cols / 200 constraints; both at `bc62f00e` with the AreBytes pairing +(`42ba68ff`) already in. + +--- + +## 0. Lead: six findings that change the plan + +Ordered by how much they move the design. (0)–(3) invalidate something currently +written down; (4)–(5) are gaps nobody has costed. + +Findings (4) and (5) were written against the docs and have since been confirmed +independently by the sibling phases — `phase-c-t0table`'s chip header states the +`len ≤ 256` obligation in almost the same words (§0.4), and `phase-b-executor`'s +shipped syscall already takes the shape §0.3 recommends. Where their in-flight +code settles something, I say so rather than leaving it open. + +### 0.0 A register-returned status **is** expressible — correcting my own earlier claim + +I previously reported that a status word returned in a register would need decode +surgery, on the grounds that ECALL decode leaves `write_register = false` +(`prover/src/tables/types.rs:781-785`). The lead folded that into IMPL-PLAN §2 and +§10 item 1 ("Decided: memory — register was tried and is not expressible"). + +**That conclusion is wrong, and the counter-example is already in the tree.** The +COMMIT accelerator overwrites `x10` during its ecall: `commit.rs:29` describes the +interaction as "read+write x10 register (fd=1→count)", and the trace builder emits +it at `trace_builder.rs:1225-1228` — + +```rust +let memw_op = MemwOperation::new(true, reg_addr, new_value, ts, 2, true) // is_register, NEW value +… +register_state.write(10, count, ts); +``` + +`write_register = false` governs the **CPU row's** register-write path. It says +nothing about what an accelerator chip may emit on the MEMW bus, and accelerators +already emit their own register reads and memory writes at their own timestamps +(ECSM's `xR` writes, `trace_builder.rs:919-932` / `ecsm.rs:432-443`). A register +status is one more MEMW send with `is_register = 1` and a new value. + +`phase-b-executor` has already shipped it that way — `ecsm_lincomb2` returns the +status through `inlateout("a0")` (`syscalls/src/syscalls.rs`, new fn). **That is +correct and strictly cheaper** than the memory route: no 8-byte status word in the +output buffer, one fewer doubleword write, and the guest tests a register instead +of a load. IMPL-PLAN §2's ABI block and §10 item 1 should be updated to match what +phase B built, rather than phase B being asked to match the plan. + +The chip-side consequence is in §1 (the output write is 8 doublewords, not 9, plus +one register-write MEMW send) and §4.4 (the `OK`/`STATUS` binding is unchanged — +where the status *lives* does not affect why it must be bound). + +### 0.1 `layout-lock.md` correction #2 is wrong — the `nb_or` column is required + +`layout-lock.md:113-117` deletes DESIGN's `nb_or` helper on the grounds that the +schedule is dense-doubling. Dense doubling is true; the conclusion does not +follow. + +Read the replay (`witness.rs:825-879`): within one iteration the DOUBLE and the +optional ADD **share the same `round`**, and `round` decrements only at the loop +boundary. So the successor round is + +- double row at round `r`, no add follows → next round `r − 1` +- double row at round `r`, add follows → next round `r` +- add row at round `r` → next round `r − 1` + +The double row's successor round therefore depends on *whether an add follows*, +which is not a function of the double row's own columns. Today's ECDAS solves the +identical problem with `NEXT_OP` and the outgoing expression +`round − 1 + next_op` (`ecdas.rs:243-253`). Deleting the equivalent column leaves +`round` free to stall, which lets a prover insert or drop doublings. + +**And the witness does not currently supply it.** All four `joint_row` call sites +(`witness.rs:807`, `:830`, `:863`, `:896`) pass `next_op = 0` — the 5th positional +argument, confirmed against the signature at `witness.rs:725-740`. Likewise +`d1`/`d2` are the *real* digit bits only on the ADD row; the DOUBLE row is given +`0, 0` (`witness.rs:838-840`). So as it stands the double row carries no +information about what follows it. + +**Fix (small, and it does not disturb the phase-A validation):** pass the round's +real `(d1, d2)` to the DOUBLE row as well, and add one materialized column +`nb = d1 ∨ d2 = d1 + d2 − d1·d2` (degree-2 defining constraint). Neither `d1`, +`d2` nor `nb` enters any convolution relation, so no emitted math changes and the +512-case host validation stays valid. Cost: +1 column on ECDAS′ (525 → 526). + +### 0.2 DESIGN §3's justification for `yP2 < p` is incorrect + +DESIGN §3 (`DESIGN.md:113-123`) says a prover submits `yP2' = yP2 + p`, which is +"same point mod p, **opposite parity as bytes**", and concludes the sign of P2 +flips. + +That does not hold. Negation on secp256k1 is `−(x, y) = (x, p − y)`. The value +`y + p` reduces to `y`, so `(x, y + p)` is the *same* point, not its negation — +the chip's relations are all mod p and would compute the identical Q. + +Decisively: **both `y` and `p − y` are already `< p`**, so a `< p` check cannot +separate them. Whatever defends the parity/sign choice, `yP2 < p` is not it. What +actually binds the sign is that `yP2` is read from memory under MEMW and the +guest — proven CPU execution — is the parity authority (`DESIGN.md:103-111`, +guest decompression at `crypto/ethrex-crypto/src/lib.rs:98-104`). + +**Recommendation: keep the check, fix the reason.** The witness already emits +`y_p2_sub_p` (`witness.rs:922`), it costs ~40 cells on a one-row-per-ecrecover +table, and it removes a non-canonical input from the width audit. But phase E +should expect its negative control to come back **UNSAT (no forgery)**, unlike +the `xQ`/`yQ` controls. Predicting that now saves phase E a confusing day. + +`xQ < p` and `yQ < p` are separately and genuinely load-bearing, and DESIGN's +reasoning for *those* is right: the output bytes are written to memory and the +guest keccaks them, so a `+p`-shifted coordinate hashes to a different address. +That is exactly the existing `XR_SUB_P` / N6 argument. + +### 0.3 The witness cannot prove `P1` is on-curve — the ABI must specialize or the witness must grow + +`Lincomb2Witness` (`witness.rs:576-612`) carries `mem_p2` and `y_p2_sub_p` but +**no `mem_p1`, no `x_p1_sub_p`, no `y_p1_sub_p`**. `check_point(p1)` runs in the +executor (`witness.rs:786`) but emits no witness, so the chip has nothing to +constrain P1 with. `layout-lock.md:48` hints at this ("P1=G constant for +ecrecover (chip may hardcode); else membership") but the ABI at +`layout-lock.md:97` and IMPL-PLAN §2 still passes P1 in `a1` as a general point. + +For ecrecover P1 is always the generator (`lib.rs:115`), so specializing is free. +**Recommended: keep `a1` in the ABI, but have ECSM′ bind it with +constant-valued MEMW reads** — `BusValue::constant(...)` for each of the 8 +doublewords, exactly as the Ecall receiver already pins the syscall number +(`ecsm.rs:313-314`). That asserts "memory at `a1` contains exactly G" with **zero +columns and zero constraints**, and P1's on-curve-ness becomes a compile-time +fact. Generalizing later costs +307 columns (64 coords + 225 membership + 16 +canonicalization + 2 address) and a witness extension. + +**Good news on timing:** `phase-b-executor` has already frozen the ABI as +`ecsm_lincomb2(q, p1, p2, u)` with `a1` a general 64-byte `xP1‖yP1`, and that is +**compatible** — the recommendation binds the bytes at `a1` to G on the *chip* +side, so the syscall signature, the executor arm, and the guest call all stay +exactly as built. No phase-B rework. What needs deciding is only whether the chip +asserts `P1 == G` (v1, free) or the witness grows a `mem_p1` block (general, ++307 columns). + +### 0.4 `len ≤ 256` must be constrained by ECSM′, and `len` does not fit a byte + +`len = max(u1.bits(), u2.bits())` (`witness.rs:799`). Since `N ≈ 2^256`, +`len = 256` is the *common* case (`layout-lock.md:16` measures mean 255.7, max +256). Today's analogue `LEN_K` is a `Byte` (`ecsm.rs:47`) holding an MSB +*position* ∈ [0, 255], so it never had this problem. + +**`phase-c-t0table` has since built the table and independently flagged the same +obligation.** Its header (`prover/src/tables/ec_t0.rs:32-39`) reads: + +> "Rows `257..512` are padding: they keep the running `LEN` key (so every row has +> a distinct key) but carry `x = y = 0`, which is not a curve point. A lookup at +> `len > 256` therefore resolves to `(0, 0)` rather than failing. **The consumer +> chip must constrain `len ≤ 256` itself** … This mirrors KECCAK_RC, whose padding +> rows likewise carry out-of-range keys with zeroed payloads." + +So this is a **hard obligation on ECSM′**, not an open question: an unconstrained +`len` silently resolves to the non-curve point `(0, 0)` and the correction row +would "add" it, producing an unblinded and unproven `Q`. The table is keyed by +`len` **directly** (real rows 0..256, `NUM_REAL_ROWS = 257`, `NUM_ROWS = 512`, +`MAX_LEN = 256`), not by `len − 1`. + +**Clean resolution that costs nothing.** Store `LEN_M1 = len − 1 ∈ [0, 255]` as a +byte column (AreBytes-checked like any other byte), and key the T₀ receive with +the expression `LEN_M1 + 1` via a `LinearTerm::Constant(1)` — exactly the way +today's ECSM sends `len_k − 1` on the Ecdas seed (`ecsm.rs:560-566`). The byte +range check then bounds `len ∈ [1, 256]` for free, discharging phase C's +obligation with a range check the chip was paying for anyway. No extra constraint, +no non-byte column. + +### 0.5 Trailing-zero tuple aliasing is real — the joint Bit streams need their own bus id + +The fingerprint accumulator skips zero elements as an optimisation, and the code +says so explicitly (`crypto/stark/src/lookup.rs:672-676`): + +> "Bus elements that are zero on this row contribute nothing — skip the F×E +> multiply. (Covers the constant(0) bus-width padding plus any variable element +> that is zero on this row…)" + +Because each element is weighted by a *positional* α power +(`lookup.rs:624-625`), a tuple `[a, b, c]` and a tuple `[a, b, c, 0]` on the same +bus produce **identical fingerprints**. Tuple-width padding with `constant(0)` is +a designed-in feature, so this is not a bug — but it means arity alone never +separates two chips sharing a `BusId`. + +Old ECDAS sends `Bit[ts_lo, ts_hi, round]` (`ecdas.rs:228-232`) and old ECSM +receives `Bit[ts_lo, ts_hi, i]` (`ecsm.rs:538-544`). Old and new chips coexist +until phase G (IMPL-PLAN §0.1) and can both be live in one proof. If ECDAS′ sends +`Bit[ts, round, stream]` with `stream = 0`, it aliases an old-ECDAS send exactly. + +**Use a distinct bus id for the joint streams** (id 32; 29 goes to Addend), and +make the stream tag `∈ {1, 2}` rather than `{0, 1}` so a trailing zero can never +alias even within the new bus. + +--- + +## 1. ECSM′ column map (1 row per ecrecover) + +Convention: `B` = byte column (AreBytes authority), `HW` = halfword column +(IsHalfword), `bit` = boolean (IS_BIT *constraint*, no bus send), `fe` = raw +field carry (IsHalfword with offset). Offsets are cumulative and assume the +block order shown; they are a proposal, not a constraint. + +Every field of `Lincomb2Witness` (`witness.rs:576-612`) maps to exactly one block. +The rightmost column names the check that bounds it. + +| # | Block | Cols | Offset | Width | Range authority | Witness field | +|---|---|---:|---:|---|---|---| +| 1 | `TIMESTAMP_0/1` | 2 | 0 | packed | MEMW consistency | — | +| 2 | `ADDR_OUT_0/1` (a0) | 2 | 2 | packed | MEMW | — | +| 3 | `ADDR_P2_0/1` (a2) | 2 | 4 | packed | MEMW | — | +| 4 | `ADDR_U_0/1` (a3) | 2 | 6 | packed | MEMW | — | +| 5 | `X_P2`, `Y_P2` | 64 | 8 | B | **inherited**: byte-checked at store time (`store.rs`), same as today's xG/k (`ecsm.rs:470`) | `x_p2`, `y_p2` | +| 6 | `MEM_X2` | 32 | 72 | B | AreBytes (paired) | `mem_p2.x2` | +| 7 | `MEM_Q0` | 32 | 104 | B | AreBytes (paired) | `mem_p2.q0` | +| 8 | `MEM_C0` | 64 | 136 | fe | IsHalfword ×63 + `ColIsZero(c[63])` | `mem_p2.c0` | +| 9 | `MEM_Q1` | 33 | 200 | B | AreBytes ×32 paired + `IS_BIT(q1[32])` | `mem_p2.q1` | +| 10 | `MEM_C1` | 64 | 233 | fe | IsHalfword ×63 + `ColIsZero(c[63])` | `mem_p2.c1` | +| 11 | `Y_P2_SUB_P` | 16 | 297 | HW | IsHalfword ×16 + 7 CarryBit + 1 OverflowRequired | `y_p2_sub_p` | +| 12 | `X_P12`, `Y_P12` | 64 | 313 | B | **inherited** from the precompute row's `XR`/`YR`, byte-checked in ECDAS′ | `x_p12`, `y_p12` | +| 13 | `U1` bits | 256 | 377 | bit | `IS_BIT` ×256 + zero-on-padding | `u1` | +| 14 | `U2` bits | 256 | 633 | bit | `IS_BIT` ×256 + zero-on-padding | `u2` | +| 15 | `U1_SUB_N` | 16 | 889 | HW | IsHalfword ×16 + 8 carry constraints | `u1_sub_n` | +| 16 | `U2_SUB_N` | 16 | 905 | HW | IsHalfword ×16 + 8 carry constraints | `u2_sub_n` | +| 17 | `LEN_M1` | 1 | 921 | B | AreBytes — which *is* the `len ≤ 256` bound; T₀ receive is keyed `LEN_M1 + 1` (§0.4) | `len` (as `len − 1`) | +| 18 | `X_Q`, `Y_Q` | 64 | 922 | B | **inherited** from the correction row's `XR`/`YR` | `x_q`, `y_q` | +| 19 | `X_Q_SUB_P` | 16 | 986 | HW | IsHalfword ×16 + 8 carry constraints | `x_q_sub_p` | +| 20 | `Y_Q_SUB_P` | 16 | 1002 | HW | IsHalfword ×16 + 8 carry constraints | `y_q_sub_p` | +| 21 | `X_T0POW`, `Y_T0POW` | 64 | 1018 | B | **inherited** from the preprocessed T₀ table (constant by construction) | `x_t0_pow`, `y_t0_pow` | +| 22 | `N1`, `N2`, `N3`, `NC` (addend publish counts) | 4 | 1082 | fe | none needed — balance-forced, gate contract C5 (§3) | — (derived) | +| 23 | `STATUS` | 1 | 1086 | fe | bound to `OK` via §4.4; written to **`x10`** by a chip-emitted register MEMW (§0.0) | — (executor) | +| 24 | `S_INV` | 1 | 1087 | fe | §4.4 | — | +| 25 | `OK` | 1 | 1088 | bit | `IS_BIT`; `OK·(1−MU) = 0` | — | +| 26 | `MU` | 1 | 1089 | bit | `IS_BIT` | — | +| | **`NUM_COLUMNS`** | **1,090** | | | | | + +**Fields deliberately given no columns.** `x_p1`/`y_p1` — pinned to G by +constant-valued MEMW reads (§0.3). `x_t0`/`y_t0` — T₀ is a fixed constant +(`witness.rs:482-489`); hardcode it in the constraint body via `b.const_base(...)` +the way `P_BYTES` already is (`ecsm.rs:713`). `steps` — those are ECDAS′ rows. + +**1,090 vs DESIGN's ≈1,310.** The difference is P1 (−64 coords, and no +membership block was ever in the witness to cost) plus DESIGN double-counting +`xP2` canonicalization, which the witness does not emit. ECSM′ is one row per +ecrecover, so this is bookkeeping, not a win — but the count should be honest. + +**Blocks reused verbatim from today's ECSM.** Rows 6–10 are a second copy of the +`X2`/`Q0`/`C0`/`Q1`/`C1` membership machinery (`ecsm.rs:50-54`, relations at +`:742-769`) applied to P2 instead of G — `membership_witness` +(`witness.rs:669-705`) explicitly "reuses the exact `x2` and `yG` convolutions". +Rows 11, 15, 16, 19, 20 are the `XG_SUB_P`/`K_SUB_N`/`XR_SUB_P` pattern +(`ecsm.rs:55-57`, `OverflowKind` `:636-677`, `carry_chain` `:796-830`): 16 +halfword columns each, 16 IsHalfword sends, and 8 constraints (7 × `µ·c_i·(1−c_i)` +degree 3, plus `µ·(1−c_7)` degree 2). The eight word-carries are **virtual** — +computed as expressions with `INV_SHIFT_32`, never stored — which is why a +canonicalization block is only 16 columns. + +--- + +## 2. ECDAS′ column map (1 row per joint step) + +The λ/xR/yR convolution core ports **byte-for-byte**: `Q0/Q1/Q2` +`C0/C1/C2`, +same offsets `CARRY_OFFSET_{LAMBDA,XR,YR}` (`ecdas.rs:24-26`), same `rq()` +shifted-quotient term (`ecdas.rs:332-345`), same `conv_carry` recurrence +(`:400-418`). `witness.rs:466-469` states the same thing from the witness side and +the phase-A tests re-check every emitted row against those relations. + +What changes: `XG/YG` → `XB/YB` (per-row addend), `NEXT_OP` → the joint +bookkeeping block, plus `PHASE`/`NEXT_PHASE` for the segment split (§4.2). + +| # | Block | Cols | Offset | Width | Range authority | Notes | +|---|---|---:|---:|---|---|---| +| 1 | `TIMESTAMP_0/1` | 2 | 0 | packed | chain key | unchanged | +| 2 | `XB`, `YB` (addend) | 64 | 2 | B | **inherited** via Addend-bus tuple equality (§3) — *no new byte checks* | was `XG`/`YG` | +| 3 | `XA`, `YA` (accumulator in) | 64 | 66 | B | inherited via Ecdas′ tuple | unchanged | +| 4 | `ROUND` | 1 | 130 | B | AreBytes, paired with `Q0[32]` | unchanged | +| 5 | `OP` | 1 | 131 | bit | `IS_BIT` | 0 = double, 1 = add | +| 6 | `XR`, `YR` (result) | 64 | 132 | B | AreBytes ×32 paired each | unchanged | +| 7 | `LAMBDA` | 32 | 196 | B | AreBytes ×16 paired | unchanged | +| 8 | `Q0` | 33 | 228 | B | AreBytes | λ relation | +| 9 | `C0` | 64 | 261 | fe | IsHalfword ×63 + `ColIsZero` | λ carries | +| 10 | `Q1` | 33 | 325 | B | AreBytes | xR relation | +| 11 | `C1` | 64 | 358 | fe | IsHalfword ×63 + `ColIsZero` | xR carries | +| 12 | `Q2` | 33 | 422 | B | AreBytes | yR relation | +| 13 | `C2` | 64 | 455 | fe | IsHalfword ×63 + `ColIsZero` | yR carries | +| 14 | `D1`, `D2` | 2 | 519 | bit | `IS_BIT` ×2 | digit bits of **this row's** round — must now be set on DOUBLE rows too (§0.1) | +| 15 | `NB` | 1 | 521 | bit | `IS_BIT` + `NB = D1 + D2 − D1·D2` | the restored `nb_or` (§0.1) | +| 16 | `S1`, `S2`, `S3` | 3 | 522 | bit | `IS_BIT` ×3; defined from `D1`,`D2` on main-chain adds (§3) | one-hot addend {P1, P2, P12} | +| 17 | `S_CORR` | 1 | 525 | bit | `IS_BIT` | correction row consumes the T₀ constant | +| 18 | `PHASE` | 1 | 526 | B | AreBytes (pairs with `Q1[32]`) | 0 = precompute, 1 = main, 2 = correction (§4.2) | +| 19 | `NEXT_PHASE` | 1 | 527 | B | AreBytes (pairs with `Q2[32]`) | rides the outgoing tuple | +| 20 | `MU` | 1 | 528 | bit | `IS_BIT` | live flag | +| | **`NUM_COLUMNS`** | **529** | | | | | + +**529 vs layout-lock's 525.** The delta is +1 `NB` (§0.1), +1 `S_CORR`, +2 +`PHASE`/`NEXT_PHASE` (§4.2), less the `NEXT_OP` that goes away. +0.8% on the +volume table — immaterial to the verdict (§5), but it is a real +4 and layout-lock +should be updated rather than quietly missed. + +**`XB`/`YB` are correctly absent from the AreBytes list.** Today's AreBytes loop +covers exactly `[LAMBDA, XR, YR, Q0, Q1, Q2]` (`ecdas.rs:188-195`) — `XG`/`YG` are +*not* in it, matching `chips-map.md:57` ("equality with seed via Ecdas tuple +matching (NOT re-checked)"). ECDAS′ keeps that list unchanged, so the addend costs +no new range checks. §3 justifies why that is sound for a *varying* addend. + +--- + +## 3. Addend bus spec (bus id 29) + +### 3.1 Registration — three sync points + +`prover/src/tables/types.rs`, id **29** (free: `Ecdas = 28`, `Bit = 30`, +`GlobalMemory = 31`, and 29 is an unassigned gap): + +1. enum variant, `types.rs:255-362` — `Addend = 29,` +2. `BusId::name()`, `types.rs:365-393` — `BusId::Addend => "Addend",` +3. `TryFrom`, `types.rs:396-425` — `29 => Ok(BusId::Addend),` + +Plus id **32** for `JointBit` per §0.5 (same three points). + +### 3.2 Tuple + +``` +Addend[id=29 | ts_lo, ts_hi, sel, x(32), y(32)] +``` +`sel ∈ {1, 2, 3, 4}` — `1 = P1`, `2 = P2`, `3 = P12`, `4 = −2^len·T₀`. +Never 0, so §0.5's trailing-zero aliasing cannot bite even if the tuple is later +widened. Coordinates packed with `point_coord_busvalues` (`ecsm.rs:274`), the same +helper `ecdas_tuple` uses, so publisher and consumer pack identically. + +### 3.3 Publisher — ECSM′, four sends + +```rust +// sel = 1 : P1 (= G, constant-valued) mult = Multiplicity::Column(cols::N1) +// sel = 2 : P2 (from memory) mult = Multiplicity::Column(cols::N2) +// sel = 3 : P12 (from the precompute row) mult = Multiplicity::Column(cols::N3) +// sel = 4 : −2^len·T₀ (from the T₀ table) mult = Multiplicity::Column(cols::NC) +``` +`N1`/`N2`/`N3`/`NC` are witnessed counts (§1 row 22). `NC` is additionally +constrained `= OK` (exactly one correction row per proven ecall). + +### 3.4 Consumer — ECDAS′, one receive + +```rust +BusInteraction::receiver( + BusId::Addend, + Multiplicity::Linear(vec![ // S1 + S2 + S3 + S_CORR + LinearTerm::Column { coefficient: 1, column: cols::S1 }, + LinearTerm::Column { coefficient: 1, column: cols::S2 }, + LinearTerm::Column { coefficient: 1, column: cols::S3 }, + LinearTerm::Column { coefficient: 1, column: cols::S_CORR }, + ]), + vec![ts_lo(), ts_hi(), sel_expr(), /* XB 32 */, /* YB 32 */], +) +``` +with +``` +sel_expr = 1·S1 + 2·S2 + 3·S3 + 4·S_CORR (degree 1, linear in tuple-bound bits) +``` + +**Note this is `Linear`, not `Sum3`.** The brief specifies `Sum3(s1,s2,s3)` +(`lookup.rs:1350`), which covers the three scalar addends but leaves the +correction row unable to receive. `Multiplicity::Linear` (`lookup.rs:1356`) takes +the fourth term at no extra cost — still one interaction. + +The **precompute row uses `sel = 2`** (its addend genuinely is P2, `witness.rs:807` +passes `p2` as the addend). So `N2` counts every P2 add *plus one* for the +precompute. That is fine: counts are witnessed and balance-forced. + +### 3.5 Why balance forces correctness + +The receive is keyed by `[ts, sel, x, y]` and multiplicities are non-negative +witnessed counts, so LogUp balance on bus 29 gives, per `ts`: + +> for each `sel`, the number of ECDAS′ rows receiving `(sel, x, y)` equals the +> count ECSM′ published for that `sel` — **and the coordinates must match +> exactly**, because `x`/`y` are part of the keyed tuple, not a payload. + +A prover who wants row `j` to add some `P*` of their choosing must make ECSM′ +publish `(sel, P*)`; but ECSM′'s published coordinates are themselves pinned: +`sel = 1` to the G constant, `sel = 2` to the MEMW-bound memory bytes at `a2`, +`sel = 3` to the precompute row's output (§4.2), `sel = 4` to the preprocessed T₀ +table entry keyed by `LEN_M1`. There is no free coordinate anywhere in the chain. +Counts need no range check under gate contract C5 (a negative count cannot be +represented; an inflated count leaves an unmatched send). + +### 3.6 Why `XB`/`YB` need no byte checks + +This is the C4 inheritance the gate already used for `YR`, extended to a varying +addend. The receiving row's `XB`/`YB` columns appear *inside the keyed tuple*, so +balance forces them equal, limb-for-limb, to the publisher's columns. It therefore +suffices that every publishable value is byte-bounded at its source: + +| `sel` | source | byte-ness from | +|---|---|---| +| 1 | G | compile-time constant | +| 2 | memory at `a2` | store-time AreBytes (`store.rs`), the same authority today's `xG`/`k` rely on (`ecsm.rs:470`) | +| 3 | precompute row `XR`/`YR` | ECDAS′'s own AreBytes on `XR`/`YR` (§2 row 6) | +| 4 | T₀ table | preprocessed constant, committed | + +Row 3 looks circular but is not: the precompute row range-checks its *own* +`XR`/`YR` on that row, ECSM′ receives those checked values through the phase-0 +drain (§4.2), and only then republishes them. The dependency is a DAG, not a +cycle. + +**Caveat carried forward from today's design:** byte-bounded means `< 2^256`, not +`< p`. Interior non-canonical representatives are admissible because every +relation is mod p with the quotient absorbing the slack — the existing argument at +`chips-map.md:93-100`. That argument must be re-run in phase E for the *addend* +(today the addend was a single loop-invariant canonical point; now it varies and +includes P12, which is an interior chip output). The width audit is the place this +could bite. + +--- + +## 4. The four hard parts + +### 4.1 Double-row cancellation — re-derived from the live `eval` body + +Everything about the `Sum3`-gated (now `Linear`-gated) Addend receive being silent +on doubles rests on this, so here is the algebra straight out of +`EcdasConstraints::s_i` (`ecdas.rs:348-397`), not from a doc. + +Let `op` be `cols::OP`, and let `xg(·)`, `yg(·)` denote the addend limbs (`XB`/`YB` +in ECDAS′). The three relations at limb `i`: + +**Lambda** (`ecdas.rs:364-379`): +``` +op·( ya(i) − yg(i) + Σ_{j≤i} lam(j)·(xg(i−j) − xa(i−j)) ) + + (1 − op)·( Σ_{j≤i} 2·lam(j)·ya(i−j) − 3·xa(j)·xa(i−j) ) + + rq(i, Q0) +``` +At `op = 0` the entire first product is multiplied by zero. Every occurrence of +`xg`/`yg` in this relation lives inside that product, so the constraint value is +**independent of the addend**. The surviving `(1 − op)` branch reads only `lam`, +`ya`, `xa`; `rq` reads only `MU`, the constants `R`/`P`, and `Q0` +(`ecdas.rs:332-345`). ✓ + +**Xr** (`ecdas.rs:380-387`): +``` +Σ_{j≤i} lam(j)·lam(i−j) − xa(i) − xg(i) − xr(i) − (1 − op)·( xa(i) − xg(i) ) + rq(i, Q1) +``` +At `op = 0`, `(1 − op) = 1`: +``` += Σ lam·lam − xa(i) − xg(i) − xr(i) − xa(i) + xg(i) + rq += Σ lam·lam − 2·xa(i) − xr(i) + rq +``` +The `−xg(i)` and `+xg(i)` cancel **exactly**. ✓ (At `op = 1` the bracket vanishes +and it reduces to the chord form `xr = λ² − xa − xg`; at `op = 0` to the tangent +form `xr = λ² − 2·xa`. Both correct.) + +A note on `layout-lock.md:87`, which writes the cancelling term as +`(1−op)(xg−xa)`: the source has `− (1 − op)·(xa − xg)`, which is the same thing +once the leading minus is folded in. The doc and the code agree. + +**Yr** (`ecdas.rs:388-395`): +``` +Σ_{j≤i} lam(j)·( xa(i−j) − xr(i−j) ) − ya(i) − yr(i) + rq(i, Q2) +``` +No `xg`/`yg` occurs at all, for either value of `op`. ✓ + +**Conclusion — verified, not assumed.** On `op = 0` no convolution constraint +reads `XB`/`YB`. The witness agrees: the double row is built with +`&zero_pt = (0, 0)` as its addend (`witness.rs:786-789`, `:831`). So double rows +may carry `XB = YB = 0` and stay silent on the Addend bus. + +**One obligation this does *not* discharge.** The addend columns are unconstrained +on double rows, so nothing stops a prover from putting garbage there instead of +zero. That is harmless for the three relations (just shown) — but it must also be +harmless for the *bus*, and it is, because the Addend receive multiplicity is +`S1 + S2 + S3 + S_CORR`, which must be 0 on a double row. That needs an explicit +constraint tying the selectors to `OP`: +``` +OP = S1 + S2 + S3 + S_CORR (degree 1) +``` +i.e. adds have exactly one selector set, doubles none. Combined with `IS_BIT` on +each selector this also forbids two selectors at once. **Without this constraint +the cancellation is real but the gating is forgeable** — a prover could set +`S2 = 1` on a double row and mint a spurious Addend receive. It is one degree-1 +constraint; do not omit it. + +### 4.2 The two telescoping breaks — proposal: three keyed segments + +The break, restated from the source. `a = prev.r` holds on every main-chain row, +but not at two places: + +- **Precompute** (`witness.rs:807-822`): `a = P1`, addend `= P2`, result `= P12`. + Entirely off the accumulator line. +- **Correction** (`witness.rs:896-911`): `a =` the last accumulator, addend + `= −2^len·T₀`, result `= Q`. + +And `round` cannot discriminate them: the precompute and correction rows are both +emitted with `round = 0` (`witness.rs:810`, `:900`), while the main loop also +produces genuine `round = 0` rows on its last iteration (`witness.rs:825`). **Any +scheme keyed on `round` is ambiguous by construction.** + +**Proposal — split the chain into three separately-keyed segments** by adding +`PHASE` to the Ecdas′ tuple and `NEXT_PHASE` to the outgoing side: + +``` +Ecdas'[id=28 | ts_lo, ts_hi, phase, accX(32), accY(32), round, op] +``` +(Note the tuple **drops** today's `genX`/`genY` — the addend now varies per row +and arrives on bus 29, so it must not be part of the accumulator state. That is a +64-element narrowing of the tuple, which costs nothing in committed cells because +LogUp aux is per *interaction*, not per element.) + +| segment | ECSM′ sends (seed) | ECSM′ receives (drain) | rows | +|---|---|---|---| +| `phase = 0` precompute | `[ts, 0, xP1, yP1, round=0, op=1]` | `[ts, 0, xP12, yP12, round=0, op=1]` | exactly 1 | +| `phase = 1` main chain | `[ts, 1, xT0, yT0, round=LEN_M1, op=0]` | — (hands off to phase 2) | `len` doubles + adds | +| `phase = 2` correction | — (received from phase 1) | `[ts, 2, xQ, yQ, round=0, op=1]` | exactly 1 | + +Transitions: a phase-1 row sends `NEXT_PHASE = 1` normally, and the *last* one +sends `NEXT_PHASE = 2`; the phase-2 row is the unique receiver of that tuple and +drains to ECSM′. + +**Why a prover cannot forge the distinction.** `phase` is inside the keyed tuple, +so a row can only execute as phase `q` if some sender published phase `q`. The +phase-0 seed and drain are ECSM′ sends/receives with multiplicity `OK`, so +**exactly one** phase-0 row can exist per proven ecall, and its `a` is pinned to +the G constant and its result to the value ECSM′ republishes as `sel = 3`. The +phase-2 row is reachable only via a phase-1 row that chose `NEXT_PHASE = 2`, and +its drain must match ECSM′'s `[ts, 2, xQ, yQ, …]` receive, which is the same +`X_Q`/`Y_Q` the canonicalization blocks and the output MEMW write bind. So both +special rows are pinned at both ends. + +**What this does *not* settle — the phase-1 counting argument.** With `PHASE`, +`NB` (§0.1) and the round bookkeeping `round' = round − 1 + NB` on doubles / +`round' = round − 1` on adds, the intended invariant is "exactly `len` doublings, +each round visited once, each set digit consumed exactly once". Proving that is +**L6, the redo IMPL-PLAN §7 calls the riskiest work in the project**, and I am not +claiming it here. Two specific obligations phase E must discharge, which the +single-scalar L6 did not have: + +1. **Two interleaved streams.** The old argument counted one Bit stream against + `k`'s set bits. Now `u1` and `u2` are counted independently on the same rows, + and `NB = D1 ∨ D2` couples them. A prover setting `D1 = 1, D2 = 0` on a row + whose true digits are `(0, 1)` still balances `NB`; only the *per-stream* + JointBit balance separates them. Worth an explicit sub-lemma. +2. **`NEXT_PHASE` cannot be used to escape early.** A prover who sends + `NEXT_PHASE = 2` before consuming all rounds shortens the chain. What forbids + it is that the phase-2 drain is the only exit and the JointBit receivers in + ECSM′ carry multiplicity `u1_bit(i)`/`u2_bit(i)` for **all** `i`, so any set + digit left unconsumed leaves an unmatched receiver. That is the same shape as + today's argument (`chips-map.md:82-87`) but now needs `round` monotonicity + across a phase boundary. + +I flag both rather than assert them. + +### 4.3 The three canonicalization blocks + +All three follow the existing `XG_SUB_P` / `K_SUB_N` / `XR_SUB_P` pattern exactly +(`ecsm.rs:55-57`, `OverflowKind` `:636-677`, `carry_chain` `:796-830`, emission +`:892-907`). Per block: + +- **16 columns**, halfword-packed. The witness emits 32 LE *bytes* + (`sub_witness`, `witness.rs:662-665`); the trace builder repacks them with + `write_halfwords` (`ecsm.rs:141-147`), exactly as today. +- **16 IsHalfword sends** (`ecsm.rs:496-516` pattern). +- **8 constraints**: 7 × `µ·c_i·(1−c_i)` (degree 3) + 1 × `µ·(1−c_7)` (degree 2) — + substitute `OK` for `µ` per §4.4. The eight word-carries stay **virtual** + (expressions built from `INV_SHIFT_32`), so no carry columns. +- The relation proved is `p + v_sub_p = v + 2^256`, i.e. the addition must + overflow, i.e. `v < p` strictly (`ecsm.rs:631-635`). + +| block | `OverflowKind` variant | constant addend | sum source | witness field | +|---|---|---|---|---| +| `Y_P2_SUB_P` | `YP2LtP` (new) | `P_BYTES` | `Y_P2` (32 bytes) | `y_p2_sub_p` | +| `X_Q_SUB_P` | `XQLtP` (new) | `P_BYTES` | `X_Q` (32 bytes) | `x_q_sub_p` | +| `Y_Q_SUB_P` | `YQLtP` (new) | `P_BYTES` | `Y_Q` (32 bytes) | `y_q_sub_p` | + +Plus `U1_SUB_N` / `U2_SUB_N` reusing `KLtN` against `N_BYTES`. Note today's +`KLtN` reads its sum from **256 individual bit columns** +(`OverflowKind::sum_is_bits`, `ecsm.rs:673-676`, consumed at `:810-815`) — both +scalar blocks must keep that variant since `U1`/`U2` are bit-decomposed for the +JointBit multiplicities. + +Load-bearing status, corrected per §0.2: `X_Q_SUB_P` and `Y_Q_SUB_P` are genuine +forgery defences (output bytes are hashed by the guest). `Y_P2_SUB_P` should be +kept for width-audit hygiene but its DESIGN §3 justification does not hold, and +phase E's negative control for it will likely return UNSAT. + +### 4.4 The mu-gated error row + +**The problem, precisely.** The CPU sends on `Ecall` (id 19) for every ecall +(`cpu.rs:962-976`), so every syscall needs a receiver or bus 19 unbalances — the +unmatched-`Print` note at `syscalls.rs:36-40` is the cautionary tale, and ECSM's +receiver is `ecsm.rs:307-316`. On the `status ≠ 0` path there is no chain to +prove, but the receive must still fire. Today's padding trick (all-zero columns +with `µ = 0`) is unavailable because `µ = 0` would also kill the Ecall receive. + +**Proposal — split the single flag into two.** + +| flag | meaning | gates | +|---|---|---| +| `MU` | this row is a real ecall | Ecall receive; **all** MEMW (operand reads + status write) | +| `OK` | `status == 0`, full chain proven | JointBit receivers, Addend publishes, Ecdas′ seeds/drains, T₀ receive, and every convolution / carry constraint | + +with `IS_BIT(OK)` and `OK·(1 − MU) = 0` (so `OK ⇒ MU`). + +Concretely: everywhere today's ECSM body writes `b.main(0, cols::MU)` inside a +relation — the `µ·p²` and `µ·b` terms (`ecsm.rs:756-768`), the `rq()` gate +(`ecdas.rs:337`), the carry-bit gates (`ecsm.rs:897-905`) — substitute `OK`. Then +an error row sets `OK = 0` and every witness column to zero, and all relations +close at zero carries by exactly the argument the padding rows already use +(`ecsm.rs:12-16`, `ecdas.rs:10-12`). + +**Executor obligation this creates (for `phase-b-executor`):** on the error path +the executor must still perform all operand reads and the status write, so the +MEMW schedule is identical on both paths and can stay gated by `MU`. A natural +implementation that early-returns before reading would desynchronise the +timestamps. Address-guard failures are a separate class and should keep trapping +(as ECSM does at `execution.rs:432-437`) — they are guest-guarded, since the +addresses are the guest's own stack arrays, never attacker bytes. + +**Why it stays sound — and the constraint that makes it so.** IMPL-PLAN §2 argues +"a lying status only wastes cycles". That is right for `status ≠ 0`: the guest +falls back to `ProjectivePoint::lincomb`, which is proven CPU execution, so +over-claiming an error is merely expensive. But the converse needs enforcing — +**`status == 0` must oblige the chain proof**, or a prover sets `OK = 0` +(proving nothing), writes `status = 0`, and the guest happily reads a fabricated Q +out of memory. Nothing in the plan currently states the mechanism. Add: + +``` +OK · STATUS = 0 (OK = 1 ⇒ STATUS = 0) +STATUS · S_INV = 1 − OK (OK = 0 ⇒ STATUS ≠ 0, witnessed inverse) +``` +Two constraints and one column (`S_INV`, §1 row 24). This preserves IMPL-PLAN's +distinct per-variant error codes — `STATUS` may be any non-zero value when +`OK = 0`, and the guest only tests `!= 0`. A boolean `STATUS = 1 − OK` would also +work and drop `S_INV`, at the cost of losing the debug-distinguishable codes. + +--- + +## 5. Cell-count check — the −74.3% verdict, recomputed + +Cost rule (`chips-map.md:104`): committed base cells = logic columns + +1.5 × interactions. + +### 5.1 Interaction counts, recounted from source + +I recounted both live chips from `bus_interactions()` and reproduce the header +note at `chips-map.md:3-7` exactly, which is the check that the method is right. + +**ECDAS today** (`ecdas.rs:152-261`): 1 Ecdas receive + 98 AreBytes (6 bases × 16 +pairs at `:188-199`, plus `(ROUND, Q0[32])` and `(Q1[32], Q2[32])` at `:200-201`) ++ 189 IsHalfword (3 × 63, `:213-225`) + 1 Bit send + 1 Ecdas send = **290** ✓ +(chips-map: "ECDAS 388→290"). + +**ECSM today** (`ecsm.rs:300-589`): 1 Ecall + 15 MEMW (3 register reads + 4 xG + 4 +k + 4 xR writes) + 65 AreBytes (4 bases × 16 at `:460-464`, plus the lone +`q1[32]` at `:465-469`) + 174 IsHalfword (63 + 63 + 16 + 16 + 16, `:482-516`) + 1 +Zero + 256 Bit receivers + 1 Bit send + 2 Ecdas = **515** ✓ ("ECSM 579→515"). + +**ECDAS′** (§2 layout): 1 Ecdas receive + **1 Addend receive** + 98 AreBytes +(unchanged — `XB`/`YB` are not checked, §3.6) + 189 IsHalfword + **2 JointBit +sends** (one per stream, mults `D1`/`D2`) + 1 Ecdas send = **292**. +DESIGN §2's 292 is confirmed. The new bit columns (`D1`,`D2`,`NB`,`S*`,`PHASE`) +cost **constraints, not interactions** — `IS_BIT` is emitted in the body +(`ecdas.rs:428-433`), not sent on a bus. + +**ECSM′** (§1 layout, status in `x10` per §0.0): 1 Ecall + ~28 MEMW (4 register +reads for a0/a1/a2/a3 + 8 for P1 + 8 for P2 + 8 for u1‖u2 + 8 for the 64-byte +output + 1 register **write** of `STATUS` to x10 = 37 if P1 is read; ~28 if the +P1 read is dropped) + ~49 AreBytes (the P2 membership `x2`/`q0`/`q1` = 97 bytes → +48 pairs + 1) + 206 IsHalfword (126 membership carries + 5 × 16 canonicalization) ++ 2 Zero + 512 JointBit receivers + 4 Addend publishes + 1 T₀ receive + 4 Ecdas′ +(phase-0 send/receive, phase-1 send, phase-2 receive) ≈ **807** (±9 on the P1 +question). One row per ecrecover, so the ±9 moves the per-ecrecover total by +0.003%. + +### 5.2 Cells per row + +| row | logic | interactions | cells | +|---|---:|---:|---:| +| ECDAS today (pre-pairing) | 521 | 388 | 1,103 | +| ECDAS today (**post-`42ba68ff`**) | 521 | 290 | **956** | +| ECSM today (pre-pairing) | 667 | 579 | 1,536 | +| ECSM today (**post-`42ba68ff`**) | 667 | 515 | **1,440** | +| **ECDAS′** | 529 | 292 | **967** | +| **ECSM′** | 1,090 | 807 | **2,301** | + +ECDAS′ at layout-lock's 525 columns would be 963, matching DESIGN §2 exactly; my ++4 columns (§2) put it at 967, **+0.4%**. + +### 5.3 Per ecrecover + +- **Today, pre-pairing**: 4 chains × 382 rows × 1,103 + 4 × 1,536 = **1.692M** +- **Today, post-pairing (the live baseline)**: 1,528 × 956 + 4 × 1,440 = **1.467M** +- **lincomb2, post-pairing**: 449.1 rows × 967 + 2,301 = **0.437M** + (mean row count measured in phase A, `layout-lock.md:16-20`) +- lincomb2 worst case (471 rows): 0.458M + +### 5.4 Does the verdict move? — the denominator does, the physics does not + +| comparison | reduction | +|---|---:| +| lincomb2+pairing **vs pre-pairing baseline** (DESIGN's headline) | **−74.2%** | +| lincomb2+pairing **vs the current post-pairing baseline** | **−70.2%** | + +DESIGN's absolute numbers hold — I get 0.437M against its 0.43M, and −74.2% +against its −74.3%, from an independent recount. **But every percentage in +DESIGN's verdict table is denominated against the *pre*-pairing 1.69M, and the +pairing has already shipped in `42ba68ff`.** Measured against what is on the +branch today, lincomb2's marginal win is **−70.2%**, not −74.3%. The −74.3% figure +silently re-banks a win that is already in the bank. + +There is a trap here worth naming: DESIGN's "lincomb2 alone = −70.4%" is +*unpaired lincomb2 vs unpaired today*, and my −70.2% is *paired lincomb2 vs paired +today*. They are different quantities that happen to land within 0.2 points of +each other. IMPL-PLAN §9 currently reads "−70.4% standalone, −74.3% with the +AreBytes pairing already landed", which reverses the sense of both. + +**Recommendation:** state the phase-H target as **−70% EC committed cells against +the post-`42ba68ff` baseline**, and keep 0.437M / 1.467M as the numbers to +reproduce. The engineering verdict is unchanged — it still clears the 2× bar by +better than 3× — but the headline should not double-count. + +--- + +## 6. Open questions for the lead + +1. **P1 general or specialized to G? (§0.3 — the one real decision left.)** The + witness has no `mem_p1`, so a general P1 is currently *unprovable*. My + recommendation is constant-valued MEMW binding to G for v1. Phase B's shipped + ABI already accommodates either choice, so this is a chip-side decision only — + but it must be made, because "general P1" is not currently an option the witness + supports. Generalizing later is +307 ECSM′ columns plus a witness extension. + +1b. **Status in register vs memory (§0.0).** Phase B shipped the register form and + it is sound (COMMIT precedent) and cheaper. IMPL-PLAN §2 and §10 item 1 say the + opposite and should be corrected — flagging because my earlier map is what put + the wrong claim there. + +2. **Extend the witness with double-row digit bits? (§0.1.)** Required for `NB`. + It is additive (`d1`/`d2` on `JointSel::Double` rows, plus an `nb` field or let + the chip derive it) and changes no emitted math, so phase A's validation + survives. But it touches `witness.rs`, which IMPL-PLAN §0.2 calls the spec — + worth an explicit blessing rather than an agent doing it unilaterally. + +3. **Does `S_CORR` belong in the selector, or should the correction row receive + the T₀ constant on its own bus?** I chose `sel = 4` on the Addend bus (one + interaction, §3.4). The alternative — ECDAS′ receiving directly from the T₀ + table keyed by `len` — removes ECSM′ as a middleman but adds a second bus to + ECDAS′, the volume table. Recommend `sel = 4`; flagging because it changes what + phase C's table must publish to. + +4. ~~**T₀ table: store `+2^i·T₀` or `−2^i·T₀`?**~~ **Resolved by phase C — no + action.** IMPL-PLAN §10 item 3 left this open. The witness settles it + (`witness.rs:888` adds `neg_tpow = (tpow.x, p − tpow.y)`, while + `x_t0_pow`/`y_t0_pow` record the *un*-negated point, `:936-937`), and + `ec_t0.rs` stores the **negation** — column `Y` holds + `y(−2^LEN·T₀) = p − y(2^LEN·T₀)`, with `X` unchanged since `x(−P) = x(P)`, and + `ecsm::tests::lincomb2_table_tests` asserts the match against real witness rows. + That is the convention §3.3's `sel = 4` publishes; ECDAS′ does no implicit + negation. Recommend IMPL-PLAN §10 item 3 be marked decided. + +5. ~~**Keying the T₀ table on `len − 1`?**~~ **Resolved — but it hands phase D a + hard obligation.** Phase C keys on `len` directly (257 real rows 0..256, padded + to 512) and its header explicitly requires the consumer to constrain + `len ≤ 256`, because padding rows keep live keys with a `(0, 0)` payload + (§0.4). ECSM′ discharges it for free by carrying `LEN_M1` as a byte and keying + the receive `LEN_M1 + 1`. **This must not be dropped** — it is the one place + where phase C's design assumes phase D does something, and it is invisible from + the phase-D side unless someone reads the table's header. + +6. **Does the width audit survive a varying addend? (§3.6.)** Today's addend was a + single canonical loop-invariant point; ECDAS′'s can be P12, an interior chip + output that is only byte-bounded (`< 2^256 ≈ 5.4p`), not canonical. The + quotient/carry headroom argument at `chips-map.md:93-100` needs re-running with + that in mind. I did not attempt the bound arithmetic. + +7. **Old and new chips both live until phase G** — beyond the bus-id aliasing in + §0.5, is there any scenario where one proof contains both an `ecsm_mul` and an + `ecsm_lincomb2` call? If yes, the `Ecdas` bus (id 28) is shared between old + ECDAS and ECDAS′ and the tuples must not alias either. My §4.2 tuple drops + `genX`/`genY` (64 elements) and inserts `phase`, so the arities differ — but per + §0.5 differing arity is *not* sufficient. Safest is a separate id for the joint + chain; I did not cost that. + +--- + +## 7. What I could not verify + +Stated explicitly rather than papered over. + +- **The L6 counting argument.** §4.2 proposes a mechanism (`PHASE` + + `NEXT_PHASE` + `NB` + two JointBit streams) and names two specific obligations, + but I did not prove that the schedule is forced. That is phase E's job and + IMPL-PLAN §11 already ranks it the riskiest work; nothing here should be read as + discharging it. + +- **Whether `yP2 < p` is load-bearing at all.** I showed DESIGN §3's stated reason + is wrong (§0.2) and could not construct a replacement attack. I could not prove + it is *redundant* either — that would need the full width audit of item 6. Keep + the check; treat its necessity as open. + +- **Exact ECSM′ interaction count.** The 807 in §5.1 is my count over a layout I + proposed, not a count of existing code. The MEMW figure in particular depends on + the final ABI (§6.1) — dropping the P1 read would take it to ~20 and ECSM′ to + ~2,289 cells. Since ECSM′ is one row per ecrecover, a ±10% error here moves the + per-ecrecover total by under 0.1%. + +- **Whether `PHASE`/`NEXT_PHASE` can be folded into existing columns.** I added + two byte columns for clarity. `OP` + the selectors may already carry enough + information to encode the three phases without new columns, but I did not work + the encoding through and would rather propose four extra columns than a clever + encoding that turns out to be forgeable — per the standing + clean-constraints-over-cleverness rule. + +- **`bitwise.rs`'s AreBytes pairing contract.** I took `ecdas.rs:174-176`'s + assertion (that `ARE_BYTES[X, Y]` range-checks *both* elements) and the landed + `42ba68ff` at their word rather than re-deriving it; it is argued in + `gate/pairing-equivalence.md`. Every paired-count figure in §5 inherits that + assumption. diff --git a/thoughts/ec-recover-opt/lincomb2/DESIGN.md b/thoughts/ec-recover-opt/lincomb2/DESIGN.md new file mode 100644 index 000000000..753ed5bcc --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/DESIGN.md @@ -0,0 +1,236 @@ +# lincomb2 precompile — design study (candidate D) + +Decision doc for replacing the guest's 4× x-only `ecsm_mul` dance with one +`ecsm_lincomb2` syscall computing `Q = u1·P1 + u2·P2`, both coordinates +returned. Companion to `../chips-map.md` (census) and `../gate/RESULTS.md` +(soundness baseline L1–L8). Status: PAPER STUDY — no code changed. + +**TL;DR verdict: BUILD.** −70.4% EC committed cells standalone, −74.3% +combined with the AreBytes pairing already in flight; clears the 2× bar ~4× +over. One genuine design finding: the joint chain's incomplete-addition edge +is **attacker-reachable** (constructive attack below, §4) — unlike the +single-scalar chain the gate proved safe (L5b) — so the chip needs NUMS +accumulator blinding, which converts that one lemma from unconditional to a +**named computational assumption** (dlog-class, same family ecrecover already +rests on). Needs user sign-off, like blake3's 6-round assumption. + +--- + +## 1. Why 4 calls exist today, and what one call removes + +Current guest flow (`crypto/ethrex-crypto/src/lib.rs`): +`pk = u1·G + u2·R` is evaluated via four x-only queries — `x(u1·G)`, +`x((u1+1)·G)`, `x(u2·R)`, `x((u2+1)·R)` (`lincomb2_with_oracle`, +lib.rs:195-250). The `+1` queries exist ONLY to recover y from an x-only +oracle (`solve_y` λ-linear trick, lib.rs:252-272). Each query is a full +~256-bit scalar mul: 1 ECSM row + ~382 ECDAS rows. + +A lincomb2 precompile returning (xQ, yQ) directly: +- 4 chains → 1 joint Shamir/Straus chain (~448 rows), +- deletes `solve_y`, the shared field inversion, and 3 syscall round-trips + from the guest (~100–150k guest cycles/ecrecover, secondary win), +- the k+1 queries and the x-only sign disambiguation disappear structurally. + +## 2. Cost model + +Baseline census (gate-confirmed): ECDAS row = 521 logic + 388 interactions +× 1.5 = 582 aux → **1,103 cells**; with AreBytes pairing → **956**. ECSM row += 1,537. Today/ecrecover = 4×382×1,103 + 4×1,537 ≈ **1.69M cells**. + +### Proposed row shape (Design B — addend bus; chosen over Design A, §2.1) + +ECDAS' (joint-step row): same 3-relation core (λ/xR/yR conv blocks untouched +— L1/L2/L3/L4 port as-is). Changes: XG/YG (the fixed addend) → XB/YB +(received per-add from a new **Addend bus**); op/next_op → digit selectors +s1,s2,s3 (addend ∈ {P1,P2,P12}) + next-digit bits nb1,nb2 + one `nb_or` +helper column (round bookkeeping, deg-2 def). Logic ≈ **525** (vs 521). + +Interactions: Ecdas 2 + Addend receive 1 (mult `Sum3(s1,s2,s3)` — +supported, lookup.rs:1336-1349) + TWO Bit sends (one per scalar stream, +mults nb1/nb2) + AreBytes 196 + IsHalfword 189 = **390** → aux 585 → +**1,110 cells/row** (≈ today's 1,103; paired: 292 → **963**). XB/YB need no +new byte checks — they inherit byte-ness from the publisher's checked +columns via tuple equality (same C4-inheritance the gate used for YR). + +Addend binding soundness: the pending digit bits ride the accumulator tuple +(as `op` does today); the Addend receive is keyed `[ts, sel]` with +`sel = s1+2·s2+3·s3` linear in tuple-bound bits; ECSM publishes +`{1:P1, 2:P2, 3:P12}` with witnessed count multiplicities (balance forces +correctness; counts need no range check under C5). + +### Rows per ecrecover (random 256-bit u1, u2) + +Joint MSB-first, acc seeded = T₀ (NUMS blinding point, §4): doubles = len ≈ +255, adds = nonzero joint digits ≈ 0.75×255 ≈ 191, P12 = P1+P2 precompute +1 row (reuses the add machinery via a special round), blinding correction +(subtract 2^len·T₀ from a 256-row preprocessed constant table, keccak_rc +precedent) 1 row → **≈ 448 rows**. + +Blinding simplification bonus: `len` no longer needs the exact-MSB pinning +lemma (gate L6.5) — any len ∈ [max_msb+1, 256] yields correct Q (extra +leading doubles just double T₀; the keyed correction absorbs them). Bit +balance still forces every set bit consumed below len. + +ECSM' (1 row/ecrecover): today's 667 + 256 more scalar bits + 2nd K_SUB_N + +yP2 (32) + P2 membership relations (2nd x2/q0/q1/c0/c1 ≈ 225) + P12 columns +(64) + xP2/yP2/xQ/yQ canonicalization halfword blocks (§5 — load-bearing, +N6 pattern) + counts (3) ≈ 1,310 logic; interactions ≈ 1,150 → **≈ 3.0k +cells**, ×1 (vs 4×1,537 = 6.1k today). + +### Verdict table (EC committed base cells / ecrecover) + +| Variant | cells | vs today | confidence | +|---|---|---|---| +| Today (gate-verified) | 1.69M | — | measured census | +| + AreBytes pairing (in flight) | 1.47M | −13.3% | high | +| lincomb2 alone | 0.50M | **−70.4%** | high (±5% on row shape) | +| **lincomb2 + pairing** | **0.43M** | **−74.3%** | high — recommended target | +| lincomb2 + GLV (4-way, phase 2) | 0.29M (0.25M paired) | −83% (−85%) | LOW — signed-digit machinery unmodeled | + +At ethrex scale the multiplier is the EC share of total prover cells +(measure first: epoch reports give per-table rows; at 2857 tx ECDAS alone is +~4.4M rows). If EC = 50% of cells, lincomb2+pairing ≈ −37% whole-prover. + +### 2.1 Design A (selector columns) — rejected + +Carrying P2, P12 in every row (+128 cells) + a witnessed selected-addend +pair (+64) ≈ +190 cells/row ≈ +17%, vs Design B's +1 interaction (+1.5 +cells). Degree works in both (selection must be materialized into columns to +keep λ·xB at deg ≤ 3), but B is strictly cheaper and keeps the tuple narrow. + +## 3. y-parity binding (the directive's subtlety) — resolved, with one new required check + +Who binds recid parity today: the **guest**, entirely. It decompresses R +from (r, v) in software (lib.rs:98-104, proven CPU execution); the chip is +x-only and never sees a y; `solve_y` recovers y(A) relative to the KNOWN +base y (sign flows guest-side; the +1-query consistency check is a +completeness guard, not the parity authority). "Guest-supplied" ≠ trusted: +guest code is proven execution. + +Under lincomb2 the same split holds: the guest decompresses (r, v) → +(xP2, yP2) and passes both coordinates; parity remains proven guest logic. +The CHIP's obligations are exactly: +1. **Membership**: yP2² ≡ xP2³ + 7 (off-curve inputs break the step lemma — + gate L3b/L4 assume on-curve). Second membership block in ECSM'. +2. **Canonicalization — NEW and load-bearing**: yP2 < p. Without it, a + malicious prover submits yP2' = yP2 + p (fits in 32 bytes when + yP2 < 2^256 − p): same point mod p, **opposite parity as bytes** — and + under lincomb2 the sign of P2 changes Q. Same class as the gate's N6 + finding (XR_SUB_P load-bearing). Likewise xQ < p and yQ < p on the + output (the guest keccaks pk bytes; a +p-shifted coordinate hashes to a + different address). Three extra halfword blocks, costed in §2. + (Today's chip deliberately leaves yG sign/canonicity free — sound only + because x(k·P) = x(k·(−P)); that symmetry is exactly what lincomb2 loses.) + +## 4. The incomplete-addition edge is attacker-REACHABLE (key finding) → NUMS blinding + +Gate L5b proved A = ±addend unreachable for the single-scalar chain, +unconditionally, from k < N + prefix structure. **That argument does not +survive the joint chain, and no analog exists.** Constructive attack sketch +(all quantities prover-chosen — ecrecover inputs (z, v, r, s) are free bytes; +z is NOT forced through any hash): + +1. Pick ρ, set r = x(ρ·G) — the prover now KNOWS dlog_G(R) = ρ. +2. Pick u2; at a chosen step j its consumed prefix is c2. +3. The collision "accumulator = ±addend" at step j reads + c1 + c2·ρ ≡ t (mod N) for a small known t. Solve for the required c1 + residue; with probability ≈ 2^−j it is a valid j-step prefix value; set + u1's top bits to it (j small ⇒ cheap retries over u2/ρ). +4. Back out z = −u1·r, s = u2·r mod N. Valid-looking signature whose joint + chain hits a degenerate add ⇒ λ unconstrained ⇒ forged Q ⇒ forged + ecrecover ⇒ arbitrary "valid" tx sender in a proven block. + +Mitigations considered: +- **Complete addition formulas** (Renes–Costello, projective): sound, + unconditional, ~3× relations/row — erases most of the win. Rejected. +- **Detect-and-branch rows** (equal-x → tangent variant; A = −B → infinity + flag + gated bypass): keeps unconditional soundness, but infinity + representation + branch selection ≈ +2 relation variants, degree pressure, + and a much fatter L6. Fallback option if the assumption below is refused. +- **NUMS accumulator blinding — CHOSEN**: seed acc = T₀, a fixed + nothing-up-my-sleeve curve point (hash-to-curve from a spec'd tag, e.g. + try-and-increment on SHA-256("lambdavm/ecsm/lincomb2/T0/v1")); drain + subtracts 2^len·T₀ via the preprocessed table. Every intermediate + accumulator is 2^j·T₀ + (c1·P1 + c2·P2); a collision now implies a known + linear relation on dlog_G(T₀) — i.e. the attacker computes a discrete log + nobody knows. Cost: ~2 rows + one 256×~70-cell preprocessed table. + **Consequence**: chip soundness for this lemma becomes computational — + "no efficient prover can produce a linear relation on dlog(T₀)" — a + dlog-class assumption, strictly within what ecrecover/ECDSA already + assumes for the chain being proven. This must be a NAMED assumption in + the spec (blake3-6-round precedent) and **requires user sign-off**. + The final correction add A − 2^len·T₀ is itself degenerate only when + Q = ∞, handled by the status contract (§6). + +## 5. Interface & implementation surface + +Syscall (new number, ECSM pattern): a0 = addr to write Q (64 bytes: +xQ‖yQ LE), a1 = addr of (xP1‖yP1) (64B), a2 = addr of (xP2‖yP2) (64B), +a3 = addr of (u1‖u2) (64B) — or split registers per current +`ecsm_addr_ok`/overlap-guard style (execution.rs:97, :432-446); executor arm +mirrors execution.rs:424-456: load, guard, `ecsm::lincomb2_witness(...)`, +store, log. **Status contract**: executor detects degenerate inputs +(u∈{0}, P2 = ±P1 ⇒ P12 degenerate, Q = ∞) cheaply in software and returns +status ≠ 0 (register or sentinel); the guest then takes the existing +pure-Rust `ProjectivePoint::lincomb` fallback (lib.rs:116-117 already has +exactly this unwrap_or_else structure). Status=1 is always SOUND — the +fallback is proven guest code; a lying status only wastes cycles. No trap ⇒ +no crafted-tx censorship of a whole block (today's ECSM traps, +execution.rs:450; acceptable there because inputs reaching it are +guest-guarded, lib.rs:210-212 — keep that pattern). + +Touch list: `syscalls/src/syscalls.rs` (+1 fn), executor `execution.rs` +(+~80 lines), `crypto/ecsm/src/witness.rs` (joint-schedule replay + +blinding + P12; compute_witness stays for the old syscall — keep both +syscalls alive through the transition), `prover/src/tables/{ecsm,ecdas}.rs` +(major rework — largest chip job since the tables were written), +`trace_builder.rs` collectors, `crypto/ethrex-crypto/src/lib.rs` (net +DELETION: 4-query + solve_y path → 1 call + fallback), a preprocessed +T₀-table chip (keccak_rc.rs pattern), and a NEW spec chapter (none exists +for EC today — stale `spec/src/ecsm.toml` references confirmed dead). + +## 6. Verification plan (gate reuse) + +- **Port unchanged**: L1 (same conv/carry shape), L2 mechanics (recompute + the same offsets), L3a/L3b, L4 chord/tangent, L5a (no 2-torsion). +- **Replaced**: L5b → the NUMS reduction argument (named assumption, + documented + user-signed; the reduction itself is a short pen-and-paper + proof with its arithmetic steps z3-checked). +- **Redone**: L6 — joint schedule (two Bit streams, Addend-bus binding via + tuple-carried digit bits, per-scalar counting; skeleton identical, and the + exact-MSB sub-lemma DROPS, §2); L7 — small-joint-scalar unrollings vs an + extended oracle (`ec_ref.py` + ~10-line lincomb2 reference). +- **New negative controls**: drop yP2_SUB_P (parity-flip forgery must SAT — + the §3 attack), drop xQ/yQ canonicalization, addend-selector tamper, + status-contract mismatch, correction-table wrong-len. +- **Oracle anchors**: Wycheproof ECDSA-verify secp256k1 vectors (exercise + the sR − zG lincomb shape), the existing 40-sig 3-way ecrecover + differential (oracle bonus_ecrecover.py), ≥500 random lincomb differential + vs k256 `ProjectivePoint::lincomb`. + +## 7. Alternatives considered + +- **(a) GLV on top** (4 half-scalars, 15-entry addend table): →~260 rows, + extra −41% relative. Real but needs signed-scalar handling (conditional + point negation, mod-N decomposition relation, |ki| < 2^129 bounds) — new + proof surface comparable to lincomb2 itself for ~40% more. Phase 2 only; + the Addend-bus design leaves room (table just grows). +- **(b) x-only lincomb**: 2 calls + solve_y still needed → only −41%, keeps + the fragile reconstruction. Rejected. +- **(c) w=2 windowed single-scalar** (no interface change): −8%. Rejected. +- **(d) pairing only**: −13.3%, already in flight; composes with everything. + +## 8. Recommendation + +Ship pairing now (in flight). Then build lincomb2 + pairing (−74.3% EC +cells, ~4× the 2× bar) in this order: (1) user sign-off on the NUMS +assumption + status-contract ABI; (2) oracle extension + T₀ derivation +spec'd; (3) witness + executor behind the new syscall (old one untouched); +(4) chips + gate port; (5) guest switch; (6) bench (extend +gen_ec_bench.sh with an ecrecover-loop guest) + EC-share measurement on a +real block for the whole-prover claim. GLV deferred until lincomb2 benches. + +Honest uncertainties: row-shape estimate ±5% (nb/selector column count, +correction-row plumbing); the L6 redo is the riskiest proof work (two +interleaved counting arguments); preprocessed-table plumbing for T₀ assumed +cheap by keccak_rc precedent. diff --git a/thoughts/ec-recover-opt/lincomb2/FINDING-nums-blinding.log b/thoughts/ec-recover-opt/lincomb2/FINDING-nums-blinding.log new file mode 100644 index 000000000..2e2ab80f5 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/FINDING-nums-blinding.log @@ -0,0 +1,135 @@ +FINDING — the NUMS blind does NOT close the incomplete-addition edge (phase D0) +============================================================================== +Found 2026-07-24 while drafting the spec chapter's assumption section (phase E0). +Re-run: from thoughts/ec-recover-opt/oracle/, + /bin/python nums_blinding_probe.py + +SEVERITY: soundness. The chip as designed would accept traces proving a FALSE +statement (Q != u1*P1 + u2*P2). It is not a bug in phase A — `lincomb2_witness` +correctly refuses these inputs; it is a gap in the argument that replaces gate +lemma L5b, i.e. in DESIGN.md section 4. + +WHAT DESIGN.md SECTION 4 CLAIMS +------------------------------ + "NUMS accumulator blinding [...] Every intermediate accumulator is + 2^j*T0 + (c1*P1 + c2*P2); a collision now implies a known linear relation on + dlog_G(T0) -- i.e. the attacker computes a discrete log nobody knows." + +WHY IT DOES NOT HOLD +-------------------- +The prover chooses P2. For ecrecover, P2 = R = lift_x(r) where `r` is a +signature component the submitter picks freely (DESIGN section 4 already relies +on exactly this freedom for its own attack on the unblinded chain, where it sets +r = x(rho*G)). Nothing stops the prover from setting + + P2 = mu * T0 for a mu it chooses, r = x(P2), v = parity(y(P2)) + +and then the "known linear relation on dlog(T0)" is satisfiable with NO +knowledge of dlog_G(T0): the T0 coefficient is cancelled against P2's. + +With P1 = G, write the accumulator entering the add at round `rr` as + acc = alpha*T0 + beta1*G + beta2*P2 = (alpha + mu*beta2)*T0 + beta1*G +where alpha, beta1, beta2 are public functions of the schedule and the scalar +bits. Choosing u1 < 2^rr forces beta1 = e1 = 0, and the collision acc = addend += P2 collapses to ONE scalar equation: + + alpha + mu*(beta2 - 1) == 0 (mod N) -> mu = -alpha/(beta2 - 1) + +One modular inversion, one scalar multiplication. This is CHEAPER than the +~2^-j-probability search DESIGN section 4 describes against the UNBLINDED chain +— the blind made the attack easier to aim, not harder. + +CONSTRUCTIVE EVIDENCE (nums_blinding_probe.py, 5/5 constructions land) +---------------------------------------------------------------------- +For each of len = 8, 12, 16, 32, 256 with a chosen target round, the probe +solves for mu, sets P2 = mu*T0, runs the REAL blinded schedule, and finds + + acc == addend as points, at exactly the targeted round, + with equal y -> the forgeable case (see below). + +It then packages the full ecrecover input (z, v, r, s) and checks that the +guest's own decomposition (u1 = -z/r, u2 = s/r, R = lift_x(r) with parity v) +reproduces the intended u1, u2 and lifts R back to P2 exactly. All five: True. + +Worked example (len = 8, round 3, u1 = 1, u2 = 0x88): + mu = 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbacd2ae642c4cedbe78cab5667435afca5 + P2 = (0x85882c59785c434236e2ec879fd034aca0ede94b97d85b0f39bc3dcbdb39753d, + 0x58cb252db487d4c48db6dbb4fac8fe290f5bdc94378bbf0bd210ae382bc019ca) + z = 0x7a77d3a687a3bcbdc91d1378602fcb5219c0f39b1770452c861620c0f4fccc04 + r = 0x85882c59785c434236e2ec879fd034aca0ede94b97d85b0f39bc3dcbdb39753d + s = 0xf0578f87f103bb2d288da80ce69bfc0e72938914bd148fc0387af9cb87b070a2 v = 0 + +Independently corroborated: + - the Python reference schedule `lincomb2_ref.lincomb2_rows` raises + ResultInfinity on this input (same collision, seen by the honest generator); + - the repo's Rust `ecsm::lincomb2_witness` (commit bc62f00e, via the harness) + answers `err ResultInfinity` on the same input; + - P2 = mu*T0 reproduced through the independent Jacobian implementation. + +WHY THE COLLISION IS A FORGERY, NOT A REJECTION +----------------------------------------------- +On an add row the lambda relation is lambda*(xB - xA) + yA - yB == 0 (mod p). + acc == -addend => xA = xB, yA = -yB => -2*yB == 0, impossible on + secp256k1 (gate L5a) => the row is UNSATISFIABLE: rejects. + acc == +addend => xA = xB, yA = yB => 0 == 0: LAMBDA IS UNCONSTRAINED. +The construction above lands in the second case (verified: acc == addend as +points, equal y). With lambda free, the row's outputs become a one-parameter +family + xR = lambda^2 - 2*xA, yR = lambda*(xA - xR) - yA, +and nothing downstream re-checks curve membership of intermediate accumulators +(the chip inherits it by induction from the ECSM-checked seed — chips-map.md +note 4), so the whole rest of the chain follows deterministically to a Q that is +not u1*P1 + u2*P2. + +HOW FAR AN ATTACKER GETS (honest scoping — do not overstate this) +----------------------------------------------------------------- +Producing an accepting proof of a FALSE lincomb2 statement is cheap: one scalar +multiplication. That alone is disqualifying for a proof system. + +Steering Q to a CHOSEN value (e.g. a specific victim's public key, which is what +turns this into fund theft) looks much harder, and this probe does not +demonstrate it. Per family (mu, u1, u2, len, round) the reachable Q form a +one-parameter family in lambda; hitting a chosen address means grinding lambda +and hashing, ~2^160. Making x_A itself a free choice (which would give enough +equations) requires knowing dlog_{T0} of a point the attacker did not construct +— i.e. a discrete log again. So: soundness is broken; targeted theft is not +demonstrated and does not look feasible by this route. I cannot rule out a +sharper exploitation path, and would not ship on the assumption that none exists. + +CONSEQUENCES FOR THE PLAN +------------------------- +1. DESIGN.md section 4's chosen mitigation is INCOMPLETE as written. The named + assumption ("no efficient prover can produce a known linear relation on + dlog(T0)") is NECESSARY but NOT SUFFICIENT. Signing it off would not buy the + soundness the design attributes to it. +2. IMPL-PLAN phase E's "Replaced: L5b -> the NUMS reduction argument" cannot be + discharged as specified. The reduction has a hole exactly where the prover + controls P2. +3. Something must actually pin non-degeneracy. The obvious candidate is an + explicit witnessed inverse on add rows — + d_inv * (xB - xA) == 1 (mod p) + — one more byte-convolution relation of the same shape the chip already runs + (~32 inverse bytes + 33 quotient + 64 carries + the matching range sends, + order +200..250 committed cells/row on a ~963-cell row). That is + UNCONDITIONAL: no assumption, no T0 needed for this purpose. It costs roughly + a quarter of the per-row budget, taking the headline from about -70% to about + -60% EC cells — still far above the 2x bar. DESIGN section 4's own listed + fallback ("detect-and-branch rows") is the other option. + Choosing between them is a design decision for the lead, not for this phase. +4. Whatever is chosen, phase E needs a negative control for it: remove the + non-degeneracy check, feed the trace built from the construction above, and + the gate must report SAT (forgery reappears). +5. The blind may still be worth keeping for the OTHER thing it buys (dropping + the exact-MSB sub-lemma L6.5, per DESIGN section 2), but that is a + convenience, not a soundness property. + +WHAT IS NOT AFFECTED +-------------------- +- Phase A is correct. `lincomb2_witness` rejects every one of these inputs + (`ResultInfinity`), and anchor D found no discrepancy over 69,431 rows. +- The existing single-scalar ECSM/ECDAS chips are unaffected: gate lemma L5b is + proved unconditionally there from k < N plus the prefix structure, and the + accumulator is not prover-steerable in the same way (there is one scalar, one + fixed addend, and no blind). +- The status contract is unaffected: status != 0 -> software fallback is sound + regardless. diff --git a/thoughts/ec-recover-opt/lincomb2/IMPL-PLAN.md b/thoughts/ec-recover-opt/lincomb2/IMPL-PLAN.md new file mode 100644 index 000000000..2a0254f6a --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/IMPL-PLAN.md @@ -0,0 +1,735 @@ +# lincomb2 — implementation plan (phases B–H) + +Execution plan for DESIGN.md §8 steps (3)–(6). Phase A (witness + T₀) is +**DONE** and committed (`bc62f00e`); its measured outputs are locked in +`layout-lock.md` and are the contract every phase below builds against. + +This document is written to be **agent-consumable**: each phase is a +self-contained brief with a touch list, an acceptance gate, and explicit +"do not touch" boundaries, so phases can be delegated in parallel where the +dependency graph allows. + +> ## ⚠️ DESIGN §4's NUMS argument is BROKEN — do not ratify the assumption +> +> The blinding does **not** close the incomplete-addition edge, because the +> prover chooses P2 (= `lift_x(r)`, free signature bytes). Setting +> **P2 = μ·T₀** cancels the T₀ coefficient and makes the collision condition +> solvable with **no knowledge of dlog(T₀)** — with P1 = G and u1 = 1 it is +> `μ·(c2 − 1) ≡ −2^j (mod N)`, one modular inversion. That is *cheaper* than +> the attack DESIGN describes against the **unblinded** chain: the blind made +> the edge easier to aim at, not harder. +> +> Verified 5/5 (len ∈ {8,12,16,32,256}): `acc == addend` with equal y at the +> targeted round ⇒ `λ` unconstrained ⇒ forgeable row, and the packaged +> `(z,v,r,s)` is well-formed (the guest's own decomposition reproduces u1/u2 +> and lifts R back to P2). Repro `oracle/nums_blinding_probe.py`, writeup +> `FINDING-nums-blinding.log`, independently re-run. +> +> **Phase A is unaffected** — the honest witness refuses every case +> (`ResultInfinity` → status ≠ 0 → fallback). The hole is on the +> malicious-prover side, where the row is hand-crafted. It is a **chip** +> obligation. +> +> **FIXED — `D_INV·(xB − xA) ≡ 1 (mod p)` has LANDED**, gated by `ΣS` (the +> same expression that counts the Addend receive — strictly better than the +> `OP` gating originally proposed, and lemma (a1) proves the two coincide on +> live rows), covering all five addend-consuming row types including the +> correction row, never doubles. ECDAS2: 529 → **658 cols**, 217 → **288 +> constraints**; cells/row 967 → 1240 ⇒ measured **−61.9%** against the +> 1.467M post-pairing baseline. +> +> **Consequence: lincomb2 rests on no cryptographic assumption that the +> original chips did not.** The T₀-dlog assumption is neither necessary nor +> sufficient — **do not sign it off.** Keep the blind only for the `len` +> simplification (L6.5 drops), which is convenience, not soundness, and say +> so wherever it is described. + +## Status (2026-07-24, uncommitted working tree) + +| Phase | State | Gate | +|---|---|---| +| A witness + T₀ | **committed** `bc62f00e` | — | +| A′ `nb` schedule fix | **done** | `-p ecsm` 26/0 | +| B syscall + executor | **done** | `-p executor lincomb2` 18/0 | +| C T₀ table (+ `LEN_M1`) | **done** | `--lib ec_t0` 17/0 | +| D0 oracle anchors | **done** | 611 lincomb + 1,536 small-scalar + 489 Wycheproof + 40/40 + 69,431 rows field-by-field, **0 failures** | +| E0 spec chapter | **done** | `spec/ecsm.typ`, compiles standalone + in `ebook.typ` | +| D chips (+ both soundness fixes) | **done** | ECDAS2 658 cols / 288 constraints; `--lib lincomb2` green | +| E z3 gate | **done, unconditional** | `gate/RESULTS-lincomb2.md`: all lemmas UNSAT, **7 forgeries SAT**, 0 live holes | +| G guest switch | **done** | `ethrex-crypto` 13/0; both real blocks prove **and verify**; **−78,823 / −78,493 guest cycles per ecrecover** (two blocks, agreeing to 0.4%) | +| H bench | **harness ready, NOT run** | `BENCH.md` has the server commands; benches run on the server, never locally | + +**Two "silently inert" traps, both now guarded — check these first if a result +looks wrong.** (a) The guest falls back to pure-Rust `lincomb` on non-zero +status and returns **the same answer**, so output equality cannot detect a run +where the precompile never fired. `test_ethrex_block_uses_the_lincomb2_ +accelerator` counts ECSM2 rows with `MU=1, OK=1, STATUS=0` and requires exactly +one per transfer; on the bench side only the **cell slope** can tell (a slope +near baseline, or a mean/worst ratio near 1.0, means you measured the +fallback). (b) Five `pr_main.yaml` cache keys hashed `executor/programs/rust/**` +and `syscalls/**` but **not** `crypto/ethrex-crypto/**`, which the ethrex guest +depends on by path — CI would have restored a stale `ethrex.elf` and kept +proving the old x-only path. Fixed (cache-key only). + +**Measured cycle win is below DESIGN's prediction**: ~78.5k/ecrecover vs the +predicted 100–150k (~21% short of the low end). Quote the measurement. + +Whole-tree gates re-run independently at this point, not taken on report: +**`make lint` clean** (fmt + all four clippy passes) and +**`--lib prove_elfs` 101 passed / 0 failed** — real end-to-end proofs still +prove and verify with the EC_T0 AIR in the machine. Five recursion-ELF +failures elsewhere in the prover suite are pre-existing and unrelated +(`executor/program_artifacts/recursion/*.elf` was never built in this tree; +`make compile-recursion-elfs`). + +--- + +## 0. Invariants that hold for every phase + +1. **The old path stays alive until phase G.** `ecsm_mul` (syscall), + `compute_witness` (single-scalar witness), the ECSM/ECDAS chips as they + exist today, and the guest's 4-query `lincomb2_with_oracle` all keep + working and keep their tests green. lincomb2 lands *beside* them. + Nothing is deleted until the new path is proven end-to-end. +2. **`crypto/ecsm/src/witness.rs::lincomb2_witness` is the spec.** It is + host-validated against two independent references over 512+ cases. If a + chip/executor disagrees with it, the chip/executor is wrong — do not + "fix" the witness to match an implementation. +3. **No constraint-body micro-optimization.** Per the standing rule + (`feedback-clean-constraints-over-cleverness`), bodies are the spec; + cleverness needs a measured bench win or it gets reverted. Clones in + bodies are free. +4. **`make lint` (not per-package clippy) + `cargo fmt` before any push.** +5. **Every phase reports honestly**: if a gate is red, say so with the + output. A phase is not "done" because it compiles. + +--- + +## 1. Dependency graph + +``` +A (DONE: witness + T0) +├── B syscall + executor arm ──────────┐ +├── C T0 preprocessed table chip ──────┤ +├── D0 oracle extension (paper/python) ─┤ +└── E0 spec chapter + NUMS assumption │ + ▼ + D chips (ECSM' / ECDAS' / Addend bus) + + trace-builder collectors + │ + ▼ + E z3 gate port + L6 redo + negative controls + │ + ▼ + G guest switch (delete solve_y + 4-query) + │ + ▼ + H bench + EC-share measurement +``` + +**Parallel now (no interdependency): B, C, D0, E0.** +D is the long pole and needs B's log format + C's table + D0's oracle. + +--- + +## 2. Phase B — syscall + executor arm + +**Goal.** A new `ecsm_lincomb2` syscall the guest can call, executed in +software by the executor, emitting a log the trace builder will later +consume. No chip work; the proof side does not yet constrain it. + +**ABI (decided; `layout-lock.md:91-107` left this TBD).** +Status is returned **in a register**: + +``` +a7 = u64::MAX - 11 (next free; continues the negative-ECALL convention) +a0 = addr to write xQ(32) ‖ yQ(32), 64 B LE → a0 holds STATUS on return +a1 = addr of xP1 ‖ yP1 (64 B LE) +a2 = addr of xP2 ‖ yP2 (64 B LE) +a3 = addr of u1 ‖ u2 (64 B LE) +``` + +**This decision flip-flopped once; here is the resolution, so it does not +get relitigated.** An intermediate draft moved the status into memory on the +grounds that ECALL decode leaves `write_register = false` +(`prover/src/tables/types.rs`, `Instruction::EcallEbreak` arm). That flag is +real, **but it governs the CPU row's write path only** — it says nothing +about what an accelerator may emit on the MEMW bus. The counter-example is +already in the tree: **COMMIT writes x10 during its ecall** +(`prover/src/tables/commit.rs:29` "Sender: Memw bus — read+write x10 +register", implemented at `trace_builder.rs:1225-1228` via +`MemwOperation::new(true, reg_addr, new_value, ts, 2, true)` + +`register_state.write(10, count, ts)`). + +The register form is therefore both expressible and strictly cheaper: no +status word in the buffer, one fewer dword write, and the guest tests a +register instead of doing a load. + +**The error path must still perform every operand read and the status +write.** Do not early-return before the loads: skipping them desynchronises +the MEMW timestamps and makes the trace unprovable. + +**Status contract (soundness-critical — get this right).** +`status ≠ 0` ⇒ the guest takes its pure-Rust `ProjectivePoint::lincomb` +fallback. This is **always sound**: the fallback is proven guest code, so a +lying status can only waste cycles, never forge a result. Therefore: + +- **Do NOT trap** on degenerate input. Today's `ecsm_mul` traps, which is + acceptable only because its inputs are guest-guarded; a trap here would + let a crafted transaction censor an entire block. +- Map every `Lincomb2Error` variant (`ScalarIsZero`, `ScalarOutOfRange`, + `PointNotOnCurve`, `PointNotCanonical`, `SumDegenerate`, + `ResultInfinity`) to a distinct non-zero status value — distinct so the + bench/debug path can tell them apart; the guest only tests `!= 0`. +- On `status ≠ 0`, write **only** the status word; leave the 64-byte Q + region untouched (there is no witness to prove). + +**There is no precompile log type — do not invent one.** Verified: no +`EcsmLog`, no event enum, no side-channel `Vec` on the executor. ECALLs +repurpose the ordinary per-instruction `Log` (`executor/src/vm/logs.rs:9-28`): +`src1_val` = a7 (set generically at `execution.rs:471`), `src2_val`/`dst_val` += two spare address slots. **The prover re-derives the witness itself** — +`trace_builder.rs:851-852` calls `ecsm::compute_witness(...)` and recovers +operand addresses from `register_state.read(10/11/12)` (`:839-841`). lincomb2 +follows the same precedent: recover all four addresses from register state in +the trace builder; the `Log` struct does not change. + +**Touch list.** `syscalls/src/syscalls.rs` (+1 `pub fn`, riscv64 + non-riscv64 +stub pair, mirroring `ecsm_mul` at `:168-188`); the syscall-number enum +(`executor/src/vm/instruction/execution.rs:10-19`, `TryFrom` `:38-51`, +`Accelerator` `:54-58`, `accelerator()` `:60-74` — exhaustive match, so a new +variant is a compile error there by design); the ecall dispatch `:356-359`; +a new arm mirroring `SyscallNumbers::Ecsm` at `:424-456`; and **`bin/cli/src/ +main.rs:367` `accelerator_of()` + its tests `:1100-1131`** — a third sync +table the DESIGN touch list missed, and one that is *not* compile-forced, so +it goes stale silently. + +Address guards: `ecsm_addr_ok` (`:96-99`) + `load_u256_le`/`store_u256_le` +(`:77-94`). Note the overlap guard's **real** rationale (`:438-444`): xG and k +are read at adjacent proof timestamps, so an overlap makes the **MEMW access +chain unprovable** — it is about trace provability, not arithmetic. Reason +about the four regions' timestamp schedule rather than copying the +`abs_diff < 32` check. + +**Build note.** `lambda-vm-syscalls` is **excluded from the workspace** +(`Cargo.toml:11`, bare-metal riscv — `#[global_allocator]`/`no_mangle` won't +link on host), so a plain workspace `cargo test` does not build it. + +**Ecall-bus obligation (phase D solves it; phase B must not preclude it).** +The CPU sends on the `Ecall` bus (id 19) for *every* ecall, and each syscall +needs a matching receiver or **the bus unbalances** — the unmatched-`Print` +note at `syscalls.rs:36-40` is the cautionary tale; ECSM's receiver is +`ecsm.rs:307-316`. This must hold on the **error path too**, where there is no +chain to prove. Hence the executor always writes a status word whether or not +it succeeded, so the error path stays expressible as a mu-gated row that +proves the receive and the status write and nothing else. Soundness is +unaffected: `status ≠ 0` only sends the guest to its proven fallback, so a +prover may always *under*-claim; only `status == 0` obliges a full chain proof. + +**Acceptance gate.** +- Executor unit tests: one happy path asserting Q equals `lincomb2_witness`'s + Q (and k256's), plus one test per `Lincomb2Error` variant asserting + `status != 0` **and** that the output buffer is untouched. +- Guard tests: out-of-bounds, unaligned, and each overlapping-region case + rejected without panicking the executor. +- A guest→executor round trip through the existing ECSM test harness style. +- `make lint` clean. + +**Do not touch.** `ecsm_mul`, `compute_witness`, any file under +`prover/src/tables/`, the guest's `lib.rs`. + +--- + +## 3. Phase C — T₀ preprocessed constant table + +**Goal.** A preprocessed (committed-once, verifier-known) table of +`2^len · T₀` for `len ∈ [0, 256]`, which the correction row indexes by `len` +to strip the NUMS blind. Follows the keccak round-constant chip precedent +(`keccak_rc.rs`). + +**Content.** Row `i` = `(i, x(2^i·T₀), y(2^i·T₀))` — or the negation +`−2^i·T₀` directly, since the correction row *adds* `−2^len·T₀`. Prefer +storing the negation: it removes a per-row negation from the chip and the +table is constant either way. **Decide once, document it in the chip +header, and make the witness/test assert the same convention** — +`witness.rs` already emits the correction addend, so read what it emits +(`JointSel::Correction`) and match it exactly rather than assuming. + +T₀ itself is pinned and reproducible: `ecsm::t0()`, derivation in `T0.md`, +independently reproduced by the `t0_derivation_matches` dev test and the +Python oracle. + +**Acceptance gate.** A test that recomputes the whole table from `ecsm::t0()` +by repeated doubling and compares against the committed constants; a test +that the table's commitment is stable across runs; on-curve check for every +entry. + +**Do not touch.** Anything outside the new table chip + its registration. + +--- + +## 4. Phase D0 — oracle extension (parallel, cheap) + +`thoughts/ec-recover-opt/oracle/lincomb2_ref.py` already exists from phase A. +Extend the oracle set so phase E has anchors ready: + +- ≥500 random lincomb differentials vs an independent implementation. +- Wycheproof ECDSA-verify secp256k1 vectors (they exercise the `sR − zG` + lincomb shape). +- Re-run the existing 40-signature 3-way ecrecover differential + (`bonus_ecrecover.py`) against the lincomb2 path. +- Small-joint-scalar unrollings (u1, u2 ∈ [1, 16]) — the L7 anchor. + +**Acceptance gate.** All differentials green, logged to +`thoughts/ec-recover-opt/lincomb2/` like `oracle_lincomb2.log`. + +--- + +## 5. Phase E0 — spec chapter + the NUMS assumption + +No EC spec chapter exists today (`spec/src/ecsm.toml` references are dead — +confirm before writing). Write one, and in it state the **named +computational assumption** the design introduces: + +> No efficient prover can produce a known linear relation on `dlog(T₀)`. + +This is dlog-class — strictly within what ECDSA/ecrecover already assume for +the chain being proven — and it replaces gate lemma L5b, which does *not* +survive the joint chain (DESIGN §4 gives a constructive attack on the +unblinded version). Precedent for a named assumption in the spec: blake3's +6-round assumption. + +**DO NOT RATIFY THIS AS WRITTEN — see the banner at the top of this +document.** The assumption is **necessary but not sufficient**: the reduction +*to* it does not close, because the prover chooses P2 and can set it to a +known multiple of T₀. Signing it off would buy strictly less than DESIGN +attributes to it, and would leave the chip accepting proofs of false +statements for one scalar multiplication of work. + +The spec chapter should therefore state **both** the assumption **and** that +the reduction to it is incomplete, plus whichever non-degeneracy mechanism is +actually adopted (working assumption: the unconditional witnessed inverse, in +which case the assumption is not load-bearing for soundness at all and the +blind survives only as a convenience that drops the exact-MSB lemma L6.5). + +--- + +## 6. Phase D — chips (the long pole) + +**Goal.** ECSM′ (1 row/ecrecover) + ECDAS′ (1 row/joint step) + the Addend +bus, proving exactly what `lincomb2_witness` emits. This is the largest chip +job since the tables were written. + +**Design B (locked; Design A rejected, DESIGN §2.1).** The addend is +*received* per-add on a new **Addend bus** rather than carried in every row. +ECSM′ publishes `{1: P1, 2: P2, 3: P12}` with witnessed count +multiplicities; ECDAS′ receives keyed `[ts, sel]` with +`sel = s1 + 2·s2 + 3·s3`, multiplicity `Sum3(s1,s2,s3)` (supported — +`lookup.rs:1336-1349`). Balance forces correctness; counts need no range +check under gate contract C5. XB/YB inherit byte-ness from the publisher's +checked columns via tuple equality (the C4 inheritance the gate already used +for YR) — **no new byte checks for the addend**. + +**Reuse verbatim.** The three convolution relations (λ, xR, yR — Q0/Q1/Q2 + +C0/C1/C2) are byte-for-byte today's ECDAS machinery; `carries_lambda/xr/yr` +are reused unchanged by the witness already. Gate lemmas L1/L2/L3/L4 port +as-is. + +**The four things that are genuinely new** (and where the bugs will be): + +1. **Addend-bus binding** — the pending digit bits ride the accumulator + tuple exactly as `op` does today. +2. **Double rows carry addend `(0,0)`.** Verified algebraic fact: on a + double the addend cancels out of all three relations (λ's op=0 branch + uses neither coordinate; xR's `−xg` cancels against `(1−op)(xg−xa)`; yR + uses neither). So the Addend receive is gated by `Sum3(s1,s2,s3)` and + stays silent on doubles. **Re-derive this before relying on it.** +3. **Telescoping breaks in exactly two places** (`layout-lock.md:118-123`): + the **precompute row's `a` is P1**, not the previous row's result (it is + a standalone chord add `P1 + P2`, *off* the accumulator line), and the + **correction row's `a`** is the last accumulator. Everywhere else + `a = prev.r` holds. This is the single most likely source of a silent + soundness hole — treat it as such. +4. **The three NEW load-bearing canonicalization checks**: `yP2 < p`, + `xQ < p`, `yQ < p`. Without `yP2 < p` a prover submits `yP2 + p` (fits in + 32 bytes) — same point mod p, **opposite parity as bytes**, flipping the + sign of Q. Without `xQ/yQ < p` the guest keccaks a shifted coordinate to + a different address. Same class as the gate's N6 finding. These are not + optional hygiene; each one is a forgery if dropped, and phase E has a + negative control for each. + +**Schedule the chip must accept** (`layout-lock.md:25-39`): dense-doubling +blinded Shamir/Straus, MSB-first, acc seeded at T₀ — one double every round +*always* (no skip-ahead, so **no `nb_or` column**; DESIGN's sketch was wrong +here), the add sharing the double's round, then the correction row. + +**Row budget to hit** (measured, not estimated): mean 449.1 rows per +ecrecover. **For capacity use 514, not `layout-lock.md`'s 471** — 471 is only +the max over *random* scalars. The worst case over the valid input domain is +`(u1, u2) = (2^255, 2^255 − 1)`: both in `[1, N)`, complementary bit patterns +⇒ every one of the 256 rounds has an add ⇒ `1 + 256 + 256 + 1 = 514`. Cheap +for a submitter to construct deliberately, and verified independently. (The +all-ones case `(N−1, N−1)` gives only 449 — complementarity maximises, not +popcount.) Mean 449.1 still governs the cost model; 514 governs padding +bounds, per-ecall row allowances and any rows-per-call assertion. Worth an +explicit test that a 514-row ecrecover proves and verifies. Column targets are now **ECSM′ 1,090** and **ECDAS′ 529** per +the layout pass — not DESIGN's 1,310/525. The ECSM′ delta is P1 (bound to G, +zero columns) plus a DESIGN double-count of `xP2` canonicalization the +witness never emits; ECDAS′ gains `NB`, `S_CORR`, `PHASE`/`NEXT_PHASE` and +loses `NEXT_OP`. + +### 6.1 Findings from the layout pass — read `CHIP-LAYOUT.md` before coding + +The full column maps, bus specs and derivations are in +`thoughts/ec-recover-opt/lincomb2/CHIP-LAYOUT.md`. The load-bearing +corrections, several of which contradict DESIGN or `layout-lock.md`: + +1. **`nb` IS required — and it is now IMPLEMENTED in the witness.** + `layout-lock.md` correction #2 claimed the opposite and has been fixed in + place. Dense doubling is true, but the double and its add *share a + round*, so a double row's successor round depends on whether an add + follows — not a function of its own columns. Today's ECDAS solves this + with `NEXT_OP` + `round − 1 + next_op` (`ecdas.rs:243-253`). Without the + analog, `round` can stall and a prover can insert or drop doublings. + + **The defining constraint is op-gated — an ungated version is wrong** (it + fails on add rows, which carry their round's real digits to select the + addend but have `nb = 0`, because the row after an add is always the next + round's double): + ``` + OP · NB = 0 (degree 2) + (1 − OP) · (NB − D1 − D2 + D1·D2) = 0 (degree 3) + ``` + Degree 3 is within budget (`EcdasConstraints::max_degree()` is already 3 + for the λ relation). Both forms are asserted on every emitted row by + `check_nb_schedule`, so phase D can lift them straight out of the test. + + **Semantics, stated precisely** (an off-by-one here breaks the + recurrence): `nb` is the OR of **this row's own round's** digits — + equivalently "the next emitted row is an add at my round" — *not* the next + round's digits. This is the same predicate as today's `EcdasStep::next_op` + ("1 ⇒ next row adds at this round"), so **phase D can reuse the existing + `NEXT_OP` column and the `round − 1 + next_op` outgoing expression + unchanged**; the witness asserts the two never diverge. The chain still + drains at the sentinel round `−1` for free, since a round-0 iteration's + last row always has `nb = 0`. + + Verified additive: `s.next_op` occurred exactly once in the pre-change + file (a plain struct-field copy at `build_step`'s tail, feeding no + numerator, quotient or carry array), and the row statistics are + bit-identical to phase A's lock (mean 449.1 / max 471 over 512 cases). + `cargo test --release -p ecsm --lib` → **26 passed, 0 failed** + (21 phase-A + 4 phase-C + 1 new), independently re-run. +2. **`OP = S1 + S2 + S3 + S_CORR` is missing from every doc.** The + double-row addend cancellation is real (re-derived from the live `eval` + body: λ's `xg`/`yg` sit inside the `op·(…)` product; xR's `−xg(i)` + cancels the `+xg(i)` from `−(1−op)(xa−xg)`; yR contains neither), **but + without this gating constraint it is forgeable** — a prover sets `S2 = 1` + on a double row and mints a spurious Addend receive. +3. **The error row needs `OK·STATUS = 0` and `STATUS·S_INV = 1 − OK`.** + Split `MU` (real ecall ⇒ Ecall receive + all MEMW) from `OK` (chain + proven ⇒ every relation and chain bus), with `OK·(1−MU) = 0`. "A lying + status only wastes cycles" holds for `status ≠ 0`, but **`status == 0` + must *oblige* the proof** — otherwise a prover sets `OK = 0`, writes + `status = 0`, and the guest reads a fabricated Q. Two constraints, one + column, distinct error codes preserved. +4. **`round` cannot discriminate the telescoping breaks.** Precompute and + correction are both emitted with `round = 0` (`witness.rs:810`, `:900`) + and the main loop also produces genuine round-0 rows. Proposed fix: a + `PHASE` element in the Ecdas′ tuple splitting the chain into three + separately-keyed segments (0 = precompute, 1 = main, 2 = correction), + each pinned at both ends by ECSM′ with multiplicity `OK`. Bonus: this + drops `genX`/`genY` (64 elements) from the tuple. +5. **JointBit needs its own bus id (33); Addend keeps 29.** (32 was the + original proposal but phase C claimed it for `EcT0`; `Bit = 30`, + `GlobalMemory = 31`.) Bus elements + that are zero on a row are **skipped** (`crypto/stark/src/lookup.rs:676-679`, + a deliberate optimization) and positions are α-weighted, so trailing-zero + padding is invisible: `[a,b,c]` and `[a,b,c,0]` have identical + fingerprints, and arity never separates chips. Since the old chips live + alongside the new ones until phase G, a `Bit[ts, round, stream=0]` send + would alias an old-ECDAS send exactly. Use a stream tag ∈ {1,2}, never 0. +6. **Addend multiplicity is `Multiplicity::Linear`, not `Sum3`.** `Sum3` + covers the three scalar addends but leaves the correction row unable to + receive. Still one interaction. Tuple `[ts, sel, x(32), y(32)]`, + `sel ∈ {1,2,3,4}` — never 0, per finding 5. Precompute reuses `sel = 2` + (its addend genuinely is P2). +7. **`len ≤ 256` — fix APPROVED, NOT YET LANDED.** As of this writing + `ec_t0.rs` still has `NUM_REAL_ROWS = 257` / `NUM_ROWS = 512` and still + carries the consumer-obligation text at `:30-35`. **Verify the code + before relying on the resolution below.** The hazard is real: the table + pads rows + 257..511 with `x = y = 0`, so an unconstrained `len` would resolve to the + off-curve `(0,0)` and the correction row would add it. The fix landed on + the *table* side, not the consumer side (my original note put it in the + wrong phase): the table now stores `LEN_M1 ∈ [0,255]` in 256 real rows + with **no padding**, and keys the receive with `LEN_M1 + 1` via + `LinearTerm::Constant(1)`. The byte bound *is* the range check, so phase D + inherits no obligation and must **not** re-add a redundant consumer check. + (Safe because `len = max(msb u1, msb u2) + 1` with both scalars non-zero + ⇒ `len ∈ [1, 256]`, so `len = 0` is unreachable and no row is wasted.) +8. **DESIGN §3's justification for `yP2 < p` is wrong** — see §11 risk 7. + +**Touch list** (verified refs). `prover/src/tables/ecsm.rs` (911 lines, 667 +cols, `cols` `:34-110`, `bus_interactions()` `:300`, `EcsmConstraints` `:704`, +`eval` `:839`) and `ecdas.rs` (463 lines, 521 cols, `cols` `:32-64`, +`bus_interactions()` `:152`, `eval` `:427`) — **prefer new sibling modules** +so the old chips stay byte-identical and their tests stay green. + +- **Registration: there is no table enum.** `VmAirs` is a plain struct, one + field per table — `prover/src/lib.rs`: struct `:487-517`, `air_trace_pairs()` + `:521-592` (prover), `air_refs()` `:595+` (verifier), construction + `:760-761`, struct literal `:866-867`, imports `:55-56`. +- **AIR constructors live in `prover/src/test_utils.rs`**, despite the name — + `create_ecsm_air` `:928-937`, `create_ecdas_air` `:940-949` are the + production ones `lib.rs` calls. +- **Addend bus**: `BusId` in `prover/src/tables/types.rs` — **id 29 is free** + (`Ecdas = 28`, `Bit = 30`, `GlobalMemory = 31`). Three sync points: enum + `:255`, `name()` `:365-393`, `TryFrom` `:396-425`. +- **Collectors**: `trace_builder.rs` — clone `collect_ecsm_ops` `:821-949` + (MEMW schedule contract in its doc comment `:821-827`); hook in + `collect_ops_from_cpu` `:536-713` at `:648-655`; classification bit + `cpu.rs:189-190`, `:236-237`, `:355`. `collect_ops_from_cpu` returns a + **10-tuple** destructured at `:2764`, `:2818`, `:2960`, `:3003`, `:4264`, + `:4282`, `:4341`, `:4355` — all need the extra element. Trace plumbing: + `Traces` fields `:2718-2722`, gen closures + rayon `:3363-3365`, `:3417`, + `:3444`, `:3478`, `:3545`, cell accounting `:3805-3806`/`:3912-3913` (main), + `:3953-3954`/`:4042-4043` (aux). +- `collect_bitwise_from_ecsm` `:2285` / `_ecdas` `:2325` (wired at + `:3078-3079`) must **mirror `bus_interactions()` exactly** — sends and + multiplicities, including the paired `AreBytes` from `42ba68ff`. The + comments at `:2290`/`:2329` say so; a mismatch here is a silent bus break. +- ~~Pinned per-table column/interaction counts in `trace_builder_tests.rs`~~ + — **wrong**: those assertions live inside a keccak-specific test module, + not a general registry, and ECSM/ECDAS have no entries there at all. The + EC-table precedent is to pin layout and bus shape in the table's *own* + test file (see `ec_t0_tests::layout_is_as_documented` / + `bus_interaction_shape`). Follow that. + +**T₀ sign gotcha for the correction row.** The table stores the **negation** +`−2^i·T₀`, matching what `lincomb2_witness` passes as the correction row's +addend (`witness.rs:888` `neg_tpow`, used at `:896-898`; `build_step` writes +the addend to `x_g`/`y_g` at `:364-365`). So the lookup wires straight into +the addend columns with **no in-circuit modular negation**. But the witness +*also* records `x_t0_pow`/`y_t0_pow` (`:936-937`), which hold the +**positive** `2^len·T₀` — the opposite convention. `x` is shared +(`x(−P) = x(P)`); `y` is negated. If phase D binds the addend from the +table, `y_t0_pow` is redundant. Do not mix the two. + +**Acceptance gate.** +- Trace-level: for ≥100 random ecrecover inputs, the generated trace + satisfies every constraint (the debug trace validator), and the chip's Q + equals `lincomb2_witness`'s Q. +- Bus balance: all buses balance, including the new Addend bus + (`DEBUG_BUS_TRACKER=1`). +- A real end-to-end proof of a guest calling the new syscall **verifies**. +- The old ECSM/ECDAS tests still pass untouched. + +--- + +## 7. Phase E — z3 soundness gate + +Port the existing gate (`thoughts/ec-recover-opt/gate/`, L1–L8 all green on +the current chips) to the new layout. Structure and harness +(`gate_common.py`, `positive_real_witness.py`) carry over. + +- **Ports unchanged**: L1, L2 (recompute offsets), L3a/L3b, L4, L5a. +- **Replaced**: ~~L5b → the NUMS reduction argument~~ — **this cannot be + discharged as specified** (see the banner). L5b is instead replaced by the + **non-degeneracy check** on add rows, which is unconditional and needs no + assumption. Prove: the check is imposed on exactly the rows that consume an + addend (all three scalar addends *and* the correction row), never on + doubles, and that it is not satisfiable when `xA = xB`. +- **New negative control, derived from a working attack**: ablate the + non-degeneracy check and feed the gate the construction from + `oracle/nums_blinding_probe.py` — **it must go SAT**. This is the strongest + control in the suite because the forgery is real, not hypothesised. + Structure the check so it can be cleanly ablated for this test. +- **Redone (riskiest work in the whole project)**: **L6** — the joint + schedule: two Bit streams, Addend-bus binding via tuple-carried digit + bits, per-scalar counting. Two interleaved counting arguments. The + exact-MSB sub-lemma (old L6.5) **drops** — blinding makes any + `len ∈ [max_msb+1, 256]` yield the correct Q, since extra leading doubles + just double T₀ and the keyed correction absorbs them. +- **Redone**: L7 — small-joint-scalar unrollings vs the extended oracle. +- **New negative controls (each must SAT, i.e. forgery reappears when the + check is removed)**: drop `yP2_SUB_P` (the §3 parity-flip attack); drop + `xQ`/`yQ` canonicalization; addend-selector tamper; status-contract + mismatch; correction-table wrong-`len`. +- **Anchor**: re-run the real-witness positive evaluation (the 872k-check + anchor) against a real lincomb2 trace. + +**Acceptance gate.** All lemmas UNSAT (sound), all negative controls SAT +(the gate can actually see forgeries), results written to +`gate/RESULTS.md` in the existing format. + +--- + +## 8. Phase G — guest switch + +Now, and only now, the deletion. `crypto/ethrex-crypto/src/lib.rs`: + +- **The call site does not change.** `lib.rs:116-117` is already + `ecsm_lincomb2(...).unwrap_or_else(|| ProjectivePoint::lincomb(...))` — + exactly the shape the status contract needs. Only the *body* of + `ecsm_lincomb2` changes: four oracle queries + `solve_y` → one syscall, + `status != 0` ⇒ `None` ⇒ existing fallback. +- **Delete**: `lincomb2_with_oracle` (~lib.rs:195-250), `solve_y` + (~:252-272), and `scalar_near_edge` if it has no other caller — check; + keep `affine_xy`/`point_from_xy` if still used. +- Keep the guest-side `(r, v)` decompression exactly as is: **the guest is + and remains the parity authority** (proven CPU execution). The chip's new + obligations are membership + canonicalization only. + +**Acceptance gate.** ethrex-crypto tests green; the 40-signature differential +green; a real block proves and verifies; guest cycle count measured (expect +~100–150k fewer cycles/ecrecover from the removed round-trips and inversion). + +--- + +## 9. Phase H — bench + +Extend `thoughts/ec-recover-opt/gen_ec_bench.sh` with an ecrecover-loop +guest. Measure (a) EC table rows/cells before vs after, (b) the EC share of +total prover cells on a real block — the multiplier that converts −74.3% EC +cells into a whole-prover number. + +**The always-on cost of EC_T0 — RESOLVED, and it is negligible per proof.** +The concern was that every proof carries a 256×66 table even with no EC ops. +It does not: `field_elements_by_table` counts EC_T0 as +`EC_T0_COLS - EC_T0_PRECOMPUTED` = 66 − 65 = **1 committed column** (the +multiplicity) × 256 rows — the same treatment `KECCAK_RC` gets +(`trace_builder.rs:4364` and `:4315`). The other 65 columns are constants +fixed by the **preprocessed commitment**, committed once rather than per +proof. That is why a per-table breakdown reports ~1k cells for EC_T0 rather +than ~17k, and it is correct accounting, not a measurement bug. + +**What is NOT resolved by that**: the extra AIR still costs the recursion +guest per-AIR opening work, which is a different axis from committed cells +and remains worth watching. `include_halt` is the precedent for a +conditionally-included AIR if it ever matters. + +**Benches run on the bench server, not locally** — hand the user the +command; do not run or schedule them here. + +**Target to confirm: −61.9% EC cells at the mean** (0.559M vs the 1.467M +post-`42ba68ff` baseline, at 449.1 rows), and **−56.4% at the 514-row worst +case** (0.640M). Report both; do not quote only the flattering one. If the +measured number lands materially below either, say so plainly rather than +reframing the target. + +**Three baselines are in circulation and two of them are wrong. Quote +neither:** + +| figure | why it is wrong | +|---|---| +| DESIGN's **−74.3%** | denominated against the **pre-pairing** 1.69M baseline, but the AreBytes pairing already shipped (`42ba68ff`) — it re-banks a banked win | +| an earlier draft of this section's **−70.2% / 0.437M** | post-pairing but **pre-`D_INV`** — written before the non-degeneracy relation that closes the degenerate-add forgery, which costs ~129 cols and ~96 interactions/row | +| **−61.9% / −56.4%** | ✅ current: measured against the live baseline with `D_INV` in | + +The headline moved from ~−70% to −61.9% because that is what unconditional +soundness cost. It is the right trade and should be stated as one: the design +originally bought its extra ~8 points by resting on a T₀-dlog assumption that +turned out **not to hold** (see the banner). Also note DESIGN's "−70.4% +standalone" is *unpaired vs unpaired* while the old −70.2% was *paired vs +paired* — two different quantities that happened to land 0.2 points apart; +never treat that coincidence as confirmation. + +Verdict unchanged: better than **2.2×** the 2× bar, with no computational +assumption. + +--- + +## 10. Open decisions + +| # | Decision | Status | +|---|---|---| +| 1 | Status in register vs memory | **Decided: register** (§2) — the `write_register = false` objection was mistaken; COMMIT sets the precedent | +| 1b | P1 general vs bound to G | **Decided: bound to G** (§6) — the witness has no `mem_p1`, so a general P1 is not provable today. Zero-cost via constant MEMW reads; ABI stays general | +| 2 | NUMS assumption named in spec | **Needs user sign-off** (§5) | +| 3 | T₀ table stores `+2^i·T₀` or `−2^i·T₀` | Phase C decides, must match witness | +| 4 | New chip modules vs in-place rework | Recommend new modules (§6) | +| 5 | GLV (4-way, −41% further) | **Deferred** until lincomb2 benches (DESIGN §7a) | + +## 11. Known risks + +1. **L6 redo** — two interleaved counting arguments; the riskiest proof work. +2. **Telescoping special cases** (precompute off-line, correction row) — the + likeliest silent soundness hole. +3. **Preprocessed-table plumbing** for T₀ assumed cheap on the keccak_rc + precedent; unverified until phase C. +4. **Row-shape estimate** was ±5%; phase A collapsed the band (449.1 + measured vs 448 estimated), so the cost verdict now rests on measurement. +5. **Chip constraint tests hardcode constraint indices.** + `prover/src/tests/ecsm_tests.rs:16-21` pins `IDX_KBITS_ZERO = 257`, + `IDX_X2_CONV0 = 258`, … into the single `eval` body. Any edit to a chip + reshuffles them. Expect churn there, and do not "fix" a failing index by + renumbering until you know which constraint actually moved. +6. **Ecall-bus balance on the error path** (§2) — a syscall with no matching + receiver unbalances bus 19. Phase D must handle the `status ≠ 0` case, + which has no chain to prove. See §6.1 finding 3 for the two constraints + that make it *sound* as well as balanced. +7. **`yP2 < p` may not be load-bearing at all, and DESIGN's reason for it is + wrong.** DESIGN §3 argues `yP2 + p` is "opposite parity as bytes" and + flips P2's sign. But negation is `(x, p − y)`, not `(x, y + p)`; and + `y + p ≡ y (mod p)` is the *same* point, so Q is unchanged. Decisively, + **both `y` and `p − y` are already `< p`**, so a `< p` test cannot + separate them — it cannot be the parity defence. What actually binds the + sign is MEMW plus the guest being parity authority + (`crypto/ethrex-crypto/src/lib.rs:98-104`). Keep the check (the witness + emits it, ~40 cells, good width-audit hygiene), but **expect phase E's + negative control for it to return UNSAT, not SAT** — and do not "fix" the + gate when it does. `xQ < p` and `yQ < p` remain genuinely load-bearing: + the output bytes get keccak'd, which is exactly the XR_SUB_P/N6 argument. +8. **~~The width audit has not been re-run for a *varying* addend.~~ — + DONE, and the widths hold** (`WIDTH-AUDIT.md`). Worst case 2^24.4 against + 2^64, i.e. **~2^39 of headroom**; z3 UNSAT ×36 on both steps with the + addend limbs free bytes, plus 36,000 corner samples and 6,346 real rows + cross-checked against the prover's own quotients/carries (38,076 + comparisons, 0 mismatches). **No new constraint, and `P12` does NOT need + canonicalization** (priced anyway at ~80 cells; recommendation: skip — + the only freedom a missing `< p` leaves is the encoding `v + p`, which + denotes the same field element and never leaves the chip; contrast + `xQ/yQ`, which do leave and get hashed). + + **Correction to an earlier note in this plan:** `chips-map.md:93-100` was + cited as having derived the bounds assuming a *canonical* addend. It does + not — item 4 there is titled "Non-canonical reps mid-chain" and already + concludes the relations are mod-p with the quotient absorbing. That + reasoning generalizes unchanged; the genuine gap was coverage of an + addend that *varies* or is chip-produced, which the audit adds. Don't + "fix" a note that is already correct. + + `D_INV` was audited too: smallest width of the four relations, **needs no + new `CARRY_OFFSET_*` constant** (honest carries `[-581, 6041]` fit inside + `CARRY_OFFSET_XR`'s window), quotient 258 bits with `r = 3p` unchanged, + degree 3 when `op`-gated — the ≤3 budget is untouched. + + *Limitation stated honestly by the audit*: the completeness table is a + measurement plus a structural-invariance argument, not a closed-form + worst case. Completeness-only, so a miss costs an unprovable honest + witness, never a forgery. +9. **Byte-ness inheritance depends on the Addend/Ecdas bus staying + one-element-per-byte.** `point_coord_busvalues` (`ecsm.rs:272`) emits 32 + separate `Packing::Direct` elements, which is what makes tuple equality + per-limb and lets a receiver inherit byte-ness without re-checking. Repack + it (e.g. `Word4L`, to shrink the bus) and a receiver can satisfy the same + packed value with a different decomposition — its limbs carry no range + check, and a single ~2^29 non-byte limb breaks the integer identity. The + margin against *malformed* limbs is small even though the margin against + *byte* limbs is astronomical. Now documented at the helper. Two agents + independently hit this hazard (phase C rejected `Word4L` for the EC_T0 + table on the same grounds), which is why it is recorded as a standing + invariant rather than a one-off note. + +## 12. Corrections already folded in + +Recorded so they are not rediscovered: `execution.rs:424-456` is **not** stale +— the real path is `executor/src/vm/instruction/execution.rs`, the DESIGN doc +just omitted the directory. DESIGN's `lookup.rs:1336-1349` is off by ~2 lines +(`crypto/stark/src/lookup.rs:1328-1360+`; `Sum3` `:1350`, `Linear` `:1356`) — +the claim holds, only the numbers were wrong. DESIGN's "`spec/src/ecsm.toml` +references confirmed dead" is **correct** (`git ls-files spec` finds no EC +source; `spec/book.typ:51` has keccak, no EC chapter), but two in-repo comments +still point at it — `prover/src/tables/ecsm.rs:9` and +`trace_builder.rs:907` — to be fixed when the phase-E0 chapter lands. diff --git a/thoughts/ec-recover-opt/lincomb2/L6-COUNTING.md b/thoughts/ec-recover-opt/lincomb2/L6-COUNTING.md new file mode 100644 index 000000000..a82d1526c --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/L6-COUNTING.md @@ -0,0 +1,332 @@ +# L6 — the joint-schedule counting argument + +> ## STATUS: the break in §2 is CLOSED. L6 HOLDS. +> +> This document was written against a chip that did **not** gate its digit +> sends. That gate landed as `ecdas2.rs` **idx 22..=27**, +> `(1 − MU)·{D1, D2, S1, S2, S3, S_CORR} = 0` — the §4 fix plus the recommended +> selector companions. With it present, both z3 queries of §2 go **UNSAT** +> (`gate/l6_joint_counting.py`, L6-D) and §3's argument goes through +> unconditionally. +> +> **§2 is kept verbatim, as the derivation of a live hole that this gate found +> and as the specification of the negative control that now guards it** +> (`gate/l8_negative2.py` N1). Read it as history, not as the current state. +> Findings §6.1 and §6.2 are both **DONE**; §6.3 (the `JOINT_CHAIN_ID` comment) +> is done in `ecdas2.rs:160-171`. +> +> Column indices and line numbers below are refreshed to `feat/ec-lincomb2` +> @ `bc62f00e` (ECDAS2: 658 columns, **288** constraints). + +**Historical verdict (pre-fix): L6 does NOT hold for `ecdas2.rs` as written. +There is a constructive break, and it is worse than the NUMS finding — it yields +an ARBITRARY CHOSEN recovered public key, i.e. an arbitrary chosen transaction +sender, with no discrete log and no search.** The fix is two degree-2 +constraints and no new columns. + +Everything else in L6 holds. §3 writes out the parts that are proved; §2 is the +break; §4 is the fix; §5 records the four mechanisms that were checked rather +than assumed and came back clean. + +Reproduce: `/bin/python thoughts/ec-recover-opt/gate/l6_joint_counting.py` +(log: `gate/logs/l6.log`). Model transcribed by reading `prover/src/tables/ecdas2.rs` +and `ecsm2.rs`; convolution carries are out of scope here (that is +`WIDTH-AUDIT.md`) — this is about the *schedule*. + +> **Column indices in this document are today's and will move.** They did: +> `D_INV` landed and took ECDAS2 from 529 to 658 columns and 217 to 288 +> constraints. Nothing in the argument depends on an index: it depends on +> *which constraints and which multiplicities exist*. + +--- + +## 1. What L6 has to establish + +For one ecall timestamp `ts` with `OK = 1`, the bus balance plus the per-row +constraints must force the joint chain to be exactly the honest schedule: + +- exactly one doubling per round, `round = len−1 … 0`; +- an add at round `r` iff the joint digit `(u1_r, u2_r) ≠ (0,0)`, exactly once, + consuming exactly the addend those digits select; +- every set bit of `u1` and `u2` consumed exactly once at its own round; +- no inserted, dropped or reordered rows; +- the three phases (precompute / main / correction) each occurring exactly once + with the right endpoints. + +The exact-MSB sub-lemma (old L6.5) drops: blinding makes any +`len ∈ [max_msb+1, 256]` yield the same `Q`. + +## 2. THE BREAK — padding rows are live digit senders + +*(Closed by idx 22..=27 — see the status header. Kept as the derivation and as +the spec of negative control N1.)* + +### 2.1 The mechanism + +ECDAS2 sends the per-stream digits as + +```rust +// ecdas2.rs:601-612 (was :459-470 when this was written) +for (stream, col) in [(1u64, cols::D1), (2u64, cols::D2)] { + out.push(BusInteraction::sender( + BusId::JointBit, + Multiplicity::Column(col), // <-- NOT MU-gated + vec![ts_lo(), ts_hi(), packed(cols::ROUND), BusValue::constant(stream)], + )); +} +``` + +and — **at the time this was written** — no constraint tied `D1`/`D2` to `MU`. +Reading every occurrence of `MU` in `Ecdas2Constraints::eval`, it appeared +exactly three times: idx 0 (`IS_BIT`), idx 20 (`MU·(1−PH1−PH2)·(S2−1)`), and +inside `rq()`. There was no `D1·(1−MU) = 0`. There is now: idx 22..=27, +`ecdas2.rs:988-1003`. + +**The old chip has precisely this defence, for precisely this reason.** +`ecdas.rs` idx 4 is `NEXT_OP·(1−MU) = 0`, gating the multiplicity of its own +`Bit`-bus sender. ECDAS2 dropped it while adopting the same pattern. + +A padding row is inert on every other bus — its `Ecdas` receive and send, +`AreBytes` and `IsHalfword` sends are all `mu()`-gated, and its `Addend` receive +is gated by `ΣS`. But its digit send is **live**. + +### 2.2 The padding row is satisfiable + +With `MU = 0, PH1 = 1, D1 = 1, ROUND = r` and everything else zero except +`NB = 1` (forced by idx 13), every constraint of the pre-fix chip held (217 of +them then; the same rows are idx 0..=21 and 28..=287 of the 288 today): + +| constraint | check | +|---|---| +| idx 0-10 `IS_BIT` | all columns are 0/1 | +| idx 11 `PH1·PH2` | `PH2 = 0` | +| idx 12 `OP·NB` | `OP = 0` | +| idx 13 `(1−OP)(NB−D1−D2+D1·D2)` | forces `NB = 1`; harmless, the Ecdas send is µ-dead | +| idx 14 `OP = ΣS` | `0 = 0` | +| idx 15,16 `(1−PH1)·D` | satisfied by `PH1 = 1` | +| idx 17-19 | all zero | +| idx 20 | **µ-gated — `MU = 0` kills it** | +| idx 21 | `PH2 = 0` | +| the conv blocks (idx 28..=287 today) | all limbs zero, `rq` is µ-gated ⇒ `S_i = 0`, carries 0 | +| idx 22..=27 (**the fix**) | `(1 − MU)·D1 = 1 ≠ 0` — **this is what now rejects the row** | + +z3: **SAT**. Note also that `ROUND` is only byte-checked through a µ-gated +`AreBytes` send, so on a padding row it is entirely free. + +### 2.3 The schedule-level forgery + +At a round `r` where `u1`'s bit is set and `u2`'s is not, the honest chain has a +double with `(D1,D2) = (1,0)` — hence `NB = 1` — and an add consuming `P1`. + +The prover instead sets the double's `D1 = D2 = 0`, so `NB = 0` and **no add +follows**, and supplies the round's `2·u1_bit(r) = 2` JointBit count from **two +phantom padding rows** carrying `D1 = 1` at `ROUND = r`. Balance is satisfied, +the chain never adds `P1` at round `r`. z3: **SAT**. + +The chain then computes `Q' = (u1 − a)·G + (u2 − b)·R`, where `a`, `b` are the +dropped bit-sets, while the proof claims `u1·G + u2·R`. + +### 2.4 Why it is critical: an arbitrary chosen sender + +Unlike the NUMS finding — which gave only a one-parameter family and needed +~2^160 grinding to aim — here the attacker picks the *effective* multipliers +first, so no discrete log is required: + +1. name the target public key `T` (a key the attacker does not hold); +2. choose `u1' = u2' = 1`, so **`R = T − G`** — a plain point subtraction; +3. set `u1 = 1 + 2^m` (bit `m` unset in `u1'` and in `u2`), `u2 = 1`, and drop + bit `m` by the §2.3 construction; +4. back-solve the signature from `r = x(R)`, `v = parity(y(R))`: + `z = −u1·r mod N`, `s = u2·r mod N`. + +The chain computes `1·G + 1·(T − G) = T`. Verified numerically end to end: + +``` + u1 = 257 (bit 8 will be dropped), u2 = 1, len = 9 + Q' == target : True + Q' != honest Q : True + guest recomputes u1: True u2: True lifts R: True +``` + +Cost: a handful of extra padding rows. Any `(u1', u2')` works; `u1' = u2' = 1` +is just the shortest to write. + +## 3. What L6 does establish (given the fix) + +Fix §4 first; then the following goes through. `ts` is fixed, `OK = 1`. + +**(a) Phase separation.** `PHASE = PH1 + 2·PH2` with `PH1·PH2 = 0` (idx 11) so +`PHASE ∈ {0,1,2}`. Every ECDAS2 row carries `phase` unchanged from its receive to +its send (same columns in both tuples), so phase is a path invariant, and the +ECSM2 seeds/drains pin it to the constants 0/1/2. + +**(b) Exactly one segment per phase.** ECSM2's six chain interactions all carry +multiplicity `OK`, which is `IS_BIT` (idx 1) — so one seed and one drain per +phase. Two ECSM2 rows cannot share a `ts` (contract C6: the `Ecall` receive +would double against the CPU's single send; C7 gives distinct ts per ecall). + +**(c) No cycles, and paths end only at drains.** Along a row, +`round' = round − 1 + NB` and `op' = NB`, with `OP·NB = 0` (idx 12): + +- `OP = 1` (add) ⇒ `NB = 0` ⇒ `Δround = −1`; +- `OP = 0` (double) ⇒ `Δround ∈ {0, −1}`, and `Δround = 0` forces `op' = 1`, + i.e. the successor is an add, which then decrements. + +So `round` never increases and any cycle would need every step at `Δ = 0` — +impossible, since a `Δ = 0` step is always followed by a strict decrease. The +drain tuple has `round = −1`, which no row can receive because `ROUND` is +byte-checked. Balance therefore decomposes the rows of each phase into exactly +one seed→drain path. + +**(d) Phases 0 and 2 are exactly one row each.** Both seeds carry `round = 0, +op = 1`. An add has `NB = 0`, so the single row sends `round = −1, op = 0` — +exactly the drain. No second row is possible. Their selectors are pinned by idx +20 (`S2 = 1`, the precompute adds `P2`) and idx 21 (`S_CORR = 1`, the correction +adds `−2^len·T₀`), with idx 15/16 forcing `D1 = D2 = 0` on both. + +**(e) The main chain is one doubling per round, plus an add iff a digit is set.** +The phase-1 seed is `(T₀, round = LEN_M1, op = 0)`. By (c) the path is +`double(L−1) [add(L−1)] double(L−2) [add(L−2)] … double(0) [add(0)]` and then +drains. Idx 13 makes `NB = D1 ∨ D2` on a doubling, so the add at round `r` +exists iff that round's joint digit is non-zero. + +**(f) Digit consumption is exact.** For each `(i, stream)`, balance gives +`#{rows with ROUND = i and D = 1} = 2·u_bit(i)`. Each row's multiplicity is a +single `IS_BIT` column, so each contributes 0 or 1 and the only decomposition of +2 is `1 + 1`. With the fix, only live rows can contribute, and by (e) at most two +live rows share a round — the double and its add. Hence: + +- `u_bit(i) = 1` ⇒ **both** rows exist and **both** carry `D = 1`; +- `u_bit(i) = 0` ⇒ neither does. + +A set bit above `LEN_M1` has a 2× receive with no possible sender ⇒ imbalance ⇒ +`len ≥ max_msb + 1`. The upper bound `len ≤ 256` is structural: the `EC_T0` +table has exactly 256 rows and no padding, so a lookup outside `[1, 256]` matches +nothing. **This is where L6.5 drops** — any larger `len` is fine, because the +extra leading doublings only double `T₀` and the keyed correction absorbs them. + +**(g) The addend matches the digits.** On a live main-chain add, idx 17 gives +`S_CORR = 0`, idx 14 gives `S1+S2+S3 = 1`, and idx 18/19 give `S1+S3 = D1`, +`S2+S3 = D2`. Solving: `(1,0) ⇒ S1`, `(0,1) ⇒ S2`, `(1,1) ⇒ S3`, and `(0,0)` is +**unsatisfiable** — no spurious add. On a live doubling `OP = 0` forces every +selector to zero, so the `Addend` receive is silent. Each case machine-checked +(z3 UNSAT on the negation). + +Combining (a)-(g): the chain is exactly the honest schedule, and by the Addend +balance each consumed addend is the one ECSM2 published — `G` (a constant), `P2` +(MEMW-bound), `P12` (the phase-0 drain) or the `EC_T0` constant. + +## 4. The fix — LANDED + +``` +(1 − MU)·D1 = 0 +(1 − MU)·D2 = 0 +``` + +Two degree-2 constraints, no new columns, the exact shape of `ecdas.rs` idx 4. +With them, both z3 queries of §2 go **UNSAT**. + +Recommended in addition: gate the selectors too. A `MU = 0, OP = 1, S1 = 1` row +still mints a spurious `Addend` **receive**. That is harmless on its own — it +injects nothing into the chain and merely forces the publisher to inflate `N1` — +but it is the same class of hole and `(1−MU)·S* = 0` closes it for four more +degree-2 constraints. Alternatively make the multiplicities `MU·D1` / `MU·ΣS` if +the `Multiplicity` type admits a product; that is the structurally right fix and +removes the need for the constraints entirely. (It does not: `Multiplicity` +offers `Column`/`Sum`/`Sum3`/`Diff`/`Negated`/`Linear`, all linear — +`crypto/stark/src/lookup.rs:1328-1363`. So the constraint form is the only one +available today.) + +**Both landed together** as `ecdas2.rs:988-1003`, idx 22..=27, over all six +columns `{D1, D2, S1, S2, S3, S_CORR}`. + +**Phase E's negative control** is `gate/l8_negative2.py` N1: it ablates the gate, +feeds the §2.3 schedule, and requires SAT — with the untampered gate the same +query must be UNSAT. Both hold. Note the selector half of the gate makes the +spurious-`Addend`-receive scenario unreachable on `MU = 0` rows *independently of +idx 14*; see `RESULTS-lincomb2.md` §4 N4b, which was corrected for exactly this. + +A structural guard was added afterwards (`gate2_common.padding_gate_state()`): +the gated column set must **equal** the set of columns supplying a multiplicity +in `ecdas2::bus_interactions()`. That is the invariant this section is really +about, and it is now machine-checked in both directions rather than restated. + +## 5. Mechanisms checked, and clean + +### 5.1 The 2× JointBit multiplicity is genuinely stronger than 1× + +Confirmed, with a concrete counterexample at 1×. At a round where **both** +digits are set, a 1× prover splits them across the two rows — double takes +`D1 = 1, D2 = 0`, add takes `D1 = 0, D2 = 1`. Both counts balance at 1. Idx +18/19 on the add then give `S1+S3 = 0`, `S2+S3 = 1` ⇒ **`S2`**: the chain adds +`P2` where the schedule calls for `P12`. Wrong `Q`, fully satisfying. z3: SAT at +1×, UNSAT at 2×. + +The `2 = 1+1`-only argument is correct because each row's multiplicity is a +single column constrained by `IS_BIT`, so no single row can contribute 2. + +The companions `(1−PH1)·D1 = 0` and `(1−PH1)·D2 = 0` are load-bearing exactly as +their comment says: precompute and correction are both emitted at `round = 0`, +so without them a prover sets `D1 = 1` on both and satisfies `2·u1_bit(0)` with +no round-0 add at all. (They are *not* sufficient against §2, because a phantom +row can simply set `PH1 = 1`.) + +### 5.2 The bus-28 separator holds — but not for the stated reason + +`JOINT_CHAIN_ID = 1` in **tuple element 0** — `values[0]`, which lands at the +**α¹** coefficient because `alpha_offset` starts at 1 (`lookup.rs:1653`) — where +the old chain pins `0`. (`RESULTS-lincomb2.md` §3 says the same thing as +"position 1", meaning the α exponent. Element 0 / exponent 1; they are the same +element.) The claim is sound. The stated justification is not the operative +mechanism: + +- **There is no re-alignment risk to begin with.** In `compute_fingerprints` + (`lookup.rs:1651-1663`) `alpha_offset` advances by `num_bus_elements()` for + every `BusValue` unconditionally. The `if result != zero` skip at `:679` + avoids a multiply and still returns `1`, so a zero element consumes its α slot + and contributes nothing. **Interior zeros do not shift positions.** +- **What actually separates the chains** is that the fingerprints are + `bus_id + Σ_k v_k·α^k` and the two tuples differ in the α¹ coefficient + (constant `0` vs constant `1`). The difference polynomial is therefore + non-zero, and Schwartz–Zippel over the random α closes it. Lengths (133 vs 70 + elements) are irrelevant. +- **Trailing-zero aliasing is real in general** — a shorter tuple does alias a + longer one whose extra trailing elements are all zero — which is what the + `sel ≠ 0` note on the `Addend` bus correctly guards. It is simply not the + mechanism at work on bus 28. + +**No need for bus 33.** Worth rewording the comment on `JOINT_CHAIN_ID` so the +next reader does not inherit the wrong model of the fingerprint. + +### 5.3 The phase relay + +Verified. Phase-1's drain is received into `ACC_X`/`ACC_Y` and phase-2's seed is +sent from **the same columns**, so the hand-off is a literal relay; both at +multiplicity `OK`. Routing it through ECSM2 rather than along the chain is +forced, as the header says: the outgoing tuple pins the successor's `op` to +`NB`, which is 0 on the last main row, while the correction row is an add. + +### 5.4 `OP = ΣS` + +Verified load-bearing. On a live doubling it forces every selector to zero, so +the `Addend` receive multiplicity is 0. Without it the double-row addend +cancellation is still algebraically real, but the *gating* is forgeable — a +prover sets `S2 = 1` on a doubling and mints a spurious receive. + +## 6. Findings + +1. **DONE.** ~~[CRITICAL — fix before anything else]~~ **Padding rows are live + digit senders** (§2). Arbitrary chosen recovered public key. Fixed by + `(1−MU)·D1 = 0`, `(1−MU)·D2 = 0` — `ecdas2.rs:988-1003` idx 22, 23. +2. **DONE.** ~~[recommended]~~ **Gate the selectors too** — `(1−MU)·S* = 0` + landed in the same loop, idx 24..=27. The `MU·D1` product form is not + expressible (§4). +3. **DONE.** ~~[documentation]~~ **Reword the `JOINT_CHAIN_ID` comment** (§5.2) + — `ecdas2.rs:160-171` now states the α¹-coefficient mechanism and explicitly + disclaims the re-alignment story. +4. **[no action] 2× multiplicity confirmed**, with the 1× counterexample + recorded as a phase-E negative control (§5.1). +5. **DONE.** ~~[phase E]~~ **Negative controls**: `l8_negative2.py` N1 (drop the + §4 gate), N4 (drop idx 18/19), N4b/N4c (drop `OP = ΣS`); + `l6_joint_counting.py` L6-B (1× JointBit) and §5.1's `(1−PH1)·D` companions. + All present and reproducing. diff --git a/thoughts/ec-recover-opt/lincomb2/T0.md b/thoughts/ec-recover-opt/lincomb2/T0.md new file mode 100644 index 000000000..972aea80d --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/T0.md @@ -0,0 +1,57 @@ +# T₀ — the lincomb2 NUMS blinding point + +`T₀` is the "nothing-up-my-sleeve" secp256k1 point the lincomb2 joint chain +seeds its accumulator with (design §4). Its only security-relevant property: +**nobody knows `dlog_G(T₀)`** — which is what makes the incomplete-addition +edge a discrete-log event instead of an attacker-reachable forgery. That +property is what the NUMS derivation buys, and why the point must be derived +verifiably (not chosen). + +## Derivation (reproducible) + +Try-and-increment hash-to-curve: + +``` +tag = "lambdavm/ecsm/lincomb2/T0/v1" (28 ASCII bytes, no NUL) +for counter = 0, 1, 2, ...: + x = int_be( SHA-256( tag || counter_be32 ) ) # 32-byte big-endian digest as an integer + if x < p and (x³ + 7) is a QR mod p: # x is a valid curve x-coordinate + y = the EVEN square root of x³ + 7 mod p # p ≡ 3 mod 4 ⇒ y = (x³+7)^((p+1)/4) + return (x, y) + # else increment counter +``` + +- `counter_be32` = the counter as 4 big-endian bytes. +- Even-`y` is chosen for determinism (either root is on-curve; parity is + irrelevant to the blind, only knowledge of the dlog matters). + +## Result — counter = 1 + +``` +x = 0xaf319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864 +y = 0x1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0 +``` + +(counter 0's digest is not a valid curve x; counter 1 succeeds. `y` is even.) + +LE bytes (the form pinned in `crypto/ecsm/src/witness.rs` as `T0_X_LE`/`T0_Y_LE`): +``` +x_le = 6478aeb10c07491bdb9388a99aa7fb5e660a33db5ee87d296ba8910fa99a31af +y_le = a07762604a253c3f19827d21fa24e6a28c5bb0f3bcb01d0732073c1438a08114 +``` + +## Reproduced by three independent paths + +1. `crypto/ecsm/src/witness.rs::t0()` — the pinned constant (used by the witness). +2. `crypto/ecsm` dev test `t0_derivation_matches` — re-runs the SHA-256 + try-and-increment (via the `sha2` crate) and asserts it equals `t0()`; + `t0_is_on_curve_and_pinned` checks on-curve + even-y. +3. `thoughts/ec-recover-opt/oracle/lincomb2_ref.py::t0_ref()` — independent + Python derivation (hashlib), used by the oracle log. + +## For the spec chapter + +This derivation + constant must appear verbatim in the EC spec chapter (none +exists yet — a known follow-up). `2^len·T₀` for each `len ∈ [1, 256]` is the +preprocessed correction table the chip subtracts (chip phase); it is a +deterministic function of `T₀` and needs no separate trust. diff --git a/thoughts/ec-recover-opt/lincomb2/WIDTH-AUDIT.md b/thoughts/ec-recover-opt/lincomb2/WIDTH-AUDIT.md new file mode 100644 index 000000000..32472d841 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/WIDTH-AUDIT.md @@ -0,0 +1,302 @@ +# Width audit — the varying addend (IMPL-PLAN §11 risk 8) + +**Verdict: the existing widths still bound it, with 2^39 of headroom, and no new +constraint is required.** `P12` does **not** need canonicalization for this +argument. The proposed `D_INV` relation also fits inside the existing window +scheme. + +But the *reason* is not the one the census implies, and the difference matters +for anyone touching the Addend bus later: + +> The carry-width argument never depended on the addend being **canonical**. It +> depends on the addend's **limbs being bytes**. Those are different properties, +> and only the second one is load-bearing — but it is *absolutely* load-bearing: +> a single limb of ~2^29 breaks the integer-lifting argument outright. + +Byte-ness *is* proven for all four addends, through a chain traced in §3. It +survives only because the Addend bus carries **one field element per byte**. If +that tuple were ever repacked (e.g. `Word4L`, four bytes per element) the +inheritance would silently become invalid — §3.1. + +Reproduce: +```sh +cd thoughts/ec-recover-opt/oracle +/bin/python width_audit.py # intervals + corners + real-witness carries +/bin/python width_audit_z3.py 63 # z3 confirmation + negative control (~25 min) +``` +Logs: `width_audit.log`, `width_audit_z3.log`. + +--- + +## 1. What was actually asked, split into two questions + +Today's ECDAS proves `A + G` where `G` is loop-invariant, external and +canonical. Under lincomb2 the addend varies per row over `{P1, P2, P12, +−2^len·T₀}` and `P12 = P1 + P2` is an interior chip output: byte-bounded, never +proven `< p`. + +**A correction to the premise this audit was commissioned under.** The task +described `chips-map.md:93-100` as having "derived the width argument on the old +assumption" that the addend is canonical. Read directly, it did not: item 4 is +titled *"Non-canonical reps mid-chain"* and already states that `xR`/`yR`/`λ` +are only byte-checked, that "relations are mod-p (quotient absorbs), so values ≡ +correct mod p", and that curve membership propagates by induction from the +ECSM-checked seed. That reasoning is correct and generalizes to the varying +addend unchanged. What the note does not do — reasonably, since it is a census +of the *existing* single-scalar chips — is say anything about an addend that +varies per row or is produced inside the chip. This audit supplies that, and +confirms rather than repairs the existing reasoning. + +Two questions hide under "does the width argument survive", and they have +different answers, so they are kept apart throughout: + +| | question | depends on | +|---|---|---| +| **Soundness** | does the field equation `256·c_i − c_{i−1} − S_i = 0` still imply the **integer** equation? | limbs being bytes | +| **Completeness** | can the honest prover always find carries inside the windows and a quotient `≥ 0` fitting 33 bytes? | composed values being `< p` | + +A soundness failure is a forgery. A completeness failure is an honest prover +that cannot build a proof. Only the first is a security bug. + +## 2. Soundness — unaffected, 2^39 of headroom + +The lifting argument (gate L1) needs `Σ 256^i·S_i = 0` over ℤ, which follows +from the carry recurrence only if nothing wraps modulo Goldilocks, i.e. + +``` +|256·c_i − c_{i−1} − S_i| < p_g = 2^64 − 2^32 + 1 +``` + +Read the relations, not the census (`prover/src/tables/ecdas.rs:348-397`, and +its twin `ecdas2.rs`, whose header states the core is byte-for-byte identical +and which imports the very same `CARRY_OFFSET_*` constants at `ecdas2.rs:71`): +**every operand enters `S_i` as an individual byte limb** — `lam(j)`, `xa(j)`, +`ya(j)`, `xg(j)`/`xb(j)`, `yg(j)`/`yb(j)`, `xr(j)`, `yr(j)`, `q[j]`. No composed +256-bit value appears anywhere in a constraint. So the magnitude of `S_i` is a +function of the limb bounds alone, and is completely blind to whether the +composed value is below `p`. + +Maximised over byte limbs, bit `op`/`mu`, and carries inside their `IsHalfword` +windows (`c_i ∈ [−offset, 2^16−1−offset]`, with `c_63` pinned to 0 by +`ColIsZero` and `c_{−1}` structurally 0): + +| relation | offset | carry window | max \|256c − c⁻ − S\| | vs `p_g` | +|---|---|---|---|---| +| λ | 32636 | `[-32636, 32899]` | 22,771,245 | 8.1×10^11 | +| xR | 8161 | `[-8161, 57374]` | 16,723,665 | 1.1×10^12 | +| yR | 16320 | `[-16320, 49215]` | 18,739,185 | 9.8×10^11 | +| `D_INV` (proposed) | — | — | 14,578,095 | 1.3×10^12 | + +Worst case **2^24.4 against a 2^64 modulus — 2^39 of headroom.** These are +over-approximations (repeated variables such as `lam·lam` and `xa·xa` are +treated as independent, the safe direction) computed with the addend limbs +**free bytes, nothing assumed canonical**. Constraining any operand to `[0, p)` +can only shrink them. + +**The varying addend changes nothing here** because `P1`, `P2`, `P12` and the +correction constant all occupy the same `xB`/`yB` limb slots the loop-invariant +`xG`/`yG` occupied, with the same byte bounds. + +### Machine-checked, not just argued + +`width_audit_z3.py` states both steps directly to z3 with the addend limbs free +bytes, at limb indices `i ∈ {0,1,2,3,7,15,31,47,63}`: + +- **W1** (the interval arithmetic above is correct): **UNSAT ×36** — 4 relations × 9 indices. +- **W2** (`|256c_i − c_{i−1} − S_i| < p_g` directly, bypassing the interval): **UNSAT ×36**. +- 36,000 random/corner samples in `width_audit.py`: 0 interval violations. + +### The negative control, and why it fires unevenly + +**N-WIDTH** drops the byte constraint on the addend's limbs only, leaving them +free field elements, and asks the same W2 question: + +``` +lambda i=31:sat i=63:unsat +xr i=31:sat i=63:unsat +yr i=31:unsat i=63:unsat +dinv i=31:sat i=63:unsat +``` + +3 SAT is the *correct* result, not a partial failure, and the two UNSAT patterns +are both explained by the relations themselves — which is a useful check that +the transcription is faithful: + +- **`yr` never reads the addend.** Its term is `Σ lam_j·(xa − xr)_{i−j} − ya_i − + yr_i`; `xb`/`yb` do not appear. Tampering with them cannot change it. +- **At `i = 63` nothing reads the addend either.** Values are 32 bytes, so + `xb[k] = 0` for `k ≥ 32`; the convolution `Σ_j lam_j·xb_{63−j}` needs + `j ≤ 31` *and* `63 − j ≤ 31`, i.e. `j ≥ 32` — an empty index set. + +So the control fires in exactly the places where the addend is actually read. +Where it fires, wraparound becomes reachable: **byte-ness of the addend limbs is +load-bearing**, it is what this audit rests on, and §3 is therefore the most +important section of this document. + +### How much slack is there before byte-ness matters? + +A single non-byte limb of about **2^29** is enough to push `3·xa_j·xa_{i−j}` (λ, +`op=0`) or `lam_j·lam_{i−j}` (xR) past `p_g` and destroy the integer identity. +That is 2^29, not 2^63 — the margin against a *malformed limb* is small even +though the margin against *byte* limbs is astronomical. + +## 3. Why byte-ness holds for all four addends + +`ECDAS2` deliberately does **not** byte-check `XB`/`YB` (`ecdas2.rs:409-410`: +"XB/YB are deliberately absent: they inherit byte-ness from the publisher's +already-checked columns through Addend tuple equality"). Traced to its root, per +selector, by reading `ecsm2.rs:765-800`: + +| `sel` | published as | byte-ness root | canonical too? | +|---|---|---|---| +| 1 `P1` | `const_coord(GENERATOR_LE)` | **compile-time constants** — not columns at all | yes | +| 2 `P2` | `coord(X_P2)`, `coord(Y_P2)` | byte-checked at MEMW store time (contract C4, the authority `xG`/`k` already rely on) | yes, for honest input | +| 3 `P12` | `coord(X_P12)`, `coord(Y_P12)` | inherited from the phase-0 `Ecdas` drain (`ecsm2.rs:832-844`), i.e. **ECDAS2's own precompute-row `XR`/`YR`, which carry real `AreBytes` sends** (`ecdas2.rs:418-427`) | **not proven** — see §4 | +| 4 `−2^len·T₀` | `coord(X_T0N)`, `coord(Y_T0N)` | the `EC_T0` preprocessed table — generated constants under a static commitment | yes, by construction | + +The chain bottoms out at real range checks and constants; there is no cycle +(`P12`'s byte-ness comes from ECDAS2's `XR`, which is checked directly, not +inherited). + +### 3.1 The inheritance is valid only because the bus is unpacked + +`addend_tuple` (`ecdas2.rs:295-311`) lays out the coordinates with `coord()` → +`point_coord_busvalues` (`ecsm.rs:274-276`), which is + +```rust +(0..32).map(|b| packed(col + b)).collect() // 32 × Packing::Direct +``` + +— **one bus element per byte**. Tuple equality is therefore per-limb equality, +and byte-ness transfers limb by limb. + +**This is a load-bearing layout choice and should be commented as such.** Had +the tuple packed bytes (`Word4L`, `b₀ + 2⁸b₁ + 2¹⁶b₂ + 2²⁴b₃`, four columns per +element), a receiver could satisfy the same packed value with a different limb +decomposition — `(b₀ + 2⁸k, b₁ − k)` for any `k` — because its own limbs carry +no range check. Reachable limb magnitudes then run to ~2^63, far past the ~2^29 +that breaks the integer identity. A future "let's shrink the Addend bus by +packing" optimization would convert this audit's PASS into a forgery, silently. + +## 4. Completeness — measured, and structurally unchanged + +Honest carries must land in `[−offset, 2^16−1−offset]` and the honest quotient +must be `≥ 0` and fit 33 bytes. This is the half that *does* depend on composed +values. + +Measured over **6,346 real rows** from 15 lincomb2 evaluations covering every row +type, including the two that break telescoping: + +| relation | honest carry range | window | fits | min offset needed | +|---|---|---|---|---| +| λ | `[-4303, 6728]` | `[-32636, 32899]` | yes | 4303 | +| xR | `[-112, 8308]` | `[-8161, 57374]` | yes | 112 | +| yR | `[-465, 5914]` | `[-16320, 49215]` | yes | 465 | +| `D_INV` | `[-581, 6041]` | (any of the above works) | yes | 581 | + +Quotients: λ `[253, 259]` bits, xR/yR/`D_INV` 258 bits — all `≥ 0`, all far +below `2^264`. + +Per row type, showing the new shapes are not outliers: + +``` +Precompute lambda=[-95, 4619] xr=[-24, 6773] yr=[-170, 4729] +Double lambda=[-4303, 6728] xr=[-112, 8308] yr=[-368, 5914] +AddP1 lambda=[-304, 5624] xr=[-94, 7722] yr=[-300, 5686] +AddP2 lambda=[-290, 6170] xr=[-109, 8074] yr=[-328, 5509] +AddP12 lambda=[-412, 5439] xr=[-100, 7897] yr=[-465, 5700] +Correction lambda=[-146, 5019] xr=[-13, 7493] yr=[-251, 5156] +``` + +The widest carries come from **doublings**, which do not read the addend at all. + +**These are the prover's own numbers, not a reimplementation of them.** The +script derives carries and quotients independently from the group law, then +diffs them against `ecsm::lincomb2_witness` through the oracle harness: +**38,076 (quotient, carry-array) comparisons, 0 mismatches**. + +### Why the honest bound is unchanged by construction + +Beyond the measurement: the honest carry magnitude is a function of the number +of convolution products in a relation and the size of its operands. The varying +addend changes neither — `P1`/`P2`/`P12`/`−2^len·T₀` sit in the same slots the +loop-invariant `xG`/`yG` sat in, with the same term counts, and all four are +canonical for an honest prover (constants, guest-canonical input, a reduced +`ec_add` output, and generated table rows respectively). So gate lemma L2b's +minimal offsets for the single-scalar chain carry over verbatim. + +**Honest limitation:** §4's table is a *measurement over 6,346 rows*, not a proof +over all valid inputs. The structural argument above is what makes it +believable; a closed-form worst-case honest bound per relation is the remaining +gap, and it is completeness-only — a miss costs an unprovable honest witness, +never a forgery. The loose analytic bound (`max|S_i|/255 ≈ 87,000`) exceeds the +windows and is therefore too weak to serve as that proof; it must go through the +operands being `< p`. + +## 5. Does `P12` need canonicalization? + +**No — not for this argument, and not for soundness generally.** + +- The width argument needs byte-ness, which `P12` has (§3). +- `P12`'s *value mod p* is pinned by the precompute row's own three relations, + so a prover cannot publish a `P12` that is not `P1 + P2` mod `p`. +- The only freedom a missing `< p` check leaves is the non-canonical *encoding* + `v + p`, which requires `v < 2^32 + 977` and denotes the same field element. + Every downstream relation is mod `p`, so the chain computes the same thing. + A prover choosing that encoding would more likely just push its own carries + out of the windows and fail to build a proof — rejection-only. + +Contrast `xQ`/`yQ`, which *are* load-bearing: those bytes leave the chip and get +hashed, so a `+p` shift changes the recovered address. `P12` never leaves. + +**Price, if wanted as defence in depth** (the lead asked): the same +`XG_SUB_P`-style block already used three times — 16 halfword columns + 16 +`IsHalfword` sends + the overflow/carry-bit constraints, per coordinate. Two +blocks ≈ 32 columns + 32 interactions ≈ **80 committed cells on ECSM2's single +row per ecrecover**, i.e. ~0.02% of the ~430k EC cells per ecrecover. Cheap, and +unnecessary. Recommendation: **skip it**, and instead put a comment on +`point_coord_busvalues` recording that the unpacked layout is load-bearing +(§3.1) — that is where the real fragility is. + +## 6. The proposed `D_INV` relation + +Auditing the relation that closes the NUMS finding +(`FINDING-nums-blinding.log`), in the chip's own idiom: + +``` +S_i = Σ_j d_inv(j)·(xB − xA)(i−j) − [i = 0] + μ·(R·P)_i − (q3·P)_i +``` + +- **Soundness width**: worst case 14,578,095, the *smallest* of the four + relations (it has one convolution product where λ's `op=0` branch has two). + 1.3×10^12 margin against `p_g`. W1/W2 UNSAT at all nine limb indices. +- **Degree**: `op·(d_inv·(xB − xA))` is degree 3 if the relation is `op`-gated — + the same degree as the existing λ relation, so the ≤ 3 budget is unaffected. +- **Honest carries**: `[-581, 6041]`, comfortably inside any of the three + existing windows. **No new `CARRY_OFFSET_*` constant is needed** — reuse + `CARRY_OFFSET_XR = 8161` (window `[-8161, 57374]`) or + `CARRY_OFFSET_LAMBDA`; both fit with an order of magnitude of slack. +- **Honest quotient**: 258 bits, `≥ 0`, fits 33 bytes with `r = 3p` unchanged. +- **Gating is a cost choice, not a correctness one**: `x = 0` is not on + secp256k1 (7 is a quadratic non-residue mod `p`, checked), so on a doubling + row `xB − xA = −xA ≠ 0` is still invertible. An ungated relation is therefore + satisfiable everywhere; gating by `op` just lets doubling rows carry + `d_inv = 0`, `q3 = 3p` and zero carries. + +## 7. Findings + +1. **[no action] The widths hold.** 2^39 of headroom, machine-checked, with the + addend free-byte and non-canonical. +2. **[no action — premise corrected] `chips-map.md:93-100` is not wrong.** It + was cited to me as having assumed a canonical addend; it did not (§1). Its + mod-`p` argument generalizes verbatim. The gap was coverage of a varying, + chip-produced addend, which this document adds. Recorded so the correction + does not get lost and nobody "fixes" a note that is already right. +3. **[documentation, please do] Comment `point_coord_busvalues` as load-bearing.** + The 32×`Direct` layout is what makes byte-ness inheritance valid (§3.1). + Nothing currently records that packing it would be a soundness change; the + name reads like a formatting helper. +4. **[no action] `P12` canonicalization not required.** Priced at ~80 cells if + wanted anyway; recommendation is to skip. +5. **[input for phase D] `D_INV` needs no new offset constant** and no degree + budget beyond what λ already uses. diff --git a/thoughts/ec-recover-opt/lincomb2/anchor_ecrecover_lincomb2.log b/thoughts/ec-recover-opt/lincomb2/anchor_ecrecover_lincomb2.log new file mode 100644 index 000000000..9b3d31333 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/anchor_ecrecover_lincomb2.log @@ -0,0 +1,34 @@ +BONUS 3 — the 40-signature ecrecover differential, re-run through lincomb2 (phase D0) +==================================================================================== +Re-run: from thoughts/ec-recover-opt/oracle/, + /bin/python bonus_ecrecover.py +Runtime ~1m15s. + +`bonus_ecrecover.py` gained a `part3`. Part 1 (unchanged) signs 40 messages with the +`ecdsa` PyPI package (RFC 6979 deterministic), recovers the key with `ec_ref.ecrecover`, +and cross-checks against the library's own recovery. It now hands that corpus to +part 3, so part 3 runs on literally the same 40 signatures — not a regenerated set. + +Part 3 redoes the recovery through the lincomb2 path exactly as the guest will: +lift R from (r, parity v), u1 = -z/r mod N, u2 = s/r mod N, then compute +pk = u1*G + u2*R via + - `lincomb2_ref.lincomb2` (affine reference), + - `jacobian_ref.lincomb2` (independent Jacobian/LSB-first implementation), + - `lincomb2_ref.lincomb2_rows` (the NUMS-blinded joint chain the chip proves), +and requires all three to equal the signer's actual public key. + +Parts 1 and 2 reproduce their previously committed values (`../oracle/bonus.log`) +byte-for-byte; part 3 is the new line. + +--- raw output --- + +BONUS 1 (ecrecover 3-way, 40 sigs): PASS (0 failures) +BONUS 2 (parity-authority identity, 200 cases): PASS (0 failures) +BONUS 3 (ecrecover via lincomb2, 40 sigs): PASS (0 failures; 40 recovered through the NUMS-blinded joint chain) + chain rows: mean 449.4 min 434 max 469 + +--- note --- + +Chain rows mean 449.4 on real RFC-6979 signatures, against the layout lock's measured +mean of 449.1 (Rust) / 449.7 (Python, random scalars). Real ecrecover traffic sits +exactly on the modelled mean; the cost verdict does not move. diff --git a/thoughts/ec-recover-opt/lincomb2/anchor_lincomb2_differential.log b/thoughts/ec-recover-opt/lincomb2/anchor_lincomb2_differential.log new file mode 100644 index 000000000..82a3909e7 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/anchor_lincomb2_differential.log @@ -0,0 +1,57 @@ +ANCHOR L-A / L-B — lincomb2 differential + small-joint-scalar unrollings (phase D0) +================================================================================== +Re-run: from thoughts/ec-recover-opt/oracle/, + /bin/python lincomb2_anchors.py (venv needs the `ecdsa` package) +Runtime ~3m45s. + +Lineages compared (three, no shared code path): + A lincomb2_ref.lincomb2 — affine, MSB-first double-and-add (ec_ref.py lineage) + B jacobian_ref.lincomb2 — Jacobian (X:Y:Z), inversion-free, LSB-first double-and-add, + infinity representable as Z=0 (NEW, phase D0) + C `ecdsa` PyPI Point arithmetic (independent package) +plus, per case, the NUMS-blinded joint chain `lincomb2_ref.lincomb2_rows` — the exact +row list `ecsm::lincomb2_witness` emits — must land on the same Q, and every row is +re-derived from the group law (slope, result, on-curve, telescoping, digit accounting). + +--- raw output --- + +T0 = (0xaf319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864, 0x1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0) counter=1 +ANCHOR L-A (3-way lincomb2 differential + blinded-chain row check): PASS (611 cases compared 3 ways, 0 degenerate/skipped, 0 failures) + row census: doubles mean 253.8 max 256 adds mean 190.5 max 256 + total rows: mean 446.3 max 514 min 4 +ANCHOR L-B (small joint scalars u1,u2 in [1,16], 6 point pairs): PASS (1536 pairs enumerated, 0 failures) + wrote 1536 vectors (64 with full row values) to lincomb2_small_vectors.json +PHASE D0 ORACLE: ALL GREEN + +--- notes --- + +L-A corpus: 600 random (u1, u2) in [1, N) x random on-curve (P1, P2) (P1 = G on every +third case, both y-parities exercised), plus 11 edge pairs: + (1,1) (1,2) (2,1) (3,5) (N-1,N-1) (N-1,1) (1,N-1) + (2^255, 2^255-1) (2^255-1, 2^255) (2^128, 2^128+1) ((N-1)/2, (N+1)/2) + +L-B ground truth is FULLY ENUMERATED: u*P is computed by u-1 repeated group additions +(`enumerated_mul`), i.e. the definition of scalar multiplication with no +double-and-add, no windowing, no recursion. 6 point pairs x 16 x 16 scalars = 1536 +cases. The `G,3G` pair carries an extra algebraic cross-check: u1*G + u2*(3G) must +equal (u1 + 3*u2)*G, computed independently — 256 of the 1536 cases carry it. + +`lincomb2_small_vectors.json` (in oracle/) is the phase-E L7 anchor: all 1536 cases +with (u1, u2, len, row count, Q, row-role sequence), and full per-row values +(sel/round/op/d1/d2/a/addend/lambda/r) for the pinned `G,3G` u1,u2<=8 subset. + +--- FINDING: worst-case row count is 514, not 471 --- + +The row census above reports max 514, against `layout-lock.md`'s "max 471". Both are +correct; they measure different things. 471/474 is the max over RANDOM scalar pairs +(re-measured here: 20,000 random pairs give mean 449.7, max 474, min 420 — the layout +lock's mean 449.1 stands). 514 is the true maximum over the whole valid input domain, +reached by e.g. (u1, u2) = (2^255, 2^255 - 1), a perfectly ordinary pair of in-range +scalars: + + 1 precompute + 256 doublings + 256 adds + 1 correction = 514 rows + +The joint digit is nonzero at every one of the 256 rounds because the two scalars' +bit patterns are complementary. Any ecrecover input reaching it is cheap for a +submitter to construct. Rows-per-ecrecover figures used for capacity (not for the +mean-cost model) should use 514. diff --git a/thoughts/ec-recover-opt/lincomb2/anchor_repo_lincomb2.log b/thoughts/ec-recover-opt/lincomb2/anchor_repo_lincomb2.log new file mode 100644 index 000000000..f1267f448 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/anchor_repo_lincomb2.log @@ -0,0 +1,67 @@ +ANCHOR D — repo `ecsm::lincomb2_witness` vs the Python oracle (phase D0) +======================================================================= +Re-run: from thoughts/ec-recover-opt/oracle/, + (cd repo-harness && cargo build --release) + /bin/python anchor_d_lincomb2_repo.py +Runtime ~30s. + +Why this exists: phase A validates the Rust witness against two references that +are themselves Rust (`crypto/ecsm/src/tests/lincomb2_tests.rs` — an `Fp` +reference and k256). This anchor is the lineage crossing those tests cannot +make: the Rust witness compared field-by-field and ROW-BY-ROW against the Python +oracle (`lincomb2_ref.lincomb2_rows`, affine/ec_ref lineage), with +`jacobian_ref` (Jacobian, LSB-first) as a third opinion on Q. It needed a new +`lincomb2` command on the repo harness. + +Checked per case: + Q, `len`, `P12`, `T0`, `2^len*T0`; + the range/canonicalisation witnesses `y_p2_sub_p`, `x_q_sub_p`, `y_q_sub_p`, + `u1_sub_n`, `u2_sub_n` (each must equal 2^256 + v - modulus); + every row's (sel, round, op, d1, d2, nb, a, addend, lambda, r) — including + the two places the accumulator does NOT telescope (the precompute row's `a` + is P1; the correction row's addend is -2^len*T0) — and that `nb` is mirrored + into the reused `EcdasStep::next_op` column; + all 6 `Lincomb2Error` variants on the input classes that should produce them. + +--- raw output --- + +ANCHOR D (repo lincomb2_witness vs python oracle): PASS (161 witnesses, 69431 rows compared field-by-field, 8 error paths, 0 failures) + +--- run history (this anchor caught a live convention change) --- + +Run 1 was against `crypto/ecsm` AS OF COMMIT bc62f00e (phase A), extracted with +`git archive` into a scratchpad crate, because the working tree was being edited +concurrently. PASS, same counts. Phase A as committed is correct against an +independent Python lineage, row for row. + +Run 2 was against the WORKING TREE and initially FAILED, at row 1 of every +case — the first `Double` row, and only there. Diagnosis: all point values, +lambdas, results and Q were identical; the sole difference was bookkeeping. +A concurrent phase had changed the witness so that + + - `d1`/`d2` (the two scalars' bits for the round) are now carried on BOTH the + double and the add of a round, not only on the add, and + - a new `nb = d1 | d2` field marks "an add follows me at this same round", + mirrored into `EcdasStep::next_op`. + +That is a deliberate and well-motivated change, not a defect: without `nb` the +successor round `round - 1 + nb` is not a function of the row's own columns, so +a prover could stall `round` — inserting or dropping doublings while every +per-row relation still holds. The oracle was updated to the new convention +(`lincomb2_ref.lincomb2_rows` now emits `nb` and sets the digits on double +rows), and run 3 against the working tree PASSES with the counts above, +including `nb` and its `next_op` mirror. + +Reading: no discrepancy in the arithmetic at any point; one witness-format +change since the phase-A layout lock, now tracked by the oracle. Note that the +bc62f00e-pinned harness no longer builds against the current `main.rs` (it has +no `nb` field) — that is expected; the harness tracks the crate. + +--- convention confirmed by reading the emitted witness (for phase C) --- + +The correction row's ADDEND columns carry the NEGATION -2^len*T0 (witness.rs +builds `neg_tpow` and adds it), while the witness's `x_t0_pow`/`y_t0_pow` fields +carry the POSITIVE 2^len*T0. The preprocessed T0 table feeds the addend columns, +so it must store -2^i*T0 — IMPL-PLAN open decision #3 resolves to "store the +negation", and the positive value is only a bookkeeping field. Verified here by +checking `x_t0_pow`/`y_t0_pow` against `pt_neg(rows[-1]["addend"])`. diff --git a/thoughts/ec-recover-opt/lincomb2/anchor_wycheproof_ecdsa.log b/thoughts/ec-recover-opt/lincomb2/anchor_wycheproof_ecdsa.log new file mode 100644 index 000000000..4d8d560dc --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/anchor_wycheproof_ecdsa.log @@ -0,0 +1,55 @@ +ANCHOR A-ECDSA — Wycheproof ECDSA-verify secp256k1 vs the lincomb2 path (phase D0) +================================================================================= +Re-run: from thoughts/ec-recover-opt/oracle/, + /bin/python anchor_a_wycheproof.py ecdsa +Runtime ~1m25s. (The bare `anchor_a_wycheproof.py` ECDH anchor is unchanged and +still reproduces `anchor_a.log` byte-for-byte.) + +Why these vectors: ECDSA verification IS the lincomb2 shape — + w = s^-1 mod N, u1 = z*w mod N, u2 = r*w mod N, + Q = u1*G + u2*PK, accept iff Q != infinity and x(Q) mod N == r. +Wycheproof's corpus is adversarially constructed, so it reaches (r, s) values a +random corpus never produces: r = 1, s = 1, r = N-1, s = N-1, u1 = 0, PK = ±G, +and cases whose lincomb output is the point at infinity. + +Sources (C2SP/wycheproof `main`, `testvectors_v1`, vendored next to this oracle): + ecdsa_secp256k1_sha256_p1363_test.json 252 tests / 108 keys (raw r||s) + ecdsa_secp256k1_sha256_test.json 476 tests / 109 keys (ASN.1 DER) + +Each parseable vector is evaluated three ways, and all three must agree with +Wycheproof's own verdict: + 1. `lincomb2_ref.lincomb2` (affine, MSB-first) + 2. `lincomb2_ref.lincomb2_rows` the NUMS-blinded joint chain the chip proves + 3. `jacobian_ref.ecdsa_verify` (Jacobian, LSB-first — independent path) +Signatures whose encoding cannot be decoded unambiguously (short/long P1363, +non-canonical DER) are skipped and counted: encoding malleability is not what a +point-math oracle tests. + +--- raw output --- + +{ + "pass": 489, + "fail": 0, + "skip_encoding": 239, + "skip_bad_pubkey": 0, + "via_lincomb2": 360, + "via_fallback": 129, + "valid_accepted": 335, + "invalid_rejected": 154, + "jacobian_disagree": 0 +} +evaluation path per test: {"infinity": 10, "lincomb2": 360, "p1-eq-p2-fallback": 4, "range": 115} +ANCHOR A-ECDSA: PASS (489 verdicts matched Wycheproof: 335 valid accepted, 154 invalid rejected; 360 evaluated through the blinded lincomb2 chain, 239 encoding-level cases skipped) + +--- reading the evaluation-path histogram --- + +lincomb2 (360) — u1, u2 both in [1, N) and P1 != ±P2: the precompile's domain. + These went through the blinded joint chain and matched. +range (115) — r or s outside [1, N): rejected before any point arithmetic. +infinity (10) — Q = u1*G + u2*PK is the point at infinity. This is the + `Lincomb2Error::ResultInfinity` / status != 0 path, and Wycheproof + agrees the signature is invalid. Real coverage of the degenerate + output the status contract exists for. +p1-eq-p2-fallback (4) — PK = ±G, so the P12 = P1 + P2 precompute is degenerate: + `Lincomb2Error::SumDegenerate` / status != 0, software fallback. + Also real coverage of a status-contract path. diff --git a/thoughts/ec-recover-opt/lincomb2/layout-lock.md b/thoughts/ec-recover-opt/lincomb2/layout-lock.md new file mode 100644 index 000000000..7a676340e --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/layout-lock.md @@ -0,0 +1,162 @@ +# lincomb2 layout lock (phase A output) + +The data contract the chip / executor / guest phases build against, derived from +the **implemented and host-validated** `ecsm::lincomb2_witness` +(`crypto/ecsm/src/witness.rs`) — not from estimates. Validated by +`crypto/ecsm/src/tests/lincomb2_tests.rs`: Q matches an independent `Fp`-reference +lincomb AND k256 over 512 random + edge cases; every emitted row re-satisfies its +double/add relation and slope; the NUMS blind provably cancels; T₀ reproducible. + +## Locked row count (replaces DESIGN's ±5% estimate) + +Per ecrecover, ONE joint chain (today: four single-scalar chains): + +| | rows | +|---|---| +| P12 precompute | 1 | +| doublings | = `len` = `max(msb u1, msb u2)+1`; mean **255.7**, max 256 | +| adds (nonzero joint digits) | mean **192.0** | +| correction | 1 | +| **total** | **mean 449.1 (Rust) / 449.7 (Python), max 471** | + +DESIGN estimated 448 → confirmed (+0.2%). Cost model verdict (−74.3% EC cells +with pairing) stands on the measured count. + +## Chain row schedule (what the chip telescopes) + +Dense-doubling blinded Shamir/Straus, MSB-first. `acc` seeded = T₀: + +``` +row 0 : PRECOMPUTE a=P1, addend=P2, op=1 → r=P12 (OFF the acc line) +for round=len-1..0: + DOUBLE a=acc, addend=(0,0), op=0 → r=2·acc ; acc=r + if u1.bit|u2.bit: ADD a=acc, addend∈{P1,P2,P12}, op=1 → r=acc+addend ; acc=r +row last : CORRECTION a=acc, addend=−2^len·T₀, op=1 → r=Q (strips blind) +``` + +`sel ∈ {Double, AddP1, AddP2, AddP12, Precompute, Correction}` (witness enum +`JointSel`). Addend sources the chip must supply: **P1, P2, P12** (add rows), +and the **table constant −2^len·T₀** (correction). Precompute's addend is P2. + +## ECSM′ column blocks (one row per ecrecover) + +Names/widths from `Lincomb2Witness`. Widths: B=byte-checked, HW=U256HL 16 +halfwords (IsHalfword), bit=boolean, fe=field carry. + +| Block | Cols | Range authority | +|---|---|---| +| ts, addrs | ~8 | MEMW | +| xP1,yP1 | 64 B | P1=G constant for ecrecover (chip may hardcode); else membership | +| xP2,yP2 | 64 B | membership (below) + **yP2 **CORRECTED 2026-07-24 — this item previously claimed "no `nb_or` column". + > That was wrong; DESIGN's helper column is required.** Dense doubling is + > true, but the conclusion does not follow. Because the double and its + > optional add share a round, the successor round is + > `round − 1 + nb` — and on a double row `nb` ("an add follows me") is **not + > a function of that row's other columns**. Without it `round` can stall, so + > a prover could insert or drop doublings while every per-row relation still + > held. It is the exact analogue of `NEXT_OP` in today's single-scalar chain + > (`prover/src/tables/ecdas.rs:243-253` sends `round - 1 + next_op`). + > + > The witness could not supply it either: all four `joint_row` call sites + > passed `next_op = 0`, and double rows were given `d1 = d2 = 0`. + > **Fixed in `witness.rs`:** double rows now carry their round's real + > digits, `JointStep` gained `nb` (mirrored into `EcdasStep::next_op`), and + > `check_nb_schedule` in `tests/lincomb2_tests.rs` asserts the recurrence + > over the whole corpus. Purely additive — `next_op` is copied straight + > through by `build_step` and read by nothing, so no emitted math changed + > (row stats still mean 449.1 / max 471, `cargo test -p ecsm` 26/26). + > + > The chip's two defining constraints, for phase D: + > `OP · NB = 0` (deg 2) and `(1 − OP)·(NB − D1 − D2 + D1·D2) = 0` (deg 3) — + > note the op-gating: an add row carries its round's digits (it needs them to + > select the addend) but `nb = 0`. + > + > → the joint row needs **one more** bookkeeping column than this document + > previously claimed, not two fewer. See `CHIP-LAYOUT.md` §0.1 and §2. +3. **P12 precompute is OFF the accumulator line.** DESIGN mused "seeded from T₀"; + it is not — it is a standalone chord add `P1+P2` (a=P1, g=P2). The chip's + accumulator telescoping must special-case that the precompute row's `a` is P1 + (not the previous row's result) and the correction row's `a` is the last + accumulator. This is the one place the clean `a = prev.r` telescoping breaks; + flag for the L6 redo. +4. **Q=∞ and acc==addend collisions** both surface as `Lincomb2Error::ResultInfinity` + in the witness → status≠0 → fallback. The blinding makes an interior + `acc==addend` a discrete-log event (the assumption), so it never fires for + honest inputs; the witness still guards it defensively. + +## What the tests prove (phase-A gate, all green) + +`cargo test -p ecsm --lib` → 21/21. New: T₀ on-curve+pinned+reproducible; +lincomb2 Q == two independent references over 512 cases; per-row relation/slope +re-check; blind-cancellation; degenerate-sum and bad-scalar rejection. diff --git a/thoughts/ec-recover-opt/lincomb2/nums_blinding_probe.log b/thoughts/ec-recover-opt/lincomb2/nums_blinding_probe.log new file mode 100644 index 000000000..62d418ae6 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/nums_blinding_probe.log @@ -0,0 +1,68 @@ +T0 = (0xaf319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864, 0x1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0) + +len= 8 r= 3 u1=1 u2=0x88 + mu = 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbacd2ae642c4cedbe78cab5667435afca5 + P2 = mu*T0 = (0x85882c59785c434236e2ec879fd034aca0ede94b97d85b0f39bc3dcbdb39753d, + 0x58cb252db487d4c48db6dbb4fac8fe290f5bdc94378bbf0bd210ae382bc019ca) + degenerate add at round 3 (target 3): acc == +addend -> LAMBDA UNCONSTRAINED (forgeable row) + acc == addend as points: True + honest reference: rejects with ResultInfinity -> status != 0 -> guest fallback + ecrecover packaging: z=0x7a77d3a687a3bcbdc91d1378602fcb5219c0f39b1770452c861620c0f4fccc04 + r=0x85882c59785c434236e2ec879fd034aca0ede94b97d85b0f39bc3dcbdb39753d + s=0xf0578f87f103bb2d288da80ce69bfc0e72938914bd148fc0387af9cb87b070a2 v=0 + guest recomputes u1: True u2: True lifts R == P2: True + +len= 12 r= 5 u1=1 u2=0x820 + mu = 0x45145145145145145145145145145144bc8895014bbe439e585535f53c3f66ef + P2 = mu*T0 = (0x92f016d1f603b48ad20096c10f098c506eb5e909946111e320eb5544b54bebae, + 0xb73170ec1ae4d03efbc38511e03a4ccae0f23866dedd37d63b5d345993adaef7) + degenerate add at round 5 (target 5): acc == +addend -> LAMBDA UNCONSTRAINED (forgeable row) + acc == addend as points: True + honest reference: rejects with ResultInfinity -> status != 0 -> guest fallback + ecrecover packaging: z=0x6d0fe92e09fc4b752dff693ef0f673ae4bf8f3dd1ae78e589ee709481aea5593 + r=0x92f016d1f603b48ad20096c10f098c506eb5e909946111e320eb5544b54bebae + s=0xdeb969eede1ae7ea44c8e09a2d94136f8d21fecebb3e9efa8cba300abc04cdd7 v=1 + guest recomputes u1: True u2: True lifts R == P2: True + +len= 16 r= 9 u1=1 u2=0x8200 + mu = 0x45145145145145145145145145145144bc8895014bbe439e585535f53c3f66ef + P2 = mu*T0 = (0x92f016d1f603b48ad20096c10f098c506eb5e909946111e320eb5544b54bebae, + 0xb73170ec1ae4d03efbc38511e03a4ccae0f23866dedd37d63b5d345993adaef7) + degenerate add at round 9 (target 9): acc == +addend -> LAMBDA UNCONSTRAINED (forgeable row) + acc == addend as points: True + honest reference: rejects with ResultInfinity -> status != 0 -> guest fallback + ecrecover packaging: z=0x6d0fe92e09fc4b752dff693ef0f673ae4bf8f3dd1ae78e589ee709481aea5593 + r=0x92f016d1f603b48ad20096c10f098c506eb5e909946111e320eb5544b54bebae + s=0xeb969eede1ae7ea44c8e09a2d9413709573eb534cd39cca00df433852d8b8d23 v=1 + guest recomputes u1: True u2: True lifts R == P2: True + +len= 32 r= 17 u1=1 u2=0x80020000 + mu = 0xdf2b7cadf2b7cadf2b7cadf2b7cadf2a611502137f09a313a1bcc02e70198bb6 + P2 = mu*T0 = (0x197a596710aec891083846b31c46101ac6298fde74c68f7a31704c30b3267b5e, + 0x8c7e065d7317dea8501ae0f3e5e54f0d61a9bdb2e7e584c43b0e972e3a867f8) + degenerate add at round 17 (target 17): acc == +addend -> LAMBDA UNCONSTRAINED (forgeable row) + acc == addend as points: True + honest reference: rejects with ResultInfinity -> status != 0 -> guest fallback + ecrecover packaging: z=0xe685a698ef51376ef7c7b94ce3b9efe3f4854d083a8210c18e62125c1d0fc5e3 + r=0x197a596710aec891083846b31c46101ac6298fde74c68f7a31704c30b3267b5e + s=0x3b2585a6153e33ca1b894099937ac85d0cdeceba2372bad597181331f7ed0e58 v=0 + guest recomputes u1: True u2: True lifts R == P2: True + +len= 256 r= 128 u1=1 u2=0x8000000000000000000000000000000100000000000000000000000000000000 + mu = 0xb19602ff6b3b54f91017fdc4bb65087881804b608e761d16b1f5a6d33d7130c4 + P2 = mu*T0 = (0xa454425a35f0a0231fe675dcbde33df9359d9f694d4b0e1fcf692c483bdb4789, + 0x11e3f6683a01b5c6e9fe394ca7537970d17f307728296fcbf3277892bb9c66d7) + degenerate add at round 128 (target 128): acc == +addend -> LAMBDA UNCONSTRAINED (forgeable row) + acc == addend as points: True + honest reference: rejects with ResultInfinity -> status != 0 -> guest fallback + ecrecover packaging: z=0x5babbda5ca0f5fdce0198a23421cc20585113d7d61fd921bf0693244945af9b8 + r=0xa454425a35f0a0231fe675dcbde33df9359d9f694d4b0e1fcf692c483bdb4789 + s=0x147967e8558bf5a55ba0d218aa104168ab60877d222f951e5b53cca9977005c6 v=1 + guest recomputes u1: True u2: True lifts R == P2: True + +forgeable (lambda-free) degenerate adds constructed: 5/5 + +READING: the NUMS blind does NOT close the incomplete-addition edge when +P2 is prover-chosen. The named dlog assumption on T0 is NECESSARY but not +SUFFICIENT; an explicit non-degeneracy check on add rows (or an equivalent) +is required. See ../lincomb2/FINDING-nums-blinding.log. diff --git a/thoughts/ec-recover-opt/lincomb2/oracle_lincomb2.log b/thoughts/ec-recover-opt/lincomb2/oracle_lincomb2.log new file mode 100644 index 000000000..1ffef9761 --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/oracle_lincomb2.log @@ -0,0 +1,23 @@ +lincomb2 oracle validation (independent Python reference, lincomb2_ref.py) +========================================================================== +Re-run: from thoughts/ec-recover-opt/oracle/, + /ec-oracle/venv/bin/python (has the `ecdsa` lib, independent lineage) + +T0 (NUMS blinding point) — SHA-256 try-and-increment of "lambdavm/ecsm/lincomb2/T0/v1": + counter = 1 (counter 0 rejected) + T0.x = 0xaf319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864 + T0.y = 0x1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0 + on-curve: yes y even: yes + +lincomb2(u1,P1,u2,P2) vs the `ecdsa` PyPI library (independent lineage): + 600/600 PASS (0 infinity/degenerate skipped) + +NUMS-blinded joint Shamir/Straus trace (mirror of the Rust witness algorithm): + self-consistency: blinded accumulator == Q + 2^len*T0, correction lands on Q, + over 600 random (u1,u2,P1,P2) + 80-case quick set + edges — all PASS. + edges: (1,1)(1,2)(3,5)(2^255, 2^255-1)(N-1, N-1)(N-1, 1) — all consistent. + +ROW COUNT PER ECRECOVER (one joint chain; today's scheme uses four chains): + doubles mean 255.7 adds mean 192.0 + P12-precompute 1 + correction 1 + total rows: mean 449.7 max 468 + (DESIGN.md estimated 448 — confirmed, ±5% collapsed to +0.4%/+4.5% worst.) diff --git a/thoughts/ec-recover-opt/lincomb2/width_audit.log b/thoughts/ec-recover-opt/lincomb2/width_audit.log new file mode 100644 index 000000000..5bffb07fb --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/width_audit.log @@ -0,0 +1,58 @@ +============================================================================== +PART 1 -- SOUNDNESS: does the field equation still imply the integer one? +============================================================================== +p_g (Goldilocks) = 18446744069414584321 ~ 2^63 + +relation offset carry window max |256c - c- - S| vs p_g +lambda 32636 [-32636, 32899] 22,771,245 810,089,394,295x +xr 8161 [-8161, 57374] 16,723,665 1,103,032,383,715x +yr 16320 [-16320, 49215] 18,739,185 984,394,148,913x +dinv 32636 [-32636, 32899] 14,578,095 1,265,374,115,713x + +worst case over all relations: 22,771,245 ~ 2^24, headroom 2^39 + +These intervals are over-approximations (repeated variables such as +lam*lam and xa*xa are treated as independent), and they are maximised +over BYTE LIMBS ONLY -- no operand is assumed canonical. Restricting +any operand to [0, p) can only shrink them. + +Sensitivity: how large would ONE non-byte limb have to be to break it? + 3*xa_j*xa_{i-j} (lambda, op=0) breaks at a limb of ~2^29 + lam_j*lam_{i-j} (xR) breaks at a limb of ~2^29 + => byte-ness of EVERY limb is load-bearing, not hygiene. + +============================================================================== +PART 2 -- random-corner cross-check of the interval method +============================================================================== + 36,000 corner/random samples, 0 interval violations + +============================================================================== +PART 3 -- COMPLETENESS: honest carries on real lincomb2 witnesses +============================================================================== + Rust differential: 38,076 (quotient, carry-array) comparisons against `ecsm::lincomb2_witness`, 0 mismatches + +6,346 real rows over 15 lincomb2 evaluations (every row type incl. Precompute and Correction) + +relation honest c range window fits min offset needed +lambda [-4303, 6728] [-32636, 32899] True 4303 +xr [-112, 8308] [-8161, 57374] True 112 +yr [-465, 5914] [-16320, 49215] True 465 +dinv [-581, 6041] [-32636, 32899] True 581 + +quotient headroom (33 bytes = [0, 2^264)): + lambda q in [253 bits, 259 bits] min q >= 0: True max q < 2^264: True + xr q in [258 bits, 258 bits] min q >= 0: True max q < 2^264: True + yr q in [258 bits, 258 bits] min q >= 0: True max q < 2^264: True + dinv q in [258 bits, 258 bits] min q >= 0: True max q < 2^264: True + +per row type (carry ranges), to show the new row shapes are not outliers: + Precompute lambda=[-95, 4619] xr=[-24, 6773] yr=[-170, 4729] + Double lambda=[-4303, 6728] xr=[-112, 8308] yr=[-368, 5914] + AddP1 lambda=[-304, 5624] xr=[-94, 7722] yr=[-300, 5686] + AddP2 lambda=[-290, 6170] xr=[-109, 8074] yr=[-328, 5509] + AddP12 lambda=[-412, 5439] xr=[-100, 7897] yr=[-465, 5700] + Correction lambda=[-146, 5019] xr=[-13, 7493] yr=[-251, 5156] + +============================================================================== +WIDTH AUDIT: PASS +============================================================================== diff --git a/thoughts/ec-recover-opt/lincomb2/width_audit_z3.log b/thoughts/ec-recover-opt/lincomb2/width_audit_z3.log new file mode 100644 index 000000000..148396e8e --- /dev/null +++ b/thoughts/ec-recover-opt/lincomb2/width_audit_z3.log @@ -0,0 +1,23 @@ +z3 limb indices checked: [0, 1, 2, 3, 7, 15, 31, 47, 63] (timeout 120s each) + +--- W1 (interval soundness) --- + lambda i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + xr i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + yr i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + dinv i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + +--- W2 (no wraparound mod p_g) --- + lambda i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + xr i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + yr i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + dinv i=0:unsat i=1:unsat i=2:unsat i=3:unsat i=7:unsat i=15:unsat i=31:unsat i=47:unsat i=63:unsat + +--- N-WIDTH (negative control: addend limbs NOT byte-constrained) --- + lambda i=31:sat i=63:unsat + xr i=31:sat i=63:unsat + yr i=31:unsat i=63:unsat + dinv i=31:sat i=63:unsat + + 3 of the tampered queries are SAT (wraparound becomes reachable once the addend is not byte-bounded) + +WIDTH AUDIT z3: PASS (0 soundness violations, 0 unknown/timeout, 3 negative controls SAT) diff --git a/thoughts/ec-recover-opt/oracle/.gitignore b/thoughts/ec-recover-opt/oracle/.gitignore new file mode 100644 index 000000000..40e415fdc --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/.gitignore @@ -0,0 +1,2 @@ +repo-harness/target/ +__pycache__/ diff --git a/thoughts/ec-recover-opt/oracle/README.md b/thoughts/ec-recover-opt/oracle/README.md new file mode 100644 index 000000000..a5894a541 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/README.md @@ -0,0 +1,172 @@ +# EC RECOVER / ECSM oracle (secp256k1) + +Independent oracle for the ECSM accelerator (`xr = x(k·P)`, `P = (xG, even-y)`) +plus a differential double-check of the repo's `crypto/ecsm` reference. +Built 2026-07-24; extended the same day for the **lincomb2** precompile +(`Q = u1·P1 + u2·P2`, phase D0). All anchors PASS. + +## Verdicts — ECSM (single-scalar, x-only) + +| Check | Verdict | Coverage | +|---|---|---| +| Curve constants vs SEC2 + repo `P_BYTES/N_BYTES/R_BYTES/B` | PASS | 8/8 (`check_constants.py`) | +| Anchor A — Wycheproof ECDH secp256k1 (authoritative) | PASS | 669 valid vectors matched, 19 invalid-x rejected, 0 fail (`anchor_a.log`) | +| Anchor B — PyPI `ecdsa` differential (independent lineage) | PASS | 500 random (k,P) + 60 k·G + 36 edge, 0 fail (`anchor_b.log`) | +| Anchor C — repo `crypto/ecsm` differential | PASS | 212 muls, 14 error paths (kind+order), 65 y-recoveries, 48 replays / **11,289 steps** verified, 0 fail (`anchor_c.log`) | +| vectors.json cross-check vs repo | PASS | 53/53 | +| Bonus 1 — ecrecover 3-way (ec_ref vs signer key vs `ecdsa` lib recovery) | PASS | 40 sigs (`bonus.log`) | +| Bonus 2 — parity-authority identity | PASS | 200 random cases (`bonus.log`). **Re-aimed 2026-07-24**: phase G deleted `solve_y`, so the old λ-linear check had become a green test of code that no longer exists. It now pins the recid→parity convention and the fact that a `< p` test cannot separate a point from its negation — the numeric basis of the gate's N7 redundancy result. | + +## Verdicts — lincomb2 (phase D0) + +Logs live in `../lincomb2/` alongside the design docs. + +| Check | Verdict | Coverage | +|---|---|---| +| Anchor L-A — 3-way lincomb2 differential + blinded-chain row re-derivation | PASS | 611 cases × 3 lineages, 0 fail (`../lincomb2/anchor_lincomb2_differential.log`) | +| Anchor L-B — small joint scalars `u1,u2 ∈ [1,16]`, fully-enumerated ground truth | PASS | 1,536 cases over 6 point pairs, 0 fail (same log; vectors in `lincomb2_small_vectors.json`) | +| Anchor A-ECDSA — Wycheproof ECDSA-verify secp256k1 (the `u1·G + u2·PK` shape) | PASS | 489 verdicts matched (335 valid / 154 invalid), 360 through the blinded chain, 0 fail (`../lincomb2/anchor_wycheproof_ecdsa.log`) | +| Anchor D — repo `ecsm::lincomb2_witness` vs the Python oracle | PASS | 161 witnesses, **69,431 rows** field-by-field, 8 error paths, 0 fail (`../lincomb2/anchor_repo_lincomb2.log`) | +| Bonus 3 — the 40-signature ecrecover differential re-run through lincomb2 | PASS | 40 sigs, all recovered through the blinded joint chain (`../lincomb2/anchor_ecrecover_lincomb2.log`) | + +Lineage count for lincomb2 is 4: the affine `ec_ref` path, the Jacobian/LSB-first +`jacobian_ref` path, the `ecdsa` PyPI package, and Wycheproof's own verdicts — +plus the repo's Rust witness as the object under test. + +### One negative result + +`nums_blinding_probe.py` is not an anchor but a counterexample generator, and it +FINDS what it looks for: the NUMS blind of DESIGN.md §4 does **not** close the +incomplete-addition edge when `P2` is prover-chosen, because the prover can set +`P2 = μ·T₀` for a `μ` it knows and cancel `T₀`'s coefficient out of the collision +equation. 5/5 constructions land a degenerate add with `λ` unconstrained, each +packaged as a full `ecrecover` input the guest's own decomposition reproduces. +Write-up: `../lincomb2/FINDING-nums-blinding.log`; raw run: +`../lincomb2/nums_blinding_probe.log`. Phase A is unaffected — the Rust witness +and the Python reference both refuse these inputs. + +coincurve (libsecp256k1, would be a 4th lineage) has no wheel for python3.14 +and fails to build from source — skipped; lineage count is still 3 +(Wycheproof vectors, pure-python `ecdsa`, repo `k256`), plus SEC2 constants. + +## Files + +- `ec_ref.py` — independent reference (from SEC2/textbook formulas only): + affine group law, MSB-first double-and-add, even-y recovery via + `a^((p+1)/4)`, ABI mirror `x_only_mul`, documented-schedule generator + `expected_schedule`, per-step replay `replay_schedule`, `ecrecover`. +- `check_constants.py` — SEC2 recomputation + repo constant diff. +- `anchor_a_wycheproof.py` — Wycheproof driver. No argument = the ECDH anchor + (`wycheproof_ecdh_secp256k1.json`, 752 tests); `ecdsa` = the ECDSA-verify + anchor for lincomb2 (`ecdsa_secp256k1_sha256_p1363_test.json` 252 tests + + `ecdsa_secp256k1_sha256_test.json` 476 tests). All three vector files are + C2SP/wycheproof `main`, `testvectors_v1`, vendored here. +- `anchor_b_pypi.py` — venv differential (`./venv/bin/python`). +- `anchor_c_repo.py` + `repo-harness/` — cargo crate (path-dep on + `crypto/ecsm`) speaking a line protocol; build with + `cargo build --release` inside `repo-harness/`. +- `gen_vectors.py` → `vectors.json` — 53 canonical vectors (42 valid, 11 + error-path) with provenance + rationale tags, for the z3 gate. +- `bonus_ecrecover.py` — end-to-end ecrecover + the parity-authority identity + (part 3) the + same 40 signatures re-run through the lincomb2 path. + +lincomb2 (phase D0): + +- `lincomb2_ref.py` — the lincomb2 reference on top of `ec_ref.py`: T₀ + derivation, `lincomb2`, the blinded-trace self-check, and `lincomb2_rows` + (the full joint-chain row list, mirroring `ecsm::lincomb2_witness`). +- `jacobian_ref.py` — a SECOND independent implementation, deliberately a + different code path: Jacobian coordinates, inversion-free formulas, LSB-first + scalar multiplication, infinity representable. Also carries a textbook + ECDSA verify. +- `lincomb2_anchors.py` → `lincomb2_small_vectors.json` — anchors L-A (≥500 + random differentials) and L-B (small-joint-scalar unrollings, the phase-E L7 + anchor). +- `anchor_d_lincomb2_repo.py` — repo `ecsm::lincomb2_witness` differential + through the harness's `lincomb2` command. +- `nums_blinding_probe.py` — the counterexample generator for the DESIGN §4 + blinding argument (see above). + +`lincomb2_ref.lincomb2_rows` tracks the CURRENT witness row format, which +includes `nb = d1 | d2` on double rows and the digit bits on both the double +and the add of a round. If `crypto/ecsm` changes that format again, anchor D is +what will notice. + +Re-run everything: + +```sh +python3 check_constants.py +python3 anchor_a_wycheproof.py # ECDH -> anchor_a.log +./venv/bin/python anchor_b_pypi.py +(cd repo-harness && cargo build --release) +python3 anchor_c_repo.py +python3 gen_vectors.py +./venv/bin/python bonus_ecrecover.py # incl. part 3 (lincomb2) +# lincomb2 (phase D0) — all need the venv (`ecdsa` package): +./venv/bin/python lincomb2_anchors.py +./venv/bin/python anchor_a_wycheproof.py ecdsa +./venv/bin/python anchor_d_lincomb2_repo.py +``` + +The venv is just `python3 -m venv venv && ./venv/bin/pip install ecdsa` +(add `z3-solver sympy` for the gate scripts in `../gate/`). + +## ECSM syscall ABI + error semantics (for the z3 gate) + +Verified by reading the code (✓ VERIFIED, citations): + +- **Syscall number**: `ECSM_SYSCALL_NUMBER = u64::MAX - 10` + (`executor/src/vm/instruction/execution.rs:32`). +- **Registers**: `x10/a0` = addr to WRITE xR, `x11/a1` = addr of xG, + `x12/a2` = addr of k (`execution.rs:429-431`, `syscalls/src/syscalls.rs:172-182`). +- **Values**: all three are 32-byte **little-endian**; loaded/stored as four + unaligned doublewords at `addr + 8i` (`execution.rs:86-94`). +- **Address guard**: each of the three addrs must satisfy + `(addr mod 2^32) + 31 < 2^32` (`LOW_LIMB = 1<<32`, `execution.rs:36,97-99`) + else `ExecutionError::EcsmAddressOverflow` (`execution.rs:432-437`). +- **Overlap guard**: `|addr_xG − addr_k| ≥ 32` required, else + `ExecutionError::EcsmOperandOverlap`. This is a *trace-provability* guard + (MEMW access-chain), not a correctness one; xR may alias either input + (`execution.rs:438-447`). +- **Input contract & check order** (`crypto/ecsm/src/lib.rs:103-120`, + `prepare`): `k == 0` → `ScalarIsZero`; `k >= N` → `ScalarOutOfRange`; + `xG >= p` → `CoordinateOutOfRange`; `x³+7` non-residue → `NotOnCurve`. + Anchor C verified the *order* too (combined-invalid inputs). +- **On error the VM TRAPS**: `ecsm::scalar_mul_x(&k, &xg)?` at + `execution.rs:450` propagates `EcsmError` into + `ExecutionError::Ecsm(#[from])` (`execution.rs:638`) — execution fails + before any write to xR. No garbage result exists; invalid inputs are + *unexecutable*, hence never reach the trace. +- **Canonical y**: the accelerator lifts xG to the **even** y + (`crypto/ecsm/src/curve.rs:26-34`, SEC1 `0x02` prefix). Sound because + `x(k·P) = x(k·(−P))`; parity/sign is the guest's responsibility + (`crypto/ethrex-crypto/src/lib.rs` lifts R from r + recid parity itself). +- **k=1 echo**: result is xG itself; `replay_double_and_add` returns an + empty step list (`curve.rs:165-168`). The prover-side `xR < p` range check + is what makes a non-canonical xG unprovable (`lib.rs:70-73` comment). + +## Notes that matter for the z3 gate + +1. **Error inputs never produce rows** — the executor traps, so the chip only + ever sees `1 ≤ k < N`, `xG < p`, residue x. The gate should assume that + domain but must confirm the *chip* enforces its own range checks + (`XG_SUB_P`, `K_SUB_N`, `XR_SUB_P` columns in `prover/src/tables/ecsm.rs`) + rather than inheriting soundness from the executor. +2. **Schedule semantics** (verified identical between repo and independent + statement on 48 replays): rows are MSB-first; for each bit below the MSB: + a double row, plus an add row iff the bit is set; `round` = bit index + (add rows share their double's round); `next_op` = op of the following + row, 0 on the last row. k=1 → zero rows. +3. **λ convention**: add rows use λ = (yG−yA)/(xG−xA) (chord from the + *accumulator* to the *base*), double rows λ = 3xA²/(2yA). Repo per-step + λ, a, r matched the independent replay on all 11,289 steps. +4. **Endianness trap**: ABI is little-endian bytes; Wycheproof/SEC1/ecdsa are + big-endian. `vectors.json` carries both (`x`/`k` BE ints, `x_le`/`k_le` + ABI bytes). +5. **x-only scope**: 9 Wycheproof "invalid" cases have off-curve (x,y) whose + x still lifts to a valid point; the x-only precompile correctly accepts + such x. y-validity is out of the accelerator's contract. +6. `ecrecover` composition (guest, `crypto/ethrex-crypto/src/lib.rs`): + 4 x-only queries (k1·P1, (k1+1)·P1, k2·P2, (k2+1)·P2), y recovered via the + λ-linear identity (validated here, 200/200), wrong-sign excluded by the + scalar-edge guards; falls back to software `lincomb` when any guard trips. diff --git a/thoughts/ec-recover-opt/oracle/anchor_a.log b/thoughts/ec-recover-opt/oracle/anchor_a.log new file mode 100644 index 000000000..fa20bdaac --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/anchor_a.log @@ -0,0 +1,11 @@ +{ + "pass": 669, + "fail": 0, + "skip_encoding": 8, + "reject_ok": 19, + "reject_mismatch": 0, + "skip_no_point": 47, + "skip_edge_scalar": 0, + "skip_offcurve_y_valid_x": 9 +} +ANCHOR A: PASS (669 valid vectors matched, 19 off-curve correctly rejected) diff --git a/thoughts/ec-recover-opt/oracle/anchor_a_wycheproof.py b/thoughts/ec-recover-opt/oracle/anchor_a_wycheproof.py new file mode 100644 index 000000000..4f64ec810 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/anchor_a_wycheproof.py @@ -0,0 +1,304 @@ +"""Anchor A: Wycheproof secp256k1 vectors vs the oracle. + +Two sub-anchors, selected by argv: + + (no arg) ECDH — `x(k·P)`, the ECSM (single-scalar, x-only) precompile. + `ecdsa` ECDSA verify — `u1·G + u2·PK`, the LINCOMB2 precompile's shape + (phase D0). Runs every parseable vector through + `lincomb2_ref.lincomb2`, through the NUMS-blinded joint chain + `lincomb2_ref.lincomb2_rows`, and through the independent Jacobian + path `jacobian_ref.ecdsa_verify`, and requires all three to agree + with Wycheproof's verdict. + +--- Anchor A (ECDH) --- + +ECDH shared secret = x(k·P) — exactly the ECSM precompile's function, with +k = private scalar and P the peer public point. Wycheproof's `public` is an +ASN.1 SubjectPublicKeyInfo; we extract the uncompressed/compressed EC point +from its tail rather than pulling in an ASN.1 library: +uncompressed points end with 0x04 || X(32) || Y(32) (65 bytes), compressed +with 0x02/0x03 || X(32) (33 bytes). + +Valid vectors must match the oracle output; vectors whose curve point is +invalid must be rejected by the oracle (EcError). Wycheproof flags cases: +result in {valid, acceptable, invalid}. Cases exercising ASN.1-encoding +malleability (not point math) are skipped when the point itself parses fine +and the flag list is encoding-only — those are out of scope for a point-math +oracle; we log how many were skipped and why. +""" + +import hashlib +import json +import sys + +from ec_ref import GX, GY, P, N, EcError, recover_even_y, scalar_mul, x_only_mul_ints + +DATA = "wycheproof_ecdh_secp256k1.json" +DATA_ECDSA_P1363 = "ecdsa_secp256k1_sha256_p1363_test.json" +DATA_ECDSA_DER = "ecdsa_secp256k1_sha256_test.json" + +# Flags that concern DER/ASN encoding or key-format quirks, not point math. +ENCODING_FLAGS = { + "InvalidAsn", "InvalidEncoding", "UnnamedCurve", "WrongCurve", + "InvalidCurveAttack", # handled separately: point not on secp256k1 +} + + +def extract_point(pub_hex): + """Pull the EC point out of the SPKI tail. Returns (x, y) or ('bad', reason).""" + b = bytes.fromhex(pub_hex) + # search from the end for the BIT STRING payload start: 0x00 then 0x04/0x02/0x03 + if len(b) >= 65 and b[-65] == 0x04: + x = int.from_bytes(b[-64:-32], "big") + y = int.from_bytes(b[-32:], "big") + return ("xy", x, y) + if len(b) >= 33 and b[-33] in (0x02, 0x03): + x = int.from_bytes(b[-32:], "big") + return ("comp", x, b[-33]) + return ("bad", None, None) + + +def main(): + d = json.load(open(DATA)) + group = d["testGroups"][0] + assert group["curve"] == "secp256k1" + + stats = {"pass": 0, "fail": 0, "skip_encoding": 0, "reject_ok": 0, + "reject_mismatch": 0, "skip_no_point": 0, "skip_edge_scalar": 0} + failures = [] + + for t in group["tests"]: + tid, result = t["tcId"], t["result"] + k = int(t["private"], 16) + want = t["shared"] + kind, x, y_or_pref = extract_point(t["public"]) + + if kind == "bad": + stats["skip_no_point"] += 1 + continue + + # Establish the point's x for the oracle; verify on-curve for xy form. + if kind == "xy": + y = y_or_pref + on_curve = (0 <= x < P) and (y * y - x**3 - 7) % P == 0 and not (x == 0 and y == 0) + else: + on_curve = (0 <= x < P) and recover_even_y(x) is not None + + if k == 0 or k >= N: + stats["skip_edge_scalar"] += 1 + continue + + if not on_curve: + # The precompile is x-only: it must reject exactly when x itself is + # invalid (>= p, or no y exists). An off-curve (x, y) whose x still + # lifts to a valid secp256k1 point is outside the oracle's contract + # (the guest's parity lift owns y validation) → skip, counted. + x_valid = (0 <= x < P) and recover_even_y(x) is not None + try: + x_only_mul_ints(x % (2**256), k) + accepted = True + except EcError: + accepted = False + if accepted and not x_valid: + stats["reject_mismatch"] += 1 + failures.append((tid, "oracle accepted invalid x")) + elif not accepted and x_valid: + stats["reject_mismatch"] += 1 + failures.append((tid, "oracle rejected valid x")) + elif accepted: + stats["skip_offcurve_y_valid_x"] = stats.get("skip_offcurve_y_valid_x", 0) + 1 + else: + stats["reject_ok"] += 1 + continue + + if result == "invalid": + # Point math is fine but the case is flagged invalid → encoding-level. + stats["skip_encoding"] += 1 + continue + + # x-only semantics: x(k·P) is independent of y's sign, so the oracle's + # even-y lift must reproduce the shared secret regardless of the + # actual y parity in the vector. + got = x_only_mul_ints(x, k) + if f"{got:064x}" == want: + stats["pass"] += 1 + else: + stats["fail"] += 1 + failures.append((tid, f"got {got:064x} want {want}")) + + print(json.dumps(stats, indent=2)) + for tid, msg in failures[:20]: + print(f"FAIL tcId={tid}: {msg}") + verdict = "PASS" if stats["fail"] == 0 and stats["reject_mismatch"] == 0 and stats["pass"] > 300 else "FAIL" + print(f"ANCHOR A: {verdict} ({stats['pass']} valid vectors matched, " + f"{stats['reject_ok']} off-curve correctly rejected)") + return 0 if verdict == "PASS" else 1 + + +# =========================================================================== +# Anchor A-ECDSA: Wycheproof ECDSA-verify vectors vs the lincomb2 path. +# +# ECDSA verification is exactly the lincomb2 shape: +# w = s^-1 mod N, u1 = z·w mod N, u2 = r·w mod N, +# Q = u1·G + u2·PK, accept iff Q != infinity and x(Q) mod N == r. +# So Wycheproof's ECDSA corpus is an authoritative, adversarially-constructed +# test set for `lincomb2` — including the special r/s values (r=1, s=1, r=N-1, +# ...) that a random corpus never produces. +# +# Signature parsing is deliberately conservative: anything whose encoding this +# script cannot decode UNAMBIGUOUSLY is skipped and counted, because encoding +# malleability is not what a point-math oracle is testing. What is left is a +# clean (r, s) pair, and the verdict must match Wycheproof's `result` exactly. +# =========================================================================== + + +def der_parse_sig(raw): + """Strict DER: SEQUENCE { INTEGER r, INTEGER s }, minimal encodings only. + Returns (r, s) or None if the encoding is not strictly canonical.""" + if len(raw) < 8 or raw[0] != 0x30: + return None + if raw[1] & 0x80: # long-form length: not canonical for these sizes + return None + if raw[1] != len(raw) - 2: + return None + body = raw[2:] + out = [] + while body: + if len(body) < 2 or body[0] != 0x02: + return None + ln = body[1] + if ln & 0x80 or ln == 0 or len(body) < 2 + ln: + return None + val = body[2:2 + ln] + if val[0] & 0x80: # negative + return None + if len(val) > 1 and val[0] == 0x00 and not (val[1] & 0x80): + return None # non-minimal leading zero + out.append(int.from_bytes(val, "big")) + body = body[2 + ln:] + if len(out) != 2: + return None + return out[0], out[1] + + +def verify_via_lincomb2(pk, z, r, s, rows_check=True): + """ECDSA verify, evaluated through the lincomb2 reference (and, when the + scalars are in the precompile's domain, through the NUMS-blinded joint + chain as well). Returns (verdict, note).""" + import lincomb2_ref + + if not (1 <= r < N and 1 <= s < N): + return False, "range" + w = pow(s, N - 2, N) + u1 = (z * w) % N + u2 = (r * w) % N + if u1 == 0 or u2 == 0: + # Outside the precompile's domain (it requires 1 <= u < N); the guest + # falls back to software here. Evaluate with plain scalar muls. + if u1 == 0 and u2 == 0: + return False, "both-zero" + pt = scalar_mul(u2, pk) if u1 == 0 else scalar_mul(u1, (GX, GY)) + return (pt[0] % N) == r, "u-zero-fallback" + + q = lincomb2_ref.lincomb2(u1, (GX, GY), u2, pk) + if q is None: + return False, "infinity" + + if rows_check: + # The blinded joint chain the chip proves must land on the same Q. + T0, _ = _t0() + if pk[0] == GX: + return (q[0] % N) == r, "p1-eq-p2-fallback" + q_chain, _len, _rows = lincomb2_ref.lincomb2_rows(u1, (GX, GY), u2, pk, T0) + if q_chain != q: + raise AssertionError("blinded chain disagrees with the reference lincomb") + return (q[0] % N) == r, "lincomb2" + + +_T0_CACHE = [] + + +def _t0(): + import lincomb2_ref + if not _T0_CACHE: + _T0_CACHE.append(lincomb2_ref.t0_ref()) + return _T0_CACHE[0] + + +def main_ecdsa(): + import jacobian_ref + + stats = {"pass": 0, "fail": 0, "skip_encoding": 0, "skip_bad_pubkey": 0, + "via_lincomb2": 0, "via_fallback": 0, "valid_accepted": 0, + "invalid_rejected": 0, "jacobian_disagree": 0} + notes = {} + failures = [] + + for data, parse in ((DATA_ECDSA_P1363, "p1363"), (DATA_ECDSA_DER, "der")): + d = json.load(open(data)) + for group in d["testGroups"]: + assert group["publicKey"]["curve"] == "secp256k1" + assert group["sha"] == "SHA-256" + px = int(group["publicKey"]["wx"], 16) + py = int(group["publicKey"]["wy"], 16) + pk = (px, py) + if not jacobian_ref.on_curve_affine(pk) or not (0 < px < P): + stats["skip_bad_pubkey"] += len(group["tests"]) + continue + + for t in group["tests"]: + raw = bytes.fromhex(t["sig"]) + if parse == "p1363": + if len(raw) != 64: + stats["skip_encoding"] += 1 + continue + r = int.from_bytes(raw[:32], "big") + s = int.from_bytes(raw[32:], "big") + else: + parsed = der_parse_sig(raw) + if parsed is None: + stats["skip_encoding"] += 1 + continue + r, s = parsed + + z = int.from_bytes( + hashlib.sha256(bytes.fromhex(t["msg"])).digest(), "big") + want = (t["result"] == "valid") + got, note = verify_via_lincomb2(pk, z, r, s) + stats["via_lincomb2" if note == "lincomb2" else "via_fallback"] += 1 + notes[note] = notes.get(note, 0) + 1 + + # third opinion: the Jacobian/LSB-first path + if jacobian_ref.ecdsa_verify(pk, z, r, s) != got: + stats["jacobian_disagree"] += 1 + failures.append((data, t["tcId"], "jacobian path disagrees")) + + if got == want: + stats["pass"] += 1 + stats["valid_accepted" if want else "invalid_rejected"] += 1 + else: + stats["fail"] += 1 + failures.append( + (data, t["tcId"], + f"got {got} want {want} ({t['result']}, {t['comment']}, " + f"flags={t.get('flags')}, via={note})")) + + print(json.dumps(stats, indent=2)) + print("evaluation path per test: " + json.dumps(notes, sort_keys=True)) + for src, tid, msg in failures[:20]: + print(f"FAIL {src} tcId={tid}: {msg}") + ok = (stats["fail"] == 0 and stats["jacobian_disagree"] == 0 + and stats["valid_accepted"] > 250) + print(f"ANCHOR A-ECDSA: {'PASS' if ok else 'FAIL'} " + f"({stats['pass']} verdicts matched Wycheproof: " + f"{stats['valid_accepted']} valid accepted, " + f"{stats['invalid_rejected']} invalid rejected; " + f"{stats['via_lincomb2']} evaluated through the blinded lincomb2 chain, " + f"{stats['skip_encoding']} encoding-level cases skipped)") + return 0 if ok else 1 + + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "ecdsa": + raise SystemExit(main_ecdsa()) + raise SystemExit(main()) diff --git a/thoughts/ec-recover-opt/oracle/anchor_b.log b/thoughts/ec-recover-opt/oracle/anchor_b.log new file mode 100644 index 000000000..017a6400e --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/anchor_b.log @@ -0,0 +1 @@ +ANCHOR B: PASS (500 random pairs + 60 kG + 36 edge cases, 0 failures) diff --git a/thoughts/ec-recover-opt/oracle/anchor_b_pypi.py b/thoughts/ec-recover-opt/oracle/anchor_b_pypi.py new file mode 100644 index 000000000..c4f39f72f --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/anchor_b_pypi.py @@ -0,0 +1,84 @@ +"""Anchor B: random differential of the oracle against the `ecdsa` PyPI +package (pure-Python, independent lineage from both our oracle and k256). + +- 500 random (k, P) pairs: x(k·P) oracle vs ecdsa Point arithmetic +- 60 random k·G checks +- edge scalars: 1, 2, 3, N-1, N-2, 2^i and 2^i - 1 for schedule-shaped edges + +Deterministic seed so the run is reproducible. + +coincurve (libsecp256k1) was attempted as a third lineage but has no wheel +for this Python and fails to build from source; noted in README. +""" + +import random + +from ecdsa import SECP256k1 +from ecdsa.ellipticcurve import Point + +from ec_ref import N, P, recover_even_y, scalar_mul, x_only_mul_ints + +rng = random.Random(20260724) + +CURVE = SECP256k1.curve +G_LIB = SECP256k1.generator + + +def random_point(): + while True: + x = rng.randrange(P) + y = recover_even_y(x) + if y is not None: + return x, y + + +def lib_mul_x(k, x, y): + pt = Point(CURVE, x, y) * k + return pt.x() + + +def main(): + fails = 0 + + # 1. random (k, P) + for i in range(500): + x, y = random_point() + k = rng.randrange(1, N) + got = x_only_mul_ints(x, k) + want = lib_mul_x(k, x, y) + if got != want: + fails += 1 + print(f"FAIL random pair {i}: k={k:x} x={x:x} got={got:x} want={want:x}") + + # 2. k·G + for i in range(60): + k = rng.randrange(1, N) + got = x_only_mul_ints(SECP256k1.generator.x(), k) if False else scalar_mul(k, (G_LIB.x(), G_LIB.y()))[0] + want = (G_LIB * k).x() + if got != want: + fails += 1 + print(f"FAIL kG {i}: k={k:x}") + + # 3. edge scalars on a fixed random point and on G + edges = [1, 2, 3, N - 1, N - 2] + for i in (1, 8, 64, 128, 255): + edges += [2**i, 2**i - 1] + edges += [int("10" * 128, 2), int("01" * 128, 2), 2**256 % N] # alternating bits + x, y = random_point() + for k in edges: + k = k % N or 1 + for (px, py) in ((x, y), (G_LIB.x(), G_LIB.y())): + got = x_only_mul_ints(px, k) + want = lib_mul_x(k, px, py) + if got != want: + fails += 1 + print(f"FAIL edge k={k:x} x={px:x}: got={got:x} want={want:x}") + + n_edge = len(edges) * 2 + print(f"ANCHOR B: {'PASS' if fails == 0 else 'FAIL'} " + f"(500 random pairs + 60 kG + {n_edge} edge cases, {fails} failures)") + return 0 if fails == 0 else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/thoughts/ec-recover-opt/oracle/anchor_c.log b/thoughts/ec-recover-opt/oracle/anchor_c.log new file mode 100644 index 000000000..35ca0f017 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/anchor_c.log @@ -0,0 +1 @@ +ANCHOR C: PASS (212 mul cases, 14 error paths, 65 y-recoveries, 48 replays / 11289 steps verified, 0 failures) diff --git a/thoughts/ec-recover-opt/oracle/anchor_c_repo.py b/thoughts/ec-recover-opt/oracle/anchor_c_repo.py new file mode 100644 index 000000000..8b8133f89 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/anchor_c_repo.py @@ -0,0 +1,146 @@ +"""Anchor C: differential of the repo's `crypto/ecsm` crate against the +oracle, via the repo-harness line protocol. + +Checks: + 1. scalar_mul_x on 200+ random and edge (k, x) pairs + 2. exact error-path agreement (kind AND check order) on invalid inputs + 3. recover_y_canonical: even-y choice, non-residue rejection, x >= p rejection + 4. replay_double_and_add: schedule == documented MSB-first double-and-add + derived independently from bits of k; every step's (a, lambda, r) matches + the oracle's own chord/tangent replay; final == oracle x(k*P); k=1 echo. +""" + +import random +import subprocess + +from ec_ref import (EcError, GX, GY, N, P, expected_schedule, recover_even_y, + replay_schedule, scalar_mul, x_only_mul_ints) + +HARNESS = "repo-harness/target/release/ecsm-oracle-harness" +rng = random.Random(97) + + +def random_valid_x(): + while True: + x = rng.randrange(P) + if recover_even_y(x) is not None: + return x + + +def nonresidue_x(): + while True: + x = rng.randrange(P) + if recover_even_y(x) is None: + return x + + +def run(lines): + r = subprocess.run([HARNESS], input="\n".join(lines) + "\n", + capture_output=True, text=True, check=True) + return r.stdout.splitlines() + + +def main(): + fails = 0 + + def check(cond, msg): + nonlocal fails + if not cond: + fails += 1 + print(f"FAIL {msg}") + + # ── 1. mul differential ────────────────────────────────────────────── + cases = [] + for _ in range(180): + cases.append((random_valid_x(), rng.randrange(1, N))) + edge_ks = [1, 2, 3, N - 1, N - 2] + [2**i for i in (1, 8, 64, 128, 255)] \ + + [2**i - 1 for i in (2, 8, 64, 128, 256) if 2**i - 1 < N] \ + + [int("10" * 128, 2) % N, int("01" * 128, 2)] + for k in edge_ks: + cases.append((GX, k)) + cases.append((random_valid_x(), k)) + out = run([f"mul {x:x} {k:x}" for (x, k) in cases]) + for (x, k), line in zip(cases, out): + want = x_only_mul_ints(x, k) + check(line == f"ok {want:x}", f"mul k={k:x} x={x:x}: repo said {line!r}, oracle {want:x}") + n_mul = len(cases) + + # ── 2. error paths: exact kind + check order ───────────────────────── + nr = nonresidue_x() + vx = random_valid_x() + err_cases = [ + (vx, 0), (vx, N), (vx, N + 1), (vx, 2**256 - 1), + (P, 5), (P + 1, 5), (2**256 - 1, 5), + (nr, 5), (nonresidue_x(), rng.randrange(1, N)), + # combined-invalid: verifies the check ORDER is scalar -> coord -> curve + (P, 0), (P, N), (nr, 0), (nr, N + 7), (P + 3, 2**256 - 1), + ] + out = run([f"mul {x:x} {k:x}" for (x, k) in err_cases]) + for (x, k), line in zip(err_cases, out): + try: + x_only_mul_ints(x, k) + want = "ok" + except EcError as e: + want = f"err {e.kind}" + check(line == want, f"errpath k={k:x} x={x:x}: repo {line!r}, oracle {want!r}") + + # ── 3. recover_y_canonical ─────────────────────────────────────────── + ys = [random_valid_x() for _ in range(40)] + [nonresidue_x() for _ in range(20)] \ + + [P, P + 1, 2**256 - 1, 0, GX] + out = run([f"recovery {x:x}" for x in ys]) + for x, line in zip(ys, out): + y = recover_even_y(x) + want = f"y {y:x}" if y is not None else "none" + check(line == want, f"recovery x={x:x}: repo {line!r}, oracle {want!r}") + if y is not None: + check(y % 2 == 0, f"oracle even-y invariant broke at x={x:x}") + + # ── 4. replay: schedule + per-step transition + final ──────────────── + replay_ks = [1, 2, 3, 5, 7, N - 1, N - 2, 2**255, 2**255 - 1, 2**64, 2**64 - 1, + int("10" * 128, 2) % N, int("01" * 128, 2), + rng.randrange(1, N), rng.randrange(1, N), rng.randrange(1, N)] + replay_pts = [(GX, "G")] + [(random_valid_x(), "rand") for _ in range(2)] + reqs, meta = [], [] + for x, tag in replay_pts: + for k in replay_ks: + reqs.append(f"replay {x:x} {k:x}") + meta.append((x, k, tag)) + out = run(reqs) + pos = 0 + n_steps_checked = 0 + for (x, k, tag) in meta: + head = out[pos]; pos += 1 + assert head.startswith("steps "), head + n, fx, fy = head.split()[1:] + n = int(n) + g = (x, recover_even_y(x)) + osteps, ofinal = replay_schedule(k, g) if k > 1 else ([], g) + sched = expected_schedule(k) if k > 1 else [] + check(n == len(osteps), f"replay k={k:x} {tag}: {n} steps, oracle {len(osteps)}") + check(int(fx, 16) == ofinal[0] and int(fy, 16) == ofinal[1], + f"replay k={k:x} {tag}: final ({fx},{fy}) != oracle {ofinal[0]:x}") + check(ofinal[0] == x_only_mul_ints(x, k), + f"oracle self-check k={k:x}: replay final != direct mul") + for j in range(n): + rnd, op, nxt, ax, ay, lam, rx, ry = out[pos].split()[1:]; pos += 1 + if j < len(osteps): + ornd, oop, onxt, oa, olam, orr = osteps[j] + good = (int(rnd), int(op), int(nxt)) == (ornd, oop, onxt) \ + and (int(ax, 16), int(ay, 16)) == oa \ + and int(lam, 16) == olam \ + and (int(rx, 16), int(ry, 16)) == orr + check(good, f"replay k={k:x} {tag} step {j}: repo " + f"({rnd},{op},{nxt},a={ax[:12]}..,l={lam[:12]}..) != oracle " + f"({ornd},{oop},{onxt},a={oa[0]:x}..)"[:200]) + n_steps_checked += 1 + # independent schedule statement (from bits of k only) + check(sched == [(s[0], s[1], s[2]) for s in osteps], f"oracle schedule self-check k={k:x}") + + print(f"ANCHOR C: {'PASS' if fails == 0 else 'FAIL'} " + f"({n_mul} mul cases, {len(err_cases)} error paths, {len(ys)} y-recoveries, " + f"{len(meta)} replays / {n_steps_checked} steps verified, {fails} failures)") + return 0 if fails == 0 else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/thoughts/ec-recover-opt/oracle/anchor_d_lincomb2_repo.py b/thoughts/ec-recover-opt/oracle/anchor_d_lincomb2_repo.py new file mode 100644 index 000000000..94a7b6638 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/anchor_d_lincomb2_repo.py @@ -0,0 +1,182 @@ +"""Anchor D: differential of the repo's `ecsm::lincomb2_witness` (phase A) +against the Python lincomb2 oracle, via the repo-harness `lincomb2` command. + +This is the lineage crossing phase A's own tests cannot make: those validate +the Rust witness against two references that are themselves in Rust. Here the +Rust witness is compared, field by field and ROW BY ROW, against +`lincomb2_ref.lincomb2_rows` (affine/ec_ref lineage) with `jacobian_ref` +(Jacobian/LSB-first lineage) as the third opinion on Q. + +Checks: + 1. Q, `len`, `P12`, `T0` and `2^len·T0` agree with the Python reference. + 2. Every emitted row agrees on (sel, round, op, d1, d2, nb, a, addend, λ, r) — + including the two places the accumulator does NOT telescope (the + precompute row's `a` is P1, the correction row's addend is −2^len·T0) — + and `nb` is mirrored into the reused `EcdasStep::next_op` column. + 3. The canonicalization witnesses (`y_p2_sub_p`, `x_q_sub_p`, `y_q_sub_p`, + `u1_sub_n`, `u2_sub_n`) really equal `2^256 + v − modulus`. + 4. Error paths: every `Lincomb2Error` variant is produced for the input class + that should produce it. + +Usage: + /bin/python anchor_d_lincomb2_repo.py [path-to-harness-binary] + +Default harness path is the in-tree build; pass an explicit path to run against +a harness built from a pinned commit (which is how this was first run, so the +differential measured phase A as committed rather than as concurrently edited). +""" + +import json +import random +import subprocess +import sys + +import jacobian_ref +import lincomb2_ref +from ec_ref import GX, GY, N, P, recover_even_y + +HARNESS = "repo-harness/target/release/ecsm-oracle-harness" +rng = random.Random(4242) +T0, _T0_COUNTER = lincomb2_ref.t0_ref() + + +def run(harness, lines): + r = subprocess.run([harness], input="\n".join(lines) + "\n", + capture_output=True, text=True, check=True) + return r.stdout.splitlines() + + +def random_point(): + while True: + x = rng.randrange(P) + y = recover_even_y(x) + if y is not None: + break + return (x, (P - y) % P if rng.random() < 0.5 else y) + + +def cmd(u1, u2, p1, p2): + return f"lincomb2 {u1:x} {u2:x} {p1[0]:x} {p1[1]:x} {p2[0]:x} {p2[1]:x}" + + +def sub_witness(v, modulus): + return (1 << 256) + v - modulus + + +def main(harness=HARNESS): + fails = 0 + + def check(cond, msg): + nonlocal fails + if not cond: + fails += 1 + print(f"FAIL {msg}") + + # ── 1-3. positive differential ─────────────────────────────────────────── + G = (GX, GY) + cases = [] + for i in range(150): + p1 = G if i % 2 == 0 else random_point() + p2 = random_point() + if p1[0] == p2[0]: + continue + cases.append((rng.randrange(1, N), rng.randrange(1, N), p1, p2)) + for u1, u2 in [(1, 1), (1, 2), (2, 1), (3, 5), (7, 8), (16, 15), + (N - 1, N - 1), (N - 1, 1), (1, N - 1), + (2**255, 2**255 - 1), (2**128, 2**128 + 1)]: + cases.append((u1, u2, G, random_point())) + + lines = [cmd(*c) for c in cases] + outs = run(harness, lines) + check(len(outs) == len(cases), f"harness returned {len(outs)} lines for {len(cases)} cases") + + rows_compared = 0 + for (u1, u2, p1, p2), out in zip(cases, outs): + tag = f"u1={u1:x} u2={u2:x} xP2={p2[0]:x}" + if not out.startswith("lincomb2_json "): + fails += 1 + print(f"FAIL rust rejected a valid case ({out}) {tag}") + continue + w = json.loads(out[len("lincomb2_json "):]) + + q_py, length, rows = lincomb2_ref.lincomb2_rows(u1, p1, u2, p2, T0) + q_jac = jacobian_ref.lincomb2(u1, p1, u2, p2) + + check(int(w["x_q"], 16) == q_py[0] and int(w["y_q"], 16) == q_py[1], + f"Q mismatch rust vs python {tag}") + check(q_jac == q_py, f"Q mismatch python vs jacobian {tag}") + check(w["len"] == length, f"len mismatch rust={w['len']} py={length} {tag}") + + p12 = rows[0]["r"] + check(int(w["x_p12"], 16) == p12[0] and int(w["y_p12"], 16) == p12[1], + f"P12 mismatch {tag}") + check((int(w["x_t0"], 16), int(w["y_t0"], 16)) == T0, f"T0 mismatch {tag}") + + tpow = lincomb2_ref.pt_neg(rows[-1]["addend"]) + check((int(w["x_t0_pow"], 16), int(w["y_t0_pow"], 16)) == tpow, + f"2^len*T0 mismatch {tag}") + + # canonicalization / range witnesses + check(int(w["y_p2_sub_p"], 16) == sub_witness(p2[1], P), f"y_p2_sub_p {tag}") + check(int(w["x_q_sub_p"], 16) == sub_witness(q_py[0], P), f"x_q_sub_p {tag}") + check(int(w["y_q_sub_p"], 16) == sub_witness(q_py[1], P), f"y_q_sub_p {tag}") + check(int(w["u1_sub_n"], 16) == sub_witness(u1, N), f"u1_sub_n {tag}") + check(int(w["u2_sub_n"], 16) == sub_witness(u2, N), f"u2_sub_n {tag}") + + # row-by-row + rr = w["rows"] + if len(rr) != len(rows): + fails += 1 + print(f"FAIL row count rust={len(rr)} py={len(rows)} {tag}") + continue + for i, (a, b) in enumerate(zip(rr, rows)): + same = ( + a["sel"] == b["sel"] + and a["round"] == b["round"] + and a["op"] == b["op"] + and a["d1"] == b["d1"] + and a["d2"] == b["d2"] + and a["nb"] == b["nb"] + # nb is mirrored into the reused next_op column + and a["next_op"] == b["nb"] + and (int(a["x_a"], 16), int(a["y_a"], 16)) == b["a"] + and (int(a["x_b"], 16), int(a["y_b"], 16)) == b["addend"] + and int(a["lambda"], 16) == b["lam"] + and (int(a["x_r"], 16), int(a["y_r"], 16)) == b["r"] + ) + if not same: + fails += 1 + print(f"FAIL row {i} ({a['sel']}/{b['sel']}) mismatch {tag}") + break + rows_compared += 1 + + # ── 4. error paths ─────────────────────────────────────────────────────── + p2 = random_point() + while p2[0] == GX: + p2 = random_point() + off_curve = (p2[0], (p2[1] + 1) % P) + non_canon = (p2[0], p2[1] + P) # same point mod p, non-canonical bytes + neg_g = (GX, (P - GY) % P) + err_cases = [ + ("ScalarIsZero", cmd(0, 5, G, p2)), + ("ScalarIsZero", cmd(5, 0, G, p2)), + ("ScalarOutOfRange", cmd(N, 5, G, p2)), + ("ScalarOutOfRange", cmd(5, N + 1, G, p2)), + ("PointNotOnCurve", cmd(3, 5, G, off_curve)), + ("PointNotCanonical", cmd(3, 5, G, non_canon)), + ("SumDegenerate", cmd(3, 5, G, G)), + ("SumDegenerate", cmd(3, 5, G, neg_g)), + ] + outs = run(harness, [c for _, c in err_cases]) + for (want, c), out in zip(err_cases, outs): + check(out == f"err {want}", f"error path: got '{out}' want 'err {want}' for `{c[:40]}...`") + + print(f"ANCHOR D (repo lincomb2_witness vs python oracle): " + f"{'PASS' if fails == 0 else 'FAIL'} " + f"({len(cases)} witnesses, {rows_compared} rows compared field-by-field, " + f"{len(err_cases)} error paths, {fails} failures)") + return 1 if fails else 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1] if len(sys.argv) > 1 else HARNESS)) diff --git a/thoughts/ec-recover-opt/oracle/bonus.log b/thoughts/ec-recover-opt/oracle/bonus.log new file mode 100644 index 000000000..979fd64ee --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/bonus.log @@ -0,0 +1,2 @@ +BONUS 1 (ecrecover 3-way, 40 sigs): PASS (0 failures) +BONUS 2 (parity-authority identity, 200 cases): PASS (0 failures) diff --git a/thoughts/ec-recover-opt/oracle/bonus_ecrecover.py b/thoughts/ec-recover-opt/oracle/bonus_ecrecover.py new file mode 100644 index 000000000..b37dc403c --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/bonus_ecrecover.py @@ -0,0 +1,230 @@ +"""Bonus checks. + +1. End-to-end ecrecover differential: sign with the `ecdsa` PyPI package + (RFC6979 deterministic, independent lineage), recover with our + ec_ref.ecrecover, and also cross-check against `ecdsa`'s own + VerifyingKey.from_public_key_recovery_with_digest (an independent + ecrecover implementation). 3-way agreement on 40 signatures. + +2. The PARITY-AUTHORITY identity, on 200 random signature r-values. + + RE-AIMED 2026-07-24. This slot used to validate the lambda-linear + y-recovery identity of `crypto/ethrex-crypto/src/lib.rs::solve_y`. Phase G + deleted `solve_y` along with the whole x-only reconstruction path, so that + check became a GREEN TEST OF CODE THAT NO LONGER EXISTS — worse than no + test, because it implies coverage that is not there. + + What it pins now is a property of the CURRENT path, and one that two live + claims rest on but nothing else executes: + + - the spec chapter's "the guest is the parity authority, backed by MEMW; + the chip's obligations are membership and canonicalisation only", and + - the z3 gate's N7 result, that dropping `yP2 < p` is REDUNDANT rather + than a forgery. + + Both reduce to: a `< p` range check cannot separate a point from its + negation, because both candidate y values are already below p. Part 2 now + asserts that numerically, together with the recid convention itself + (`y_is_odd = recid & 1`, lib.rs:104-106) and the fact that the recid bit + really does change the recovered key. + + Do not restore the solve_y version: the code it tested is gone. + +3. (phase D0) The SAME 40 signatures, recovered through the LINCOMB2 path: + pk = u1*G + u2*R evaluated by `lincomb2_ref.lincomb2`, by the NUMS-blinded + joint chain `lincomb2_ref.lincomb2_rows` (what the chip will prove), and by + the independent Jacobian implementation `jacobian_ref.lincomb2`. All must + equal the signer's key and the `ecdsa` library's recovery. This is the + existing 3-way ecrecover differential re-run end-to-end over lincomb2 -- + part1 hands its corpus to part3, so it is literally the same signatures. +""" + +import hashlib +import random + +from ecdsa import SECP256k1, SigningKey +from ecdsa.ellipticcurve import Point +from ecdsa.util import sigdecode_string + +from ec_ref import (GX, GY, N, P, ecrecover, finv, recover_even_y, + scalar_mul, x_only_mul_ints) + +rng = random.Random(777) + + +def part1(): + fails = 0 + corpus = [] # (digest, v, r, s, want_pk) -- handed to part3 + from ecdsa import VerifyingKey + for i in range(40): + sk = SigningKey.generate(curve=SECP256k1, entropy=lambda n: rng.randbytes(n)) + vk = sk.get_verifying_key() + msg = rng.randbytes(32 + i % 7) + digest = hashlib.sha256(msg).digest() + sig = sk.sign_digest_deterministic(digest) + r, s = sigdecode_string(sig, N) + + # recid: which parity of R.y recovers the true key (r < N < P here; + # the r+N branch has ~2^-128 probability and never occurs randomly) + pub = vk.pubkey.point + want = (pub.x(), pub.y()) + got = None + for v in (0, 1): + cand = ecrecover(digest, v, r, s) + if cand == want: + got = (v, cand) + break + if got is None: + fails += 1 + print(f"FAIL roundtrip {i}: neither parity recovers the signer key") + continue + corpus.append((digest, got[0], r, s, want)) + + # 3-way: python-ecdsa's own recovery must contain the same key + cands = VerifyingKey.from_public_key_recovery_with_digest( + sig, digest, curve=SECP256k1, sigdecode=sigdecode_string) + lib_pts = {(c.pubkey.point.x(), c.pubkey.point.y()) for c in cands} + if want not in lib_pts: + fails += 1 + print(f"FAIL lib-recovery {i}: ecdsa lib does not recover signer") + # and OUR recovered set must be a subset of the lib's candidate set + ours = set() + for v in (0, 1): + c = ecrecover(digest, v, r, s) + if c is not None: + ours.add(c) + if not ours <= lib_pts: + fails += 1 + print(f"FAIL candidate-set {i}: ours={ours} lib={lib_pts}") + print(f"BONUS 1 (ecrecover 3-way, 40 sigs): {'PASS' if fails == 0 else 'FAIL'} ({fails} failures)") + return fails, corpus + + +def part2(): + """The PARITY AUTHORITY identity — see the module docstring for why this + replaced the deleted `solve_y` check. + + Four properties per case, all of the CURRENT path: + (a) lifting `r` under the guest's convention `y_is_odd = recid & 1` + (lib.rs:104-106) gives an on-curve point whose y-parity is exactly + that bit; + (b) flipping the recid bit yields exactly the negation `(x, p - y)`; + (c) the two parities recover DIFFERENT public keys, so the recid bit + genuinely determines the answer — parity is load-bearing; + (d) BOTH candidate y values are `< p`, so a `< p` canonicalisation test + cannot separate a point from its negation. + + (d) is the numeric statement behind the gate's N7 redundancy result and the + spec chapter's correction to DESIGN section 3: `yP2 < p` is defence in + depth, and parity is pinned by the guest plus MEMW, not by a range check. + """ + fails = 0 + checked = 0 + for i in range(200): + # a random valid signature r-value, i.e. a curve x-coordinate < N + while True: + r = rng.randrange(1, N) + y_even = recover_even_y(r) + if y_even is not None: + break + y_odd = (P - y_even) % P + z = rng.randrange(1, N) + s = rng.randrange(1, N) + checked += 1 + + # (a) the guest's convention: recid bit 0 selects the y-parity + for recid in (0, 1): + y = y_odd if (recid & 1) else y_even + if y & 1 != (recid & 1): + fails += 1 + print(f"FAIL parity {i}: lifted parity != recid bit (recid={recid})") + if (y * y - pow(r, 3, P) - 7) % P != 0: + fails += 1 + print(f"FAIL parity {i}: lifted point off-curve (recid={recid})") + + # (b) the two lifts are exact negations + if (y_even + y_odd) % P != 0: + fails += 1 + print(f"FAIL parity {i}: the two lifts are not negations") + + # (c) parity is load-bearing: the two recids recover different keys + pk0 = ecrecover(z.to_bytes(32, "big"), 0, r, s) + pk1 = ecrecover(z.to_bytes(32, "big"), 1, r, s) + if pk0 is None or pk1 is None: + continue # degenerate (u1 or u2 zero); the guest falls back + if pk0 == pk1: + fails += 1 + print(f"FAIL parity {i}: both recids recover the same key") + + # (d) a `< p` test cannot tell them apart + if not (y_even < P and y_odd < P): + fails += 1 + print(f"FAIL parity {i}: a candidate y is not below p") + + print(f"BONUS 2 (parity-authority identity, {checked} cases): " + f"{'PASS' if fails == 0 else 'FAIL'} ({fails} failures)") + return fails + + +def part3(corpus): + """The same 40 signatures, recovered through the lincomb2 path.""" + import jacobian_ref + import lincomb2_ref + + T0, _ = lincomb2_ref.t0_ref() + fails = 0 + via_chain = 0 + rows_seen = [] + for i, (digest, v, r, s, want) in enumerate(corpus): + # Exactly the guest's decomposition (crypto/ethrex-crypto/src/lib.rs): + # R lifted from (r, parity v), u1 = -z/r, u2 = s/r (mod N). + y_even = recover_even_y(r) + if y_even is None: + fails += 1 + print(f"FAIL lincomb2 {i}: r does not lift to a curve point") + continue + R = (r, y_even if v == 0 else (P - y_even) % P) + z = int.from_bytes(digest, "big") % N + rinv = pow(r, N - 2, N) + u1 = (-(rinv * z)) % N + u2 = (rinv * s) % N + if not (1 <= u1 < N and 1 <= u2 < N): + print(f"SKIP lincomb2 {i}: u1 or u2 outside [1, N) (software fallback)") + continue + + G = (GX, GY) + q_ref = lincomb2_ref.lincomb2(u1, G, u2, R) + q_jac = jacobian_ref.lincomb2(u1, G, u2, R) + if q_ref != want or q_jac != want: + fails += 1 + print(f"FAIL lincomb2 {i}: pk mismatch ref={q_ref} jac={q_jac} want={want}") + continue + + # the NUMS-blinded joint chain -- what the chip proves + try: + q_chain, length, rows = lincomb2_ref.lincomb2_rows(u1, G, u2, R, T0) + except ValueError as e: + fails += 1 + print(f"FAIL lincomb2 {i}: blinded chain rejected ({e})") + continue + if q_chain != want: + fails += 1 + print(f"FAIL lincomb2 {i}: blinded chain pk != signer key") + continue + via_chain += 1 + rows_seen.append(len(rows)) + + print(f"BONUS 3 (ecrecover via lincomb2, {len(corpus)} sigs): " + f"{'PASS' if fails == 0 else 'FAIL'} ({fails} failures; " + f"{via_chain} recovered through the NUMS-blinded joint chain)") + if rows_seen: + print(f" chain rows: mean {sum(rows_seen)/len(rows_seen):.1f} " + f"min {min(rows_seen)} max {max(rows_seen)}") + return fails + + +if __name__ == "__main__": + f1, corpus = part1() + f2 = part2() + f3 = part3(corpus) + raise SystemExit(1 if (f1 + f2 + f3) else 0) diff --git a/thoughts/ec-recover-opt/oracle/check_constants.log b/thoughts/ec-recover-opt/oracle/check_constants.log new file mode 100644 index 000000000..48408f2cc --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/check_constants.log @@ -0,0 +1,8 @@ +PASS p formula == SEC2 hex +PASS N == SEC2 hex +PASS G on curve +PASS G.y even (canonical form exists) +PASS repo P_BYTES == p (LE) +PASS repo N_BYTES == N (LE) +PASS repo R_BYTES == 3p (LE) +PASS repo B == 7 diff --git a/thoughts/ec-recover-opt/oracle/check_constants.py b/thoughts/ec-recover-opt/oracle/check_constants.py new file mode 100644 index 000000000..e6f68dcbc --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/check_constants.py @@ -0,0 +1,56 @@ +"""Recompute the curve constants from the SEC2 definition and diff them +against the byte arrays hardcoded in crypto/ecsm/src/lib.rs. + +Parses the Rust source text directly so a repo edit can't silently desync. +""" + +import re +import sys + +from ec_ref import P, N, B, GX, GY, recover_even_y + +REPO_LIB = "/Users/maurofab/workspace/lambda_vm/crypto/ecsm/src/lib.rs" + + +def parse_rust_byte_array(src, name): + m = re.search(rf"pub const {name}: \[u8; \d+\] = \[(.*?)\];", src, re.S) + assert m, f"{name} not found" + return bytes(int(t, 16) for t in re.findall(r"0x([0-9A-Fa-f]{2})", m.group(1))) + + +def main(): + src = open(REPO_LIB).read() + ok = True + + # Independent recomputation from the standard. + p_indep = 2**256 - 2**32 - 977 + # SEC2 v2.0 published hex for p (transcribed from the standard): + p_sec2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F + n_sec2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 + checks = [ + ("p formula == SEC2 hex", p_indep == p_sec2 == P), + ("N == SEC2 hex", N == n_sec2), + ("G on curve", (GY * GY - GX**3 - B) % P == 0), + ("G.y even (canonical form exists)", recover_even_y(GX) is not None), + ] + + p_bytes = parse_rust_byte_array(src, "P_BYTES") + n_bytes = parse_rust_byte_array(src, "N_BYTES") + r_bytes = parse_rust_byte_array(src, "R_BYTES") + b_m = re.search(r"pub const B: u64 = (\d+);", src) + + checks += [ + ("repo P_BYTES == p (LE)", int.from_bytes(p_bytes, "little") == P), + ("repo N_BYTES == N (LE)", int.from_bytes(n_bytes, "little") == N), + ("repo R_BYTES == 3p (LE)", int.from_bytes(r_bytes, "little") == 3 * P), + ("repo B == 7", b_m is not None and int(b_m.group(1)) == B == 7), + ] + + for name, res in checks: + print(f"{'PASS' if res else 'FAIL'} {name}") + ok &= res + sys.exit(0 if ok else 1) + + +if __name__ == "__main__": + main() diff --git a/thoughts/ec-recover-opt/oracle/ec_ref.py b/thoughts/ec-recover-opt/oracle/ec_ref.py new file mode 100644 index 000000000..778089415 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/ec_ref.py @@ -0,0 +1,204 @@ +"""Independent secp256k1 reference for the ECSM/ECDAS oracle. + +Written from the SEC2 curve definition and textbook affine Weierstrass +formulas ONLY. No k256, no transcription from lambda_vm repo code — the whole +point is independent lineage. Constants below are the published SEC2 values +(Certicom SEC2 v2.0, section 2.4.1). + +Curve: y^2 = x^3 + 7 over GF(p), p = 2^256 - 2^32 - 977. +""" + +# ── SEC2 published constants (from the standard, not from the repo) ───────── +P = 2**256 - 2**32 - 977 +N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 +B = 7 +GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 +GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 + +assert P % 4 == 3 # sqrt(a) = a^((p+1)/4) is valid + + +class EcError(Exception): + """Mirrors the accelerator's rejection classes.""" + + def __init__(self, kind): + self.kind = kind # 'ScalarIsZero' | 'ScalarOutOfRange' | 'CoordinateOutOfRange' | 'NotOnCurve' + super().__init__(kind) + + +# ── field helpers ──────────────────────────────────────────────────────────── + +def finv(a): + return pow(a, P - 2, P) + + +def fsqrt_even(a): + """The EVEN square root of a mod p, or None if a is a non-residue.""" + r = pow(a, (P + 1) // 4, P) + if (r * r) % P != a % P: + return None + return r if r % 2 == 0 else P - r + + +def recover_even_y(x): + """Canonical (even) y with y^2 = x^3 + B, or None if x is not on the curve.""" + if not (0 <= x < P): + return None + return fsqrt_even((pow(x, 3, P) + B) % P) + + +# ── affine group law (never the point at infinity; callers guarantee it) ──── + +def pt_double(p1): + x1, y1 = p1 + assert y1 != 0, "double of a 2-torsion point (impossible on secp256k1)" + lam = (3 * x1 * x1 * finv(2 * y1)) % P + x3 = (lam * lam - 2 * x1) % P + y3 = (lam * (x1 - x3) - y1) % P + return (x3, y3) + + +def pt_add(p1, p2): + x1, y1 = p1 + x2, y2 = p2 + assert x1 != x2, "add with equal x (doubling or inverse) must not reach here" + lam = ((y2 - y1) * finv(x2 - x1)) % P + x3 = (lam * lam - x1 - x2) % P + y3 = (lam * (x1 - x3) - y1) % P + return (x3, y3) + + +def pt_neg(p1): + x1, y1 = p1 + return (x1, (P - y1) % P) + + +def scalar_mul(k, pt): + """k·pt by plain MSB-first double-and-add over affine points. + + Requires 1 <= k < N and pt on curve, not infinity. Because the group has + prime order N and 1 <= k < N, no intermediate ever hits infinity and the + add never sees equal-x operands (acc = ±pt would need k' ≡ ±1 with more + bits pending, which the MSB-first schedule only allows transiently — the + assertion in pt_add would fire if the claim were wrong, making this + self-checking rather than silently incorrect). + """ + assert 1 <= k < N + bits = bin(k)[2:] + acc = pt + for b in bits[1:]: + acc = pt_double(acc) + if b == "1": + acc = pt_add(acc, pt) + return acc + + +# ── the precompile ABI mirror ──────────────────────────────────────────────── + +def x_only_mul_ints(x, k): + """Integer-level core: x(k·P) for P = (x, even-y). Raises EcError exactly + when the accelerator's contract rejects. Check order mirrors the contract: + scalar checks, then coordinate range, then curve membership.""" + if k == 0: + raise EcError("ScalarIsZero") + if k >= N: + raise EcError("ScalarOutOfRange") + if x >= P: + raise EcError("CoordinateOutOfRange") + y = recover_even_y(x) + if y is None: + raise EcError("NotOnCurve") + return scalar_mul(k, (x, y))[0] + + +def x_only_mul(x_le: bytes, k_le: bytes) -> bytes: + """Byte-level ABI mirror of ecsm_mul: 32-byte little-endian in/out.""" + assert len(x_le) == 32 and len(k_le) == 32 + x = int.from_bytes(x_le, "little") + k = int.from_bytes(k_le, "little") + xr = x_only_mul_ints(x, k) + return xr.to_bytes(32, "little") + + +# ── documented ECDAS schedule semantics (MSB-first double-and-add rows) ────── + +def expected_schedule(k): + """The row list ((round, op, next_op) per row) the ECDAS design documents: + one double row per bit below the MSB, plus an add row when that bit is set. + `round` is the bit index, op 0=double 1=add, next_op = op of the following + row (0 for the last row). Derived here purely from the bit pattern of k — + an independent statement of the documented algorithm, for comparison + against the repo's schedule/replay. + """ + assert 1 <= k < N + bits = bin(k)[2:] + m = len(bits) - 1 # msb position + rows = [] # (round, op) + for i, b in enumerate(bits[1:]): + rnd = m - 1 - i + rows.append((rnd, 0)) + if b == "1": + rows.append((rnd, 1)) + out = [] + for j, (rnd, op) in enumerate(rows): + nxt = rows[j + 1][1] if j + 1 < len(rows) else 0 + out.append((rnd, op, nxt)) + return out + + +def replay_schedule(k, g): + """Execute expected_schedule step-by-step, returning per-row + (round, op, next_op, a, lambda, r) with a=incoming accumulator, r=result. + Lambda is the tangent/chord slope of that row's operation.""" + sched = expected_schedule(k) + acc = g + steps = [] + for (rnd, op, nxt) in sched: + if op == 0: + lam = (3 * acc[0] * acc[0] * finv(2 * acc[1])) % P + r = pt_double(acc) + else: + lam = ((g[1] - acc[1]) * finv(g[0] - acc[0])) % P + r = pt_add(acc, g) + steps.append((rnd, op, nxt, acc, lam, r)) + acc = r + return steps, acc + + +# ── ecrecover on top of the reference (for the end-to-end differential) ───── + +def ninv(a): + return pow(a, N - 2, N) + + +def ecrecover(msg_hash: bytes, v: int, r: int, s: int): + """Recover the uncompressed pubkey (x, y) or None. v in {0,1} = parity of + R.y. Implements pk = r^-1 (s·R - z·G) from the ECDSA definition. Rejects + r,s outside [1, N) and unrecoverable R. Does not handle recid >= 2.""" + if not (1 <= r < N and 1 <= s < N): + return None + if r >= P: # r is used directly as R.x here (recid>=2 not supported) + return None + y_even = recover_even_y(r) + if y_even is None: + return None + ry = y_even if v == 0 else (P - y_even) % P + R = (r, ry) + z = int.from_bytes(msg_hash, "big") % N + rinv = ninv(r) + u1 = (-(rinv * z)) % N + u2 = (rinv * s) % N + # pk = u1·G + u2·R, handling the (never-for-valid-sigs) degenerate cases. + if u1 == 0 and u2 == 0: + return None + if u1 == 0: + return scalar_mul(u2, R) + if u2 == 0: + return scalar_mul(u1, (GX, GY)) + A = scalar_mul(u1, (GX, GY)) + Bp = scalar_mul(u2, R) + if A[0] == Bp[0]: + if A[1] == Bp[1]: + return pt_double(A) + return None # A = -B: infinity + return pt_add(A, Bp) diff --git a/thoughts/ec-recover-opt/oracle/ecdsa_secp256k1_sha256_p1363_test.json b/thoughts/ec-recover-opt/oracle/ecdsa_secp256k1_sha256_p1363_test.json new file mode 100644 index 000000000..3c59b142e --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/ecdsa_secp256k1_sha256_p1363_test.json @@ -0,0 +1,5500 @@ +{ + "algorithm": "ECDSA", + "schema": "ecdsa_p1363_verify_schema_v1.json", + "numberOfTests": 252, + "header": [ + "Test vectors of type EcdsaVerify are meant for the verification", + "of IEEE P1363 encoded ECDSA signatures." + ], + "notes": { + "ArithmeticError": { + "bugType": "EDGE_CASE", + "description": "Some implementations of ECDSA have arithmetic errors that occur when intermediate results have extreme values. This test vector has been constructed to test such occurrences.", + "cves": [ + "CVE-2017-18146" + ] + }, + "EdgeCasePublicKey": { + "bugType": "EDGE_CASE", + "description": "The test vector uses a special case public key. " + }, + "EdgeCaseShamirMultiplication": { + "bugType": "EDGE_CASE", + "description": "Shamir proposed a fast method for computing the sum of two scalar multiplications efficiently. This test vector has been constructed so that an intermediate result is the point at infinity if Shamir's method is used." + }, + "IntegerOverflow": { + "bugType": "CAN_OF_WORMS", + "description": "The test vector contains an r and s that has been modified, so that the original value is restored if the implementation ignores the most significant bits.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "InvalidSignature": { + "bugType": "AUTH_BYPASS", + "description": "The signature contains special case values such as r=0 and s=0. Buggy implementations may accept such values, if the implementation does not check boundaries and computes s^(-1) == 0.", + "effect": "Accepting such signatures can have the effect that an adversary can forge signatures without even knowing the message to sign.", + "cves": [ + "CVE-2022-21449", + "CVE-2021-43572", + "CVE-2022-24884" + ] + }, + "ModifiedInteger": { + "bugType": "CAN_OF_WORMS", + "description": "The test vector contains an r and s that has been modified. The goal is to check for arithmetic errors.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "ModularInverse": { + "bugType": "EDGE_CASE", + "description": "The test vectors contains a signature where computing the modular inverse of s hits an edge case.", + "effect": "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", + "cves": [ + "CVE-2019-0865" + ] + }, + "PointDuplication": { + "bugType": "EDGE_CASE", + "description": "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission.", + "cves": [ + "2020-12607", + "CVE-2015-2730" + ] + }, + "RangeCheck": { + "bugType": "CAN_OF_WORMS", + "description": "The test vector contains an r and s that has been modified. By adding or subtracting the order of the group (or other values) the test vector checks whether signature verification verifies the range of r and s.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "SignatureSize": { + "bugType": "LEGACY", + "description": "This test vector contains valid values for r and s. But the values are encoded using a smaller number of bytes. The size of an IEEE P1363 encoded signature should always be twice the number of bytes of the size of the order. Some libraries accept signatures with less bytes. To our knowledge no standard (i.e., IEEE P1363 or RFC 7515) requires any explicit checks of the signature size during signature verification." + }, + "SmallRandS": { + "bugType": "EDGE_CASE", + "description": "The test vectors contains a signature where both r and s are small integers. Some libraries cannot verify such signatures.", + "effect": "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", + "cves": [ + "2020-13895" + ] + }, + "SpecialCaseHash": { + "bugType": "EDGE_CASE", + "description": "The test vector contains a signature where the hash of the message is a special case, e.g., contains a long run of 0 or 1 bits." + }, + "ValidSignature": { + "bugType": "BASIC", + "description": "The test vector contains a valid signature that was generated pseudorandomly. Such signatures should not fail to verify unless some of the parameters (e.g. curve or hash function) are not supported." + } + }, + "testGroups": [ + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", + "wx": "00b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6f", + "wy": "00f0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\nA3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 1, + "comment": "signature malleability", + "flags": [ + "ValidSignature" + ], + "msg": "313233343030", + "sig": "813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365900e75ad233fcc908509dbff5922647db37c21f4afd3203ae8dc4ae7794b0f87", + "result": "valid" + }, + { + "tcId": 2, + "comment": "replaced r by r + n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "01813ef79ccefa9a56f7ba805f0e478583b90deabca4b05c4574e49b5899b964a6006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 3, + "comment": "replaced r by r + 256 * n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "0100813ef79ccefa9a56f7ba805f0e47843fad3bf4853e07f7c98770c99bffc4646500006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 4, + "comment": "replaced r by n - r", + "flags": [ + "ModifiedInteger" + ], + "msg": "313233343030", + "sig": "7ec10863310565a908457fa0f1b87a79bc4fcf10b9e0e4320ac021c106b31ddc6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 5, + "comment": "replaced r by r + 2**256", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "01813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 6, + "comment": "replaced r by r + 2**320", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "010000000000000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650000000000000000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 7, + "comment": "replaced s by s + n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "016ff18a52dcc0336f7af62400a6dd9b7fc1e197d8aebe203c96c87232272172fb006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 8, + "comment": "replaced s by s + 256 * n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "01006ff18a52dcc0336f7af62400a6dd9a3bb60fa1a14815bbc0a954a0758d2c72ba00006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 9, + "comment": "replaced s by s + 2**256", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "016ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 10, + "comment": "replaced s by s + 2**320", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "0100000000000000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000000000000000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 11, + "comment": "Signature with special case values r=0 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 12, + "comment": "Signature with special case values r=0 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "result": "invalid" + }, + { + "tcId": 13, + "comment": "Signature with special case values r=0 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 14, + "comment": "Signature with special case values r=0 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 15, + "comment": "Signature with special case values r=0 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 16, + "comment": "Signature with special case values r=0 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 17, + "comment": "Signature with special case values r=0 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 18, + "comment": "Signature with special case values r=1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 19, + "comment": "Signature with special case values r=1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "result": "invalid" + }, + { + "tcId": 20, + "comment": "Signature with special case values r=1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 21, + "comment": "Signature with special case values r=1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 22, + "comment": "Signature with special case values r=1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 23, + "comment": "Signature with special case values r=1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 24, + "comment": "Signature with special case values r=1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 25, + "comment": "Signature with special case values r=n and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 26, + "comment": "Signature with special case values r=n and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410000000000000000000000000000000000000000000000000000000000000001", + "result": "invalid" + }, + { + "tcId": 27, + "comment": "Signature with special case values r=n and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 28, + "comment": "Signature with special case values r=n and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 29, + "comment": "Signature with special case values r=n and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 30, + "comment": "Signature with special case values r=n and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 31, + "comment": "Signature with special case values r=n and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 32, + "comment": "Signature with special case values r=n - 1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641400000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 33, + "comment": "Signature with special case values r=n - 1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641400000000000000000000000000000000000000000000000000000000000000001", + "result": "invalid" + }, + { + "tcId": 34, + "comment": "Signature with special case values r=n - 1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 35, + "comment": "Signature with special case values r=n - 1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 36, + "comment": "Signature with special case values r=n - 1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 37, + "comment": "Signature with special case values r=n - 1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 38, + "comment": "Signature with special case values r=n - 1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 39, + "comment": "Signature with special case values r=n + 1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641420000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 40, + "comment": "Signature with special case values r=n + 1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641420000000000000000000000000000000000000000000000000000000000000001", + "result": "invalid" + }, + { + "tcId": 41, + "comment": "Signature with special case values r=n + 1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 42, + "comment": "Signature with special case values r=n + 1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 43, + "comment": "Signature with special case values r=n + 1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 44, + "comment": "Signature with special case values r=n + 1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 45, + "comment": "Signature with special case values r=n + 1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 46, + "comment": "Signature with special case values r=p and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 47, + "comment": "Signature with special case values r=p and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001", + "result": "invalid" + }, + { + "tcId": 48, + "comment": "Signature with special case values r=p and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 49, + "comment": "Signature with special case values r=p and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 50, + "comment": "Signature with special case values r=p and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 51, + "comment": "Signature with special case values r=p and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 52, + "comment": "Signature with special case values r=p and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 53, + "comment": "Signature with special case values r=p + 1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc300000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 54, + "comment": "Signature with special case values r=p + 1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc300000000000000000000000000000000000000000000000000000000000000001", + "result": "invalid" + }, + { + "tcId": 55, + "comment": "Signature with special case values r=p + 1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 56, + "comment": "Signature with special case values r=p + 1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 57, + "comment": "Signature with special case values r=p + 1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 58, + "comment": "Signature with special case values r=p + 1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 59, + "comment": "Signature with special case values r=p + 1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 60, + "comment": "Edge case for Shamir multiplication", + "flags": [ + "EdgeCaseShamirMultiplication" + ], + "msg": "3235353835", + "sig": "dd1b7d09a7bd8218961034a39a87fecf5314f00c4d25eb58a07ac85e85eab51635138c401ef8d3493d65c9002fe62b43aee568731b744548358996d9cc427e06", + "result": "valid" + }, + { + "tcId": 61, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "343236343739373234", + "sig": "95c29267d972a043d955224546222bba343fc1d4db0fec262a33ac61305696ae6edfe96713aed56f8a28a6653f57e0b829712e5eddc67f34682b24f0676b2640", + "result": "valid" + }, + { + "tcId": 62, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "37313338363834383931", + "sig": "28f94a894e92024699e345fe66971e3edcd050023386135ab3939d550898fb25cd69c1a42be05a6ee1270c821479251e134c21858d800bda6f4e98b37196238e", + "result": "valid" + }, + { + "tcId": 63, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130333539333331363638", + "sig": "be26b18f9549f89f411a9b52536b15aa270b84548d0e859a1952a27af1a77ac68f3e2b05632fc33715572af9124681113f2b84325b80154c044a544dc1a8fa12", + "result": "valid" + }, + { + "tcId": 64, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33393439343031323135", + "sig": "b1a4b1478e65cc3eafdf225d1298b43f2da19e4bcff7eacc0a2e98cd4b74b114e8655ce1cfb33ebd30af8ce8e8ae4d6f7b50cd3e22af51bf69e0a2851760d52b", + "result": "valid" + }, + { + "tcId": 65, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31333434323933303739", + "sig": "325332021261f1bd18f2712aa1e2252da23796da8a4b1ff6ea18cafec7e171f240b4f5e287ee61fc3c804186982360891eaa35c75f05a43ecd48b35d984a6648", + "result": "valid" + }, + { + "tcId": 66, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33373036323131373132", + "sig": "a23ad18d8fc66d81af0903890cbd453a554cb04cdc1a8ca7f7f78e5367ed88a0dc1c14d31e3fb158b73c764268c8b55579734a7e2a2c9b5ee5d9d0144ef652eb", + "result": "valid" + }, + { + "tcId": 67, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "333433363838373132", + "sig": "2bdea41cda63a2d14bf47353bd20880a690901de7cd6e3cc6d8ed5ba0cdb1091c31599433036064073835b1e3eba8335a650c8fd786f94fe235ad7d41dc94c7a", + "result": "valid" + }, + { + "tcId": 68, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31333531353330333730", + "sig": "d7cd76ec01c1b1079eba9e2aa2a397243c4758c98a1ba0b7404a340b9b00ced6ca8affe1e626dd192174c2937b15bc48f77b5bdfe01f073a8aeaf7f24dc6c85b", + "result": "valid" + }, + { + "tcId": 69, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36353533323033313236", + "sig": "a872c744d936db21a10c361dd5c9063355f84902219652f6fc56dc95a7139d96400df7575d9756210e9ccc77162c6b593c7746cfb48ac263c42750b421ef4bb9", + "result": "valid" + }, + { + "tcId": 70, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31353634333436363033", + "sig": "9fa9afe07752da10b36d3afcd0fe44bfc40244d75203599cf8f5047fa3453854af1f583fec4040ae7e68c968d2bb4b494eec3a33edc7c0ccf95f7f75bc2569c7", + "result": "valid" + }, + { + "tcId": 71, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "34343239353339313137", + "sig": "885640384d0d910efb177b46be6c3dc5cac81f0b88c3190bb6b5f99c2641f205738ed9bff116306d9caa0f8fc608be243e0b567779d8dab03e8e19d553f1dc8e", + "result": "valid" + }, + { + "tcId": 72, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130393533323631333531", + "sig": "2d051f91c5a9d440c5676985710483bc4f1a6c611b10c95a2ff0363d90c2a45892206b19045a41a797cc2f3ac30de9518165e96d5b86341ecb3bcff231b3fd65", + "result": "valid" + }, + { + "tcId": 73, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35393837333530303431", + "sig": "f3ac2523967482f53d508522712d583f4379cd824101ff635ea0935117baa54f27f10812227397e02cea96fb0e680761636dab2b080d1fc5d11685cbe8500cfe", + "result": "valid" + }, + { + "tcId": 74, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33343633303036383738", + "sig": "96447cf68c3ab7266ed7447de3ac52fed7cc08cbdfea391c18a9b8ab370bc913f0a1878b2c53f16e70fe377a5e9c6e86f18ae480a22bb499f5b32e7109c07385", + "result": "valid" + }, + { + "tcId": 75, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "39383137333230323837", + "sig": "530a0832b691da0b5619a0b11de6877f3c0971baaa68ed122758c29caaf46b7293761bb0a14ccf9f15b4b9ce73c6ec700bd015b8cb1cfac56837f4463f53074e", + "result": "valid" + }, + { + "tcId": 76, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33323232303431303436", + "sig": "9c54c25500bde0b92d72d6ec483dc2482f3654294ca74de796b681255ed58a77988bac394a90ad89ce360984c0c149dcbd2684bb64498ace90bcf6b6af1c170e", + "result": "valid" + }, + { + "tcId": 77, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36363636333037313034", + "sig": "e7909d41439e2f6af29136c7348ca2641a2b070d5b64f91ea9da7070c7a2618b42d782f132fa1d36c2c88ba27c3d678d80184a5d1eccac7501f0b47e3d205008", + "result": "valid" + }, + { + "tcId": 78, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31303335393531383938", + "sig": "5924873209593135a4c3da7bb381227f8a4b6aa9f34fe5bb7f8fbc131a039ffee0e44ee4bbe370155bf0bbdec265bf9fe31c0746faab446de62e3631eacd111f", + "result": "valid" + }, + { + "tcId": 79, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31383436353937313935", + "sig": "eeb692c9b262969b231c38b5a7f60649e0c875cd64df88f33aa571fa3d29ab0e218b3a1eb06379c2c18cf51b06430786d1c64cd2d24c9b232b23e5bac7989acd", + "result": "valid" + }, + { + "tcId": 80, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33313336303436313839", + "sig": "a40034177f36091c2b653684a0e3eb5d4bff18e4d09f664c2800e7cafda1daf83a3ec29853704e52031c58927a800a968353adc3d973beba9172cbbeab4dd149", + "result": "valid" + }, + { + "tcId": 81, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "32363633373834323534", + "sig": "b5d795cc75cea5c434fa4185180cd6bd21223f3d5a86da6670d71d95680dadbfab1b277ef5ffe134460835e3d1402461ba104cb50b16f397fdc7a9abfefef280", + "result": "valid" + }, + { + "tcId": 82, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31363532313030353234", + "sig": "07dc2478d43c1232a4595608c64426c35510051a631ae6a5a6eb1161e57e42e14a59ea0fdb72d12165cea3bf1ca86ba97517bd188db3dbd21a5a157850021984", + "result": "valid" + }, + { + "tcId": 83, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35373438303831363936", + "sig": "ddd20c4a05596ca868b558839fce9f6511ddd83d1ccb53f82e5269d559a01552a46e8cb8d626cf6c00ddedc3b5da7e613ac376445ee260743f06f79054c7d42a", + "result": "valid" + }, + { + "tcId": 84, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36333433393133343638", + "sig": "9cde6e0ede0a003f02fda0a01b59facfe5dec063318f279ce2de7a9b1062f7b72886a5b8c679bdf8224c66f908fd6205492cb70b0068d46ae4f33a4149b12a52", + "result": "valid" + }, + { + "tcId": 85, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31353431313033353938", + "sig": "c5771016d0dd6357143c89f684cd740423502554c0c59aa8c99584f1ff38f609ab4bfa0bb88ab99791b9b3ab9c4b02bd2a57ae8dde50b9064063fcf85315cfe5", + "result": "valid" + }, + { + "tcId": 86, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130343738353830313238", + "sig": "a24ebc0ec224bd67ae397cbe6fa37b3125adbd34891abe2d7c7356921916dfe634f6eb6374731bbbafc4924fb8b0bdcdda49456d724cdae6178d87014cb53d8c", + "result": "valid" + }, + { + "tcId": 87, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130353336323835353638", + "sig": "2557d64a7aee2e0931c012e4fea1cd3a2c334edae68cdeb7158caf21b68e5a2480f93244956ffdc568c77d12684f7f004fa92da7e60ae94a1b98c422e23eda34", + "result": "valid" + }, + { + "tcId": 88, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "393533393034313035", + "sig": "c4f2eccbb6a24350c8466450b9d61b207ee359e037b3dcedb42a3f2e6dd6aeb5cd9c394a65d0aa322e391eb76b2a1a687f8620a88adef3a01eb8e4fb05b6477a", + "result": "valid" + }, + { + "tcId": 89, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "393738383438303339", + "sig": "eff04781c9cbcd162d0a25a6e2ebcca43506c523385cb515d49ea38a1b12fcadea5328ce6b36e56ab87acb0dcfea498bcec1bba86a065268f6eff3c41c4b0c9c", + "result": "valid" + }, + { + "tcId": 90, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33363130363732343432", + "sig": "f58b4e3110a64bf1b5db97639ee0e5a9c8dfa49dc59b679891f520fdf0584c87d32701ae777511624c1f8abbf02b248b04e7a9eb27938f524f3e8828ba40164a", + "result": "valid" + }, + { + "tcId": 91, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31303534323430373035", + "sig": "f8abecaa4f0c502de4bf5903d48417f786bf92e8ad72fec0bd7fcb7800c0bbe34c7f9e231076a30b7ae36b0cebe69ccef1cd194f7cce93a5588fd6814f437c0e", + "result": "valid" + }, + { + "tcId": 92, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35313734343438313937", + "sig": "5d5b38bd37ad498b2227a633268a8cca879a5c7c94a4e416bd0a614d09e606d212b8d664ea9991062ecbb834e58400e25c46007af84f6007d7f1685443269afe", + "result": "valid" + }, + { + "tcId": 93, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31393637353631323531", + "sig": "0c1cd9fe4034f086a2b52d65b9d3834d72aebe7f33dfe8f976da82648177d8e313105782e3d0cfe85c2778dec1a848b27ac0ae071aa6da341a9553a946b41e59", + "result": "valid" + }, + { + "tcId": 94, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33343437323533333433", + "sig": "ae7935fb96ff246b7b5d5662870d1ba587b03d6e1360baf47988b5c02ccc1a5b5f00c323272083782d4a59f2dfd65e49de0693627016900ef7e61428056664b3", + "result": "valid" + }, + { + "tcId": 95, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "333638323634333138", + "sig": "00a134b5c6ccbcefd4c882b945baeb4933444172795fa6796aae149067547098a991b9efa2db276feae1c115c140770901839d87e60e7ec45a2b81cf3b437be6", + "result": "valid" + }, + { + "tcId": 96, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33323631313938363038", + "sig": "2e4721363ad3992c139e5a1c26395d2c2d777824aa24fde075e0d7381171309d8bf083b6bbe71ecff22baed087d5a77eaeaf726bf14ace2c03fd6e37ba6c26f2", + "result": "valid" + }, + { + "tcId": 97, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "39363738373831303934", + "sig": "6852e9d3cd9fe373c2d504877967d365ab1456707b6817a042864694e1960ccff9b4d815ebd4cf77847b37952334d05b2045cb398d4c21ba207922a7a4714d84", + "result": "valid" + }, + { + "tcId": 98, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "34393538383233383233", + "sig": "188a8c5648dc79eace158cf886c62b5468f05fd95f03a7635c5b4c31f09af4c536361a0b571a00c6cd5e686ccbfcfa703c4f97e48938346d0c103fdc76dc5867", + "result": "valid" + }, + { + "tcId": 99, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "383234363337383337", + "sig": "a74f1fb9a8263f62fc4416a5b7d584f4206f3996bb91f6fc8e73b9e92bad0e136815032e8c7d76c3ab06a86f33249ce9940148cb36d1f417c2e992e801afa3fa", + "result": "valid" + }, + { + "tcId": 100, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3131303230383333373736", + "sig": "07244865b72ff37e62e3146f0dc14682badd7197799135f0b00ade7671742bfef27f3ddc7124b1b58579573a835650e7a8bad5eeb96e9da215cd7bf9a2a039ed", + "result": "valid" + }, + { + "tcId": 101, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "313333383731363438", + "sig": "da7fdd05b5badabd619d805c4ee7d9a84f84ddd5cf9c5bf4d4338140d689ef0828f1cf4fa1c3c5862cfa149c0013cf5fe6cf5076cae000511063e7de25bb38e5", + "result": "valid" + }, + { + "tcId": 102, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "333232313434313632", + "sig": "d3027c656f6d4fdfd8ede22093e3c303b0133c340d615e7756f6253aea927238f6510f9f371b31068d68bfeeaa720eb9bbdc8040145fcf88d4e0b58de0777d2a", + "result": "valid" + }, + { + "tcId": 103, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130363836363535353436", + "sig": "0bf6c0188dc9571cd0e21eecac5fbb19d2434988e9cc10244593ef3a98099f694864a562661f9221ec88e3dd0bc2f6e27ac128c30cc1a80f79ec670a22b042ee", + "result": "valid" + }, + { + "tcId": 104, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3632313535323436", + "sig": "ae459640d5d1179be47a47fa538e16d94ddea5585e7a244804a51742c686443a6c8e30e530a634fae80b3ceb062978b39edbe19777e0a24553b68886181fd897", + "result": "valid" + }, + { + "tcId": 105, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "37303330383138373734", + "sig": "1cf3517ba3bf2ab8b9ead4ebb6e866cb88a1deacb6a785d3b63b483ca02ac495249a798b73606f55f5f1c70de67cb1a0cff95d7dc50b3a617df861bad3c6b1c9", + "result": "valid" + }, + { + "tcId": 106, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35393234353233373434", + "sig": "e69b5238265ea35d77e4dd172288d8cea19810a10292617d5976519dc5757cb84b03c5bc47e826bdb27328abd38d3056d77476b2130f3df6ec4891af08ba1e29", + "result": "valid" + }, + { + "tcId": 107, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31343935353836363231", + "sig": "5f9d7d7c870d085fc1d49fff69e4a275812800d2cf8973e7325866cb40fa2b6f6d1f5491d9f717a597a15fd540406486d76a44697b3f0d9d6dcef6669f8a0a56", + "result": "valid" + }, + { + "tcId": 108, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "34303035333134343036", + "sig": "0a7d5b1959f71df9f817146ee49bd5c89b431e7993e2fdecab6858957da685ae0f8aad2d254690bdc13f34a4fec44a02fd745a422df05ccbb54635a8b86b9609", + "result": "valid" + }, + { + "tcId": 109, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33303936343537353132", + "sig": "79e88bf576b74bc07ca142395fda28f03d3d5e640b0b4ff0752c6d94cd55340832cea05bd2d706c8f6036a507e2ab7766004f0904e2e5c5862749c0073245d6a", + "result": "valid" + }, + { + "tcId": 110, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "32373834303235363230", + "sig": "9d54e037a00212b377bc8874798b8da080564bbdf7e07591b861285809d0148818b4e557667a82bd95965f0706f81a29243fbdd86968a7ebeb43069db3b18c7f", + "result": "valid" + }, + { + "tcId": 111, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "32363138373837343138", + "sig": "2664f1ffa982fedbcc7cab1b8bc6e2cb420218d2a6077ad08e591ba9feab33bd49f5c7cb515e83872a3d41b4cdb85f242ad9d61a5bfc01debfbb52c6c84ba728", + "result": "valid" + }, + { + "tcId": 112, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31363432363235323632", + "sig": "5827518344844fd6a7de73cbb0a6befdea7b13d2dee4475317f0f18ffc81524bb0a334b1f4b774a5a289f553224d286d239ef8a90929ed2d91423e024eb7fa66", + "result": "valid" + }, + { + "tcId": 113, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36383234313839343336", + "sig": "97ab19bd139cac319325869218b1bce111875d63fb12098a04b0cd59b6fdd3a3bce26315c5dbc7b8cfc31425a9b89bccea7aa9477d711a4d377f833dcc28f820", + "result": "valid" + }, + { + "tcId": 114, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "343834323435343235", + "sig": "52c683144e44119ae2013749d4964ef67509278f6d38ba869adcfa69970e123d3479910167408f45bda420a626ec9c4ec711c1274be092198b4187c018b562ca", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "uDj_ROW8F3vyEYnQdmCC_J2EMiaIf8l2A3EQC37iCm8", + "y": "8MnXW_unsxpryhl0SW7rVt41cHGVXYPEsbraoLIYMuk", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", + "wx": "07310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc362", + "wy": "26a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEBzEPkKnq4UmghAL1QZSg97SsQnv42b1s\ndoEHHcR9w2ImptN6xG1h/WAMC/G/+HaJ7RF92msOWTGK4BChl6JsoA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 115, + "comment": "k*G has a large x-coordinate", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "000000000000000000000000000000014551231950b75fc4402da1722fc9baebfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + }, + { + "tcId": 116, + "comment": "r too large", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2cfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "BzEPkKnq4UmghAL1QZSg97SsQnv42b1sdoEHHcR9w2I", + "y": "JqbTesRtYf1gDAvxv_h2ie0RfdprDlkxiuAQoZeibKA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", + "wx": "00bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22", + "wy": "705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvJfnWF7srUjhZoO8QJFwjhqTDGg/xHAB\n1LODWU8sTiJwWYnPadrq3U5OS4FR7YiN/sIPsBco2J1Ws/OPKunIxQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 117, + "comment": "r,s are large", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "vJfnWF7srUjhZoO8QJFwjhqTDGg_xHAB1LODWU8sTiI", + "y": "cFmJz2na6t1OTkuBUe2Ijf7CD7AXKNidVrPzjyrpyMU", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", + "wx": "44ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252", + "wy": "00b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERK0zmvvCHpq/e2AqXKU16jeBNbbRDYEx\nC92Ck9HfMlK2P/fQd0dw+P4dFyL6g6zQL0NOT8EQoMyPbd3TfVbEYw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 118, + "comment": "r and s^-1 have a large Hamming weight", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3e9a7582886089c62fb840cf3b83061cd1cff3ae4341808bb5bdee6191174177", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "RK0zmvvCHpq_e2AqXKU16jeBNbbRDYExC92Ck9HfMlI", + "y": "tj_30HdHcPj-HRci-oOs0C9DTk_BEKDMj23d031WxGM", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", + "wx": "1260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c", + "wy": "5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEmDCEiyeJE4a9RUb7eDDriO1TXxZaIHT\n7rrSHzfdh4xcmgwamt52c3qIEb1qf5KHyXjuOWqonBHkcinSzLVS8A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 119, + "comment": "r and s^-1 have a large Hamming weight", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc24238e70b431b1a64efdf9032669939d4b77f249503fc6905feb7540dea3e6d2", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "EmDCEiyeJE4a9RUb7eDDriO1TXxZaIHT7rrSHzfdh4w", + "y": "XJoMGprednN6iBG9an-Sh8l47jlqqJwR5HIp0sy1UvA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", + "wx": "1877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce", + "wy": "00821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGHcEW+JdNKHQYA+dXADQZFoqVDebbO76\n0ua/XCozUs6CGlMswXUe4dNtQcPWq06bFD5E7EbXNHjqanmlwOVBWQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 120, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "result": "valid" + }, + { + "tcId": 121, + "comment": "incorrect size of signature", + "flags": [ + "SmallRandS", + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "0101", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "GHcEW-JdNKHQYA-dXADQZFoqVDebbO760ua_XCozUs4", + "y": "ghpTLMF1HuHTbUHD1qtOmxQ-ROxG1zR46mp5pcDlQVk", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", + "wx": "455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50", + "wy": "00aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERVQ5/MPS3uzt3q7OYOe9FzBPNuu2Aq31\noi4Ljx20alCuw4+yuvIh6ajRiHx79iIt0YNGNOdyYzFa9tI2CdBPdw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 122, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "result": "valid" + }, + { + "tcId": 123, + "comment": "incorrect size of signature", + "flags": [ + "SmallRandS", + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "0102", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "RVQ5_MPS3uzt3q7OYOe9FzBPNuu2Aq31oi4Ljx20alA", + "y": "rsOPsrryIemo0Yh8e_YiLdGDRjTncmMxWvbSNgnQT3c", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", + "wx": "2e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece718", + "wy": "0449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELh9GawJMDDrOJDfeCRJ/7QS3BvlLGaIb\nscKs81zs5xgESa41I9clNOlklyz9OzivC93ZYZ5a8iPk0aQPNM+fHQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 124, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003", + "result": "valid" + }, + { + "tcId": 125, + "comment": "incorrect size of signature", + "flags": [ + "SmallRandS", + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "0103", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Lh9GawJMDDrOJDfeCRJ_7QS3BvlLGaIbscKs81zs5xg", + "y": "BEmuNSPXJTTpZJcs_Ts4rwvd2WGeWvIj5NGkDzTPnx0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", + "wx": "008e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a23373", + "wy": "26ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjnq9u9GN50UjdMGHmhw7AdEyYefUVxw7\nR6HHbFWiM3Mm7Yl81Rek9TSduAl4D20vK59imdi1qJB38RGacY/Xsw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 126, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001", + "result": "valid" + }, + { + "tcId": 127, + "comment": "incorrect size of signature", + "flags": [ + "SmallRandS", + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "0201", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "jnq9u9GN50UjdMGHmhw7AdEyYefUVxw7R6HHbFWiM3M", + "y": "Ju2JfNUXpPU0nbgJeA9tLyufYpnYtaiQd_ERmnGP17M", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", + "wx": "7b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af19", + "wy": "42117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEezM9Q0DT1xjdPmr/fee7+Lcr/WFshCAF\nYFKEI3a5rxlCEXxa/qx1XW83b8Yymn12BRuHEjpKXQvEpTk4DwPeew==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 128, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002", + "result": "valid" + }, + { + "tcId": 129, + "comment": "incorrect size of signature", + "flags": [ + "SmallRandS", + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "0202", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "ezM9Q0DT1xjdPmr_fee7-Lcr_WFshCAFYFKEI3a5rxk", + "y": "QhF8Wv6sdV1vN2_GMpp9dgUbhxI6Sl0LxKU5OA8D3ns", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", + "wx": "00d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e5", + "wy": "03a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0wykoN22YWyFHTDO1oLED4PGJ1ih8nWZ\niNZ2OojxwOUDqA1UFWUNQSOXhOji+xI16f6ZHREuu4EYbL8Not46/w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 130, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", + "result": "valid" + }, + { + "tcId": 131, + "comment": "incorrect size of signature", + "flags": [ + "SmallRandS", + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "0203", + "result": "invalid" + }, + { + "tcId": 132, + "comment": "r is larger than n", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641430000000000000000000000000000000000000000000000000000000000000003", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "0wykoN22YWyFHTDO1oLED4PGJ1ih8nWZiNZ2OojxwOU", + "y": "A6gNVBVlDUEjl4To4vsSNen-mR0RLruBGGy_DaLeOv8", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", + "wx": "48969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24", + "wy": "00b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESJabOZkSl7MyplLT7m4B6QmzmQTnH6I1\nSngwx3ULryS0AS0bgw0ZnMsfyXKzK/3tVfCc1i0lfl6ETiflehWU7A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 133, + "comment": "s is larger than n", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000002fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd04917c8", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "SJabOZkSl7MyplLT7m4B6QmzmQTnH6I1Sngwx3ULryQ", + "y": "tAEtG4MNGZzLH8lysyv97VXwnNYtJX5ehE4n5XoVlOw", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", + "wx": "02ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee77", + "wy": "7eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAu9NbWz9WpTx13hCJuPipsCkNsVYOWGf\nOPtEcrX57nd+tKzU7r2lzXKHX/0qLyYinC3GtGUAkZpDLIZznzroZg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 134, + "comment": "small r and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000101c58b162c58b162c58b162c58b162c58a1b242973853e16db75c8a1a71da4d39d", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Au9NbWz9WpTx13hCJuPipsCkNsVYOWGfOPtEcrX57nc", + "y": "frSs1O69pc1yh1_9Ki8mIpwtxrRlAJGaQyyGc5866GY", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", + "wx": "464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584", + "wy": "00b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERk9P9xVynK5Qcso72AHTGVtnrsZemwGq\n0gopQ9y8tYSxr9KdMaOaEdVwqhWXQ5s7LRlxvy8avxVDLQIHsQ0dCA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 135, + "comment": "smallish r and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "000000000000000000000000000000000000000000000000002d9b4d347952ccfcbc5103d0da267477d1791461cf2aa44bf9d43198f79507bd8779d69a13108e", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Rk9P9xVynK5Qcso72AHTGVtnrsZemwGq0gopQ9y8tYQ", + "y": "sa_SnTGjmhHVcKoVl0ObOy0Zcb8vGr8VQy0CB7ENHQg", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", + "wx": "157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4c", + "wy": "00deadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFX+P3fNz619Jz88Q2LhTz5HLzX1mXDUi\nun3XON23mkzerfGlxEjqPJ9BkaiZmr/MdXrG1kVn7wcsR/7GE0Q7jw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 136, + "comment": "100-bit r and small s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "000000000000000000000000000000000000001033e67e37b32b445580bf4efc906f906f906f906f906f906f906f906ed8e426f7b1968c35a204236a579723d2", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "FX-P3fNz619Jz88Q2LhTz5HLzX1mXDUiun3XON23mkw", + "y": "3q3xpcRI6jyfQZGomZq_zHV6xtZFZ-8HLEf-xhNEO48", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", + "wx": "0934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0", + "wy": "00d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECTSlN0ZsB0MOLEj+uZC7Gft4zsyc7kJO\npNEwKRqiN/DU+S0jtGKAS1toxSVYwByZltv3J/zKu+7bliGkAFNa+g==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 137, + "comment": "small r and 100 bit s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000000000000000000101783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "CTSlN0ZsB0MOLEj-uZC7Gft4zsyc7kJOpNEwKRqiN_A", + "y": "1PktI7RigEtbaMUlWMAcmZbb9yf8yrvu25YhpABTWvo", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", + "wx": "00d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c65", + "wy": "4a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1u8gvmbIk/dBqb+Q2bdGddHCoxKWOXrL\nPvF0/QswDGVKDJVHjKADmRYtfw8tyJ79wrKKMPur4oWFcpWksMTiZQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 138, + "comment": "100-bit r and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "00000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c26783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "1u8gvmbIk_dBqb-Q2bdGddHCoxKWOXrLPvF0_QswDGU", + "y": "SgyVR4ygA5kWLX8PLcie_cKyijD7q-KFhXKVpLDE4mU", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", + "wx": "00b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee06", + "wy": "29c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEtykdFATgwMB9q5NyGJ9L1Y0s6qjRXt5U\nTZUUVFup7gYpyaY9XjCHacww7CdqQQ5kZKJ+6v2eWZ2xDwU6T+SoKQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 139, + "comment": "r and s^-1 are close to n", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c155555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "tykdFATgwMB9q5NyGJ9L1Y0s6qjRXt5UTZUUVFup7gY", + "y": "KcmmPV4wh2nMMOwnakEOZGSifur9nlmdsQ8FOk_kqCk", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", + "wx": "6e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8", + "wy": "186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbigwMwXWQsy5I7ci6oayoLyONzXssm6E\nmxnJ92sv27gYboDWTYyrFk9SOPUxhGG/idTZbuZUTIFsdWaUd3Tg9g==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 140, + "comment": "r and s are 64-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000000000000009c44febf31c3594d000000000000000000000000000000000000000000000000839ed28247c2b06b", + "result": "valid" + }, + { + "tcId": 141, + "comment": "incorrect size of signature", + "flags": [ + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "9c44febf31c3594d839ed28247c2b06b", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "bigwMwXWQsy5I7ci6oayoLyONzXssm6EmxnJ92sv27g", + "y": "GG6A1k2MqxZPUjj1MYRhv4nU2W7mVEyBbHVmlHd04PY", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", + "wx": "375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9", + "wy": "00a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEN1vak/avkvtfj0sbXwU047r6s0y3rZ+5\n0Lci5KXDAqmgC584elo5YJeqIWL8W7z0pSYzcvaByU2lHpeZEgmQ/Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 142, + "comment": "r and s are 100-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "0000000000000000000000000000000000000009df8b682430beef6f5fd7c7cf000000000000000000000000000000000000000fd0a62e13778f4222a0d61c8a", + "result": "valid" + }, + { + "tcId": 143, + "comment": "incorrect size of signature", + "flags": [ + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "09df8b682430beef6f5fd7c7cf0fd0a62e13778f4222a0d61c8a", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "N1vak_avkvtfj0sbXwU047r6s0y3rZ-50Lci5KXDAqk", + "y": "oAufOHpaOWCXqiFi_Fu89KUmM3L2gclNpR6XmRIJkP0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", + "wx": "00d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197", + "wy": "00da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE11toIWur4DriV+lLTjvxxS9E498mbRUk\n/4xepp2nMZfaS/+e0cU/RJF6Z9e5eFmOid81nj1ZE+rqJPOuJZq8RA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 144, + "comment": "r and s are 128-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "000000000000000000000000000000008a598e563a89f526c32ebec8de26367a0000000000000000000000000000000084f633e2042630e99dd0f1e16f7a04bf", + "result": "valid" + }, + { + "tcId": 145, + "comment": "incorrect size of signature", + "flags": [ + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "8a598e563a89f526c32ebec8de26367a84f633e2042630e99dd0f1e16f7a04bf", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "11toIWur4DriV-lLTjvxxS9E498mbRUk_4xepp2nMZc", + "y": "2kv_ntHFP0SRemfXuXhZjonfNZ49WRPq6iTzriWavEQ", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", + "wx": "78bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653", + "wy": "118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeLzaFArtI9QwyyPD3A0B9CPbE07pSjqM\ntIPy3qwqxlMRgRT28zBF1OntkQcIUAe/vd+PWP56GiRF1mqZAEVHbg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 146, + "comment": "r and s are 160-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "000000000000000000000000aa6eeb5823f7fa31b466bb473797f0d0314c0bdf000000000000000000000000e2977c479e6d25703cebbc6bd561938cc9d1bfb9", + "result": "valid" + }, + { + "tcId": 147, + "comment": "incorrect size of signature", + "flags": [ + "ArithmeticError", + "SignatureSize" + ], + "msg": "313233343030", + "sig": "aa6eeb5823f7fa31b466bb473797f0d0314c0bdfe2977c479e6d25703cebbc6bd561938cc9d1bfb9", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "eLzaFArtI9QwyyPD3A0B9CPbE07pSjqMtIPy3qwqxlM", + "y": "EYEU9vMwRdTp7ZEHCFAHv73fj1j-ehokRdZqmQBFR24", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", + "wx": "00bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c", + "wy": "1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEu3n2GFf3Q7+htucRHOQJQ3claWnk4VFZ\nEj2VSKzDvmwfnZ+IYNz/0+s23Wwx/y5yJsIAnEyU2NfStWhr96vWdw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 148, + "comment": "s == 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10000000000000000000000000000000000000000000000000000000000000001", + "result": "valid" + }, + { + "tcId": 149, + "comment": "s == 0", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "u3n2GFf3Q7-htucRHOQJQ3claWnk4VFZEj2VSKzDvmw", + "y": "H52fiGDc_9PrNt1sMf8ucibCAJxMlNjX0rVoa_er1nc", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", + "wx": "0093591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36", + "wy": "073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEk1kYJ9nmcTtOn66mLHKyjf76aODAUWC1\n1qroj9LjbDYHP1VFrVr0EK8mr/9oZUz3LUXkk0iTESAyRzR6iQ9FGA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 150, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1419d981c515af8cc82545aac0c85e9e308fbb2eab6acd7ed497e0b4145a18fd9", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "k1kYJ9nmcTtOn66mLHKyjf76aODAUWC11qroj9LjbDY", + "y": "Bz9VRa1a9BCvJq__aGVM9y1F5JNIkxEgMkc0eokPRRg", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", + "wx": "31ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0da", + "wy": "00da01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMe0wga7+AB62QCBp7izMGGKTe4WZUUTb\nqVA5Q1h78NraAbjMTfNPWrOxo1lhUgiUbl7jX5jud1uMzs2GzMFlDw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 151, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c11b21717ad71d23bbac60a9ad0baf75b063c9fdf52a00ebf99d022172910993c9", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Me0wga7-AB62QCBp7izMGGKTe4WZUUTbqVA5Q1h78No", + "y": "2gG4zE3zT1qzsaNZYVIIlG5e41-Y7ndbjM7NhszBZQ8", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", + "wx": "7dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea8", + "wy": "54c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEff9m+phQn/Pi5RBF9DkFI9zNpDo7wohe\nWMJICQmQ7qhUx2wrmt62u1cYI+B/18ZchjnPnZBSYAZMjnZ1zm2YtA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 152, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c12f588f66018f3dd14db3e28e77996487e32486b521ed8e5a20f06591951777e9", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "ff9m-phQn_Pi5RBF9DkFI9zNpDo7woheWMJICQmQ7qg", + "y": "VMdsK5retrtXGCPgf9fGXIY5z52QUmAGTI52dc5tmLQ", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", + "wx": "4280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a", + "wy": "2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEQoBQmqtk7fwLSiln5MvOhJy1ROSncxPI\n5uzlefvXQgouif5cwZJ9VU5qO7FAM+p8kizXXLosdBX9q1LyCxhg8Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 153, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1091a08870ff4daf9123b30c20e8c4fc8505758dcf4074fcaff2170c9bfcf74f4", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "QoBQmqtk7fwLSiln5MvOhJy1ROSncxPI5uzlefvXQgo", + "y": "Lon-XMGSfVVOajuxQDPqfJIs11y6LHQV_atS8gsYYPE", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", + "wx": "4f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb", + "wy": "2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAET43xRRlOPE/D7qJtQ851tALWsXRy3cuy\nVLinmwvz2csqog2ChEyyZjROccp48q0np1oJ5bwPpX5O/Z1GWgiI2w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 154, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c17c370dc0ce8c59a8b273cba44a7c1191fc3186dc03cab96b0567312df0d0b250", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "T43xRRlOPE_D7qJtQ851tALWsXRy3cuyVLinmwvz2cs", + "y": "KqINgoRMsmY0TnHKePKtJ6daCeW8D6V-Tv2dRloIiNs", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", + "wx": "009598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14", + "wy": "122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElZilfdZ+w+FrWHoziqOhCjo5E7QaOvMu\nPtP/ATWMaxQSKBnt+AdLvFIffUzc6C/velFnBq/7odk9neqcyuGiBw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 155, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c170b59a7d1ee77a2f9e0491c2a7cfcd0ed04df4a35192f6132dcc668c79a6160e", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "lZilfdZ-w-FrWHoziqOhCjo5E7QaOvMuPtP_ATWMaxQ", + "y": "EigZ7fgHS7xSH31M3Ogv73pRZwav-6HZPZ3qnMrhogc", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", + "wx": "009171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e", + "wy": "634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkXH+w8oggGvAhPEvB2CRG2CZC9gOWypx\nygOgSLIPg35jT9F4Y3YbKVjSvk4Un409ervcGL4D9FGrbBf6Ch+DMA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 156, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c12736d76e412246e097148e2bf62915614eb7c428913a58eb5e9cd4674a9423de", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "kXH-w8oggGvAhPEvB2CRG2CZC9gOWypxygOgSLIPg34", + "y": "Y0_ReGN2GylY0r5OFJ-NPXq73Bi-A_RRq2wX-gofgzA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", + "wx": "777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9", + "wy": "00ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEd3yJMLbh0nEQD+aM6T8WP6N2EsX/9n9K\nYvw7r689F6ntc9hvYKUbXtkTU6OwVO3AqpLJ68vQt10Yj9yIJ5HWjQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 157, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c14a1e12831fbe93627b02d6e7f24bccdd6ef4b2d0f46739eaf3b1eaf0ca117770", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "d3yJMLbh0nEQD-aM6T8WP6N2EsX_9n9KYvw7r689F6k", + "y": "7XPYb2ClG17ZE1OjsFTtwKqSyevL0LddGI_ciCeR1o0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", + "wx": "00eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf470", + "wy": "0603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE6rwkj2JuCmPh64HEPUYaOaHbqIHrbuIV\nKwfDLXG89HAGA8qoudM9sTr0TG777IoZjtYSSsnrF+qv0oJKVF7AAA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 158, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c106c778d4dfff7dee06ed88bc4e0ed34fc553aad67caf796f2a1c6487c1b2e877", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "6rwkj2JuCmPh64HEPUYaOaHbqIHrbuIVKwfDLXG89HA", + "y": "BgPKqLnTPbE69Exu--yKGY7WEkrJ6xfqr9KCSlRewAA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", + "wx": "009f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001", + "wy": "00f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEn3oTraFYpV+d3xpF8ETwc9m4ADDv3Pyf\nn1hBj7zq8AH4raAXUJD4DUcifWcTtnQPmgCR2IqDfQoc13tYqPKNcw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 159, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c14de459ef9159afa057feb3ec40fef01c45b809f4ab296ea48c206d4249a2b451", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "n3oTraFYpV-d3xpF8ETwc9m4ADDv3Pyfn1hBj7zq8AE", + "y": "-K2gF1CQ-A1HIn1nE7Z0D5oAkdiKg30KHNd7WKjyjXM", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", + "wx": "11c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4db", + "wy": "00bbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEcTz5GHNAZtcBuoM6kxAkMPMPjxdnzxt\nZbQ2gm2ptNu763p35Mv9ogcJfENCNwX3LIBHbaPaxApIOwqw8urRyw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 160, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1745d294978007302033502e1acc48b63ae6500be43adbea1b258d6b423dbb416", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "EcTz5GHNAZtcBuoM6kxAkMPMPjxdnzxtZbQ2gm2ptNs", + "y": "u-t6d-TL_aIHCXxDQjcF9yyAR22j2sQKSDsKsPLq0cs", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", + "wx": "00e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4", + "wy": "161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE4uGGgtUxI6oBpsXQCwxiPWcbRi6oC93W\nUif9UQWYiqQWGQez/SUESpSepByOLqhFncbxZUhWuLYbMVQ7sbRb2w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 161, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c17b2a785e3896f59b2d69da57648e80ad3c133a750a2847fd2098ccd902042b6c", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "4uGGgtUxI6oBpsXQCwxiPWcbRi6oC93WUif9UQWYiqQ", + "y": "FhkHs_0lBEqUnqQcji6oRZ3G8WVIVri2GzFUO7G0W9s", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", + "wx": "0090f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197da", + "wy": "00fadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkPjUynPeCKZWSq8AUke28P/peFBNzlJg\nX0a3w+Vhl9r62+Uo63DZ7n6g5wcC21T3IVFMe4YErCyyFPHey344PQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 162, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c171ae94a72ca896875e7aa4a4c3d29afdb4b35b6996273e63c47ac519256c5eb1", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "kPjUynPeCKZWSq8AUke28P_peFBNzlJgX0a3w-Vhl9o", + "y": "-tvlKOtw2e5-oOcHAttU9yFRTHuGBKwsshTx3st-OD0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", + "wx": "00824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e", + "wy": "3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEgkwZXHPP/fA40QG84Wh7XDthRvOVyIWX\nb3dTsjdrlI483vpvw0fRPk3LxjoLA6FlGAzSvhQxoM90zh6iUILSvA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 163, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10fa527fa7343c0bc9ec35a6278bfbff4d83301b154fc4bd14aee7eb93445b5f9", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "gkwZXHPP_fA40QG84Wh7XDthRvOVyIWXb3dTsjdrlI4", + "y": "PN76b8NH0T5Ny8Y6CwOhZRgM0r4UMaDPdM4eolCC0rw", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", + "wx": "2788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f", + "wy": "30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJ4ilLweOs/ICxPpz4NM4b6899r6FYANj\nb1mZItT1Jo8wtPIHyRm7315nqL5CZagXR1Szq6jxbldbd/9NWn62Tw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 164, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c16539c0adadd0525ff42622164ce9314348bd0863b4c80e936b23ca0414264671", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "J4ilLweOs_ICxPpz4NM4b6899r6FYANjb1mZItT1Jo8", + "y": "MLTyB8kZu99eZ6i-QmWoF0dUs6uo8W5XW3f_TVp-tk8", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", + "wx": "00d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b4150874", + "wy": "01b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1TO3iaSviQ+nqCofrljEBPmmKlC0mtr6\ns0nFE7QVCHQBtBcbgD52s0qYYeEPe8KJoGb9Ab0p+EyYehCl+xjC1A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 165, + "comment": "point at infinity during verify", + "flags": [ + "PointDuplication", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "1TO3iaSviQ-nqCofrljEBPmmKlC0mtr6s0nFE7QVCHQ", + "y": "AbQXG4A-drNKmGHhD3vCiaBm_QG9KfhMmHoQpfsYwtQ", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", + "wx": "3a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4", + "wy": "221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOjFQeYyK9p0ebpgfOkVAK6HXMvS+gzDF\nFk9J4Q7FVbQiG9hCvF5Nl+/zcWX2DjmYpCTXKkUM+V6kd8eCh9A0Og==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 166, + "comment": "edge case for signature malleability", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a07fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "OjFQeYyK9p0ebpgfOkVAK6HXMvS-gzDFFk9J4Q7FVbQ", + "y": "IhvYQrxeTZfv83Fl9g45mKQk1ypFDPlepHfHgofQNDo", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", + "wx": "3b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e80", + "wy": "0de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOzffX7NHxpoPF9hcDHyoNzaIOoJeExQ9\nD8/IEB6FHoAN48CQtsohulQ1FzMMBLEvlIxrrfFKY6v/3074x1NwJg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 167, + "comment": "edge case for signature malleability", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a07fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "OzffX7NHxpoPF9hcDHyoNzaIOoJeExQ9D8_IEB6FHoA", + "y": "DePAkLbKIbpUNRczDASxL5SMa63xSmOr_99O-MdTcCY", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", + "wx": "00feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82c", + "wy": "00e87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/rUWOw7OMP8+A8fVXEOA+i+oHuLANUlC\n/28IyZ0M2CzofeBe4b2gidPk4kj6D3IRAqz//fUOZUvigUM5md+Jfg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 168, + "comment": "u1 == 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "_rUWOw7OMP8-A8fVXEOA-i-oHuLANUlC_28IyZ0M2Cw", + "y": "6H3gXuG9oInT5OJI-g9yEQKs__31DmVL4oFDOZnfiX4", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", + "wx": "238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd4149228976", + "wy": "40683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEI4ztABzyK4hT4C7cicvspQULp+BCp6d/\nk4LNQUkiiXZAaD0wlGQ4QPKViQqkwYqjm0HXfdD7O7JwDk+ewoT/wg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 169, + "comment": "u1 == n - 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b844a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "I4ztABzyK4hT4C7cicvspQULp-BCp6d_k4LNQUkiiXY", + "y": "QGg9MJRkOEDylYkKpMGKo5tB133Q-zuycA5PnsKE_8I", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", + "wx": "00961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35e", + "wy": "00d2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElhz2SBfAbA5Rs8JzbJIv3hi9jEkG/Nf1\n72bEZ4UI817SxdGBaM++cPLxI710GSMruS3WkRPilBBhiJSBxaAnvw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 170, + "comment": "u2 == 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b855555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "lhz2SBfAbA5Rs8JzbJIv3hi9jEkG_Nf172bEZ4UI814", + "y": "0sXRgWjPvnDy8SO9dBkjK7kt1pET4pQQYYiUgcWgJ78", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", + "wx": "13681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b10288", + "wy": "16528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEE2gerhaM1Op88uKkXQUnQtEKn2TnloZ9\nvcuCn+CxAogWUodg0Xc3bAnfed45VXwynMF1NRes/+j6LsKYAmuDhA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 171, + "comment": "u2 == n - 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b89", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "E2gerhaM1Op88uKkXQUnQtEKn2TnloZ9vcuCn-CxAog", + "y": "FlKHYNF3N2wJ33neOVV8MpzBdTUXrP_o-i7CmAJrg4Q", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", + "wx": "5aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c2", + "wy": "0091c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWqer/ba0CG1UMyXl15xulc5C+GbSu4SQ\nljOgS7GqMcKRyACIeUkF4dozM22HTi+RzPRcxZGFvt5d1vP3rKrhiw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 172, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffce91e1ba6ba898620a46bcb51dc0b8b4ad1dc35dad892c4552d1847b2ce444637", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Wqer_ba0CG1UMyXl15xulc5C-GbSu4SQljOgS7GqMcI", + "y": "kcgAiHlJBeHaMzNth04vkcz0XMWRhb7eXdbz96yq4Ys", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", + "wx": "277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e4", + "wy": "64108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEACd3kbMFpFsrOVkLLwXTOSpsgYLO9OtU\nASDg9cIGw+RkEIIz+wuMOsiS15744Pv5LtEzrdtFVCcBMlhNxS7vQQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 173, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffce36bf0cec06d9b841da81332812f74f30bbaec9f202319206c6f0b8a0a400ff7", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "ACd3kbMFpFsrOVkLLwXTOSpsgYLO9OtUASDg9cIGw-Q", + "y": "ZBCCM_sLjDrIktee-OD7-S7RM63bRVQnATJYTcUu70E", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", + "wx": "6efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1a", + "wy": "00c75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbvoJK2jelGDwvMkZAFpfboDhnemJaL48\n0sdwqZSb+xrHXm5Qh9ZVDV+b6x555QKTB7wlUjXi1dyZJBrDq4hsSQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 174, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcea26b57af884b6c06e348efe139c1e4e9ec9518d60c340f6bac7d278ca08d8a6", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "bvoJK2jelGDwvMkZAFpfboDhnemJaL480sdwqZSb-xo", + "y": "x15uUIfWVQ1fm-seeeUCkwe8JVI14tXcmSQaw6uIbEk", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", + "wx": "72d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058", + "wy": "00e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEctShnE+dLPWEjqQERbcNRpa18C1jLAxl\nTMfX7rDG0FjoxM2ZQ+RZF0x6wB+nQhmOR+bBmmvbDE9sI3gxwbP5Qg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 175, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5b1d27a7694c146244a5ad0bd0636d9d9ef3b9fb58385418d9c982105077d1b7", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "ctShnE-dLPWEjqQERbcNRpa18C1jLAxlTMfX7rDG0Fg", + "y": "6MTNmUPkWRdMesAfp0IZjkfmwZpr2wxPbCN4McGz-UI", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", + "wx": "2a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e7402", + "wy": "58f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEKo6i9Q3M7QwhdXW9+nzUfRxvEABB7A41\nUSeUwb5+dAJY+MFxIu0wP9pxQ+tYvt5wKVtlMmYBOwsOvT8FMTf27A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 176, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcd27a7694c146244a5ad0bd0636d9e12abe687897e8e9998ddbd4e59a78520d0f", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Ko6i9Q3M7QwhdXW9-nzUfRxvEABB7A41USeUwb5-dAI", + "y": "WPjBcSLtMD_acUPrWL7ecClbZTJmATsLDr0_BTE39uw", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", + "wx": "0088de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b8", + "wy": "0c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiN5onOmvHpS+aiCJyKixJT/9u2yOnIYk\nm6IgABpK07gMSZjlSEL0E7ntsYJay7YzXoHk0YSysByL69yF0fKJRg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 177, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca4f4ed29828c4894b5a17a0c6db3c256c2221449228a92dff7d76ca8206dd8dd", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "iN5onOmvHpS-aiCJyKixJT_9u2yOnIYkm6IgABpK07g", + "y": "DEmY5UhC9BO57bGCWsu2M16B5NGEsrAci-vchdHyiUY", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", + "wx": "00fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7", + "wy": "00b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/qLTH3D5DV+z4A4YasQqs8FhXO5xTgtO\nETGz1NgiW/ewN6GN8qwVND8w90Bn3fKegX1fd/jc4FcU2lnAlPDNqQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 178, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc694c146244a5ad0bd0636d9e12bc9e09e60e68b90d0b5e6c5dddd0cb694d8799", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "_qLTH3D5DV-z4A4YasQqs8FhXO5xTgtOETGz1NgiW_c", + "y": "sDehjfKsFTQ_MPdAZ93ynoF9X3f43OBXFNpZwJTwzak", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", + "wx": "7258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db", + "wy": "17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcliRHj1CM0kWZHnb4Lg0Gvf70D0KfhDt\nzLNrbO6lo9sXrCuJknkRKPo7ltwvvUyjv6eC7ygy/GZWlD2xjnNGsA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 179, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3d7f487c07bfc5f30846938a3dcef696444707cf9677254a92b06c63ab867d22", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "cliRHj1CM0kWZHnb4Lg0Gvf70D0KfhDtzLNrbO6lo9s", + "y": "F6wriZJ5ESj6O5bcL71Mo7-ngu8oMvxmVpQ9sY5zRrA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", + "wx": "4f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914", + "wy": "00c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAETyhGHepkR01rs00Umcl9N7npVjPfHO7q\nrNRQFsmLORTIgYgQuMwG3bQOihJhxSj6pYlFXVpt+Tt3vF4OSTx0cA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 180, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6c7648fc0fbf8a06adb8b839f97b4ff7a800f11b1e37c593b261394599792ba4", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "TyhGHepkR01rs00Umcl9N7npVjPfHO7qrNRQFsmLORQ", + "y": "yIGIELjMBt20DooSYcUo-qWJRV1abfk7d7xeDkk8dHA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", + "wx": "74f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66", + "wy": "00eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEdPKoFPtdjsqRppteYHEnMrOTfeMoKb6X\nTte2jFwvXWbv8PB8VvmHplf0IZYgX1iMDx2W/YpjpfI4tI9Hh4j+Ow==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 181, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9be363a286f23f6322c205449d320baad417953ecb70f6214e90d49d7d1f26a8", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "dPKoFPtdjsqRppteYHEnMrOTfeMoKb6XTte2jFwvXWY", + "y": "7_DwfFb5h6ZX9CGWIF9YjA8dlv2KY6XyOLSPR4eI_js", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", + "wx": "195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6a", + "wy": "00b2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGVtRp8xKIbgnSnCpDed5gUw8jKNYMoII\nwJop8za4LWqyQWt8kv/9wpw7EoLdKnek0E3390UgRzk9hJmJxc7prQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 182, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc29798c5c45bdf58b4a7b2fdc2c46ab4af1218c7eeb9f0f27a88f1267674de3b0", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "GVtRp8xKIbgnSnCpDed5gUw8jKNYMoIIwJop8za4LWo", + "y": "skFrfJL__cKcOxKC3Sp3pNBN9_dFIEc5PYSZicXO6a0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", + "wx": "622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa", + "wy": "736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYi/HRzIDS+wt3zvBbTSz0fejJ90qjBm6\ntLtP46JLWKpzay8vrnb0367MkJYzOwEyjVHrP9qckifpDQtEmYPE8A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 183, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0b70f22ca2bb3cefadca1a5711fa3a59f4695385eb5aedf3495d0b6d00f8fd85", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Yi_HRzIDS-wt3zvBbTSz0fejJ90qjBm6tLtP46JLWKo", + "y": "c2svL6529N-uzJCWMzsBMo1R6z_anJIn6Q0LRJmDxPA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", + "wx": "1f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c7", + "wy": "0827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH3+FyvLXVQ56+bZQI+u03ONFAxFpIwnb\nJplpuDS2EccIJ/RbeAIOy7r0hP3Vv6rmhw8RhMIVgbr274K9e1MPkw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 184, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc16e1e459457679df5b9434ae23f474b3e8d2a70bd6b5dbe692ba16da01f1fb0a", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "H3-FyvLXVQ56-bZQI-u03ONFAxFpIwnbJplpuDS2Ecc", + "y": "CCf0W3gCDsu69IT91b-q5ocPEYTCFYG69u-CvXtTD5M", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", + "wx": "49c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377a", + "wy": "00efc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEScGX3ICtHaR6Q0K5OJPo4fsLuU/DOoPn\ng8ALJMeBN3rvwg2pK6x2KVH3JHS+zHNNTMIrqBuJXigv2sTfevDzfQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 185, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc2252d685e831b6cf095e4f0535eeaf0ddd3bfa91c210c9d9dc17224702eaf88f", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "ScGX3ICtHaR6Q0K5OJPo4fsLuU_DOoPng8ALJMeBN3o", + "y": "78INqSusdilR9yR0vsxzTUzCK6gbiV4oL9rE33rw830", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", + "wx": "00d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe", + "wy": "7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2MtoUXthalZACqOGhjXlS29plZii9hZ3\nV2VJgLr2rL5+yM9EnISaoDRhow762kFFPFfG5vvJO7xvpJrabcBVXA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 186, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc75135abd7c425b60371a477f09ce0f274f64a8c6b061a07b5d63e93c65046c53", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "2MtoUXthalZACqOGhjXlS29plZii9hZ3V2VJgLr2rL4", + "y": "fsjPRJyEmqA0YaMO-tpBRTxXxub7yTu8b6Sa2m3AVVw", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", + "wx": "030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3", + "wy": "00b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAwcT+2Pyqm/iyt8bIO/CWcd0Rdr6h9rD\nmLhAZco0ffOyJ4GN4aObWJywcdg+UxfMzcIzjlHjEv4x2Nw0pIAXUA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 187, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcd55555555555555555555555555555547c74934474db157d2a8c3f088aced62a", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "AwcT-2Pyqm_iyt8bIO_CWcd0Rdr6h9rDmLhAZco0ffM", + "y": "sieBjeGjm1icsHHYPlMXzM3CM45R4xL-MdjcNKSAF1A", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", + "wx": "00babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7", + "wy": "252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEurs2d7CVWALY6SmkE1VkDq8eoTU/incT\nMcSUbjSAr6clLxlsh+09KlnTsbVZE3/tABP+zvwZ+1qSaCubylG5UA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 188, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc1777c8853938e536213c02464a936000ba1e21c0fc62075d46c624e23b52f31", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "urs2d7CVWALY6SmkE1VkDq8eoTU_incTMcSUbjSAr6c", + "y": "JS8ZbIftPSpZ07G1WRN_7QAT_s78Gftakmgrm8pRuVA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", + "wx": "1aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60", + "wy": "00bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGqsgGHk0cREaig6bFD/eAvyVkgeW06Y9\n4ym0JDlvumC75BMHBRdHkkQbMY06ox3+hXeCHptEbsVz0nLgNsTr6Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 189, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc30bbb794db588363b40679f6c182a50d3ce9679acdd3ffbe36d7813dacbdc818", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "GqsgGHk0cREaig6bFD_eAvyVkgeW06Y94ym0JDlvumA", + "y": "u-QTBwUXR5JEGzGNOqMd_oV3gh6bRG7Fc9Jy4DbE6-k", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", + "wx": "008cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff", + "wy": "47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjLC5CUmcg+qAbNiFsd1GegEZ8GqIoCdu\nsM/aJ0U1qP9HtUKIM7w/LIv52QQRWM8zcYpplhzQFym8ABHR5YardQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 190, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc2c37fd995622c4fb7fffffffffffffffc7cee745110cb45ab558ed7c90c15a2f", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "jLC5CUmcg-qAbNiFsd1GegEZ8GqIoCdusM_aJ0U1qP8", + "y": "R7VCiDO8PyyL-dkEEVjPM3GKaZYc0BcpvAAR0eWGq3U", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", + "wx": "008f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d", + "wy": "3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjwPPGkInK7FTJyMJP3Lm/urIXhcA6fvp\npqLdZC10v107iacYna2M91/CL28ViqJ/nCygDaynhb4zWPK9o4YsoA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 191, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc7fd995622c4fb7ffffffffffffffffff5d883ffab5b32652ccdcaa290fccb97d", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "jwPPGkInK7FTJyMJP3Lm_urIXhcA6fvppqLdZC10v10", + "y": "O4mnGJ2tjPdfwi9vFYqif5wsoA2sp4W-M1jyvaOGLKA", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", + "wx": "44de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8ace", + "wy": "00a2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERN47nHpXqMnoIJUnU0IefZh7s9efcfAT\ngFyJfgGPis6iRgdYyPmNP9zhIalDZZ43LDJv/y5fwq5/o/edquE8Eg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 192, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcffb32ac4589f6ffffffffffffffffffebb107ff56b664ca599b954521f9972fa", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "RN47nHpXqMnoIJUnU0IefZh7s9efcfATgFyJfgGPis4", + "y": "okYHWMj5jT_c4SGpQ2WeNywyb_8uX8Kuf6P3narhPBI", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", + "wx": "6fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a", + "wy": "0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEb7iytI4zAxJorWpRdITciDnqkPZmnqDH\nrDIz4qwxOUoKyLvn9zwv9N+ZeHJ6wd/C/VhkfSDzH5kQUxa2RnHyBA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 193, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5622c4fb7fffffffffffffffffffffff928a8f1c7ac7bec1808b9f61c01ec327", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "b7iytI4zAxJorWpRdITciDnqkPZmnqDHrDIz4qwxOUo", + "y": "Csi75_c8L_TfmXhyesHfwv1YZH0g8x-ZEFMWtkZx8gQ", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", + "wx": "00bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6", + "wy": "00f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvqcRIqBIaT6QX/YCs8+d0Yr2m5/J2EMd\nKx3Sa5Qsleb0PHuLletiCCwS2529p/445Fy+SkiGkH+4G9sMXqkkbA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 194, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc44104104104104104104104104104103b87853fd3b7d3f8e175125b4382f25ed", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "vqcRIqBIaT6QX_YCs8-d0Yr2m5_J2EMdKx3Sa5QsleY", + "y": "9Dx7i5XrYggsEtudvaf-OORcvkpIhpB_uBvbDF6pJGw", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", + "wx": "00da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156", + "wy": "00e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2pGMcxugaiDLlO8zt3jpgaQEowXxlB/j\nNma0WwM1MVbiuyaU9XW0UYO+eOXJtSEL879Ij9TIKUUW2JVyyk9TkQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 195, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc2739ce739ce739ce739ce739ce739ce705560298d1f2f08dc419ac273a5b54d9", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "2pGMcxugaiDLlO8zt3jpgaQEowXxlB_jNma0WwM1MVY", + "y": "4rsmlPV1tFGDvnjlybUhC_O_SI_UyClFFtiVcspPU5E", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", + "wx": "3007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d", + "wy": "5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMAfpLDk32t55ZN+jWw7/Ax9+sCrtCgMU\nQREGzetw/j1adUb8BVKZeyDj1vQT514stm4RYyJpcRS3m6xzS/xNxQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 196, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcb777777777777777777777777777777688e6a1fe808a97a348671222ff16b863", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "MAfpLDk32t55ZN-jWw7_Ax9-sCrtCgMUQREGzetw_j0", + "y": "WnVG_AVSmXsg49b0E-deLLZuEWMiaXEUt5usc0v8TcU", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", + "wx": "60e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9b", + "wy": "00d2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYOc071Yk08vw3dN1ARvWY9bWrrxkTrWZ\n/fmNvc0YzpvS2Qs6wx8TmvgyzM9sy7ssbqEfqXNw3JkG2kdNfYp1Zw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 197, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6492492492492492492492492492492406dd3a19b8d5fb875235963c593bd2d3", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "YOc071Yk08vw3dN1ARvWY9bWrrxkTrWZ_fmNvc0Yzps", + "y": "0tkLOsMfE5r4MszPbMu7LG6hH6lzcNyZBtpHTX2KdWc", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", + "wx": "0085a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba337", + "wy": "69744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEhakA6XhY9pPAt9+iYeOA2tbqBG0fZd3u\n7dX32K8LozdpdE0VrdT2wLw7DaKuyTs0y4xl+TQN33TnsACe7szOPA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 198, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc955555555555555555555555555555547c74934474db157d2a8c3f088aced62c", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "hakA6XhY9pPAt9-iYeOA2tbqBG0fZd3u7dX32K8Lozc", + "y": "aXRNFa3U9sC8Ow2irsk7NMuMZfk0Dd9057AAnu7Mzjw", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", + "wx": "38066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046", + "wy": "00a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOAZvddiO/EyT3jb0ngN7I0zBix3lYIdQ\npiyrA0VAEEaj6EvtjPy4Ge9NVQRE8s5LZRdmtp4uKQH4iDb/kANP7Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 199, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b17", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "OAZvddiO_EyT3jb0ngN7I0zBix3lYIdQpiyrA0VAEEY", + "y": "o-hL7Yz8uBnvTVUERPLOS2UXZraeLikB-Ig2_5ADT-0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", + "wx": "0098f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabf", + "wy": "00a33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmPaBd9yVwbTL+lJFSIylI6fVYpRw0DXW\nIaRDxy85qr+jPSlUb6HGSPLH1cz3DPHOSrebXbGsBZ2+zQaNvf8biQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 200, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcbffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "mPaBd9yVwbTL-lJFSIylI6fVYpRw0DXWIaRDxy85qr8", + "y": "oz0pVG-hxkjyx9XM9wzxzkq3m12xrAWdvs0Gjb3_G4k", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", + "wx": "5c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277", + "wy": "00e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEXCu/ojybmtB/A4qom0kwvyZ9lAHkJV3p\n6NoKUHjsgnfj6IKjHV5qN54Hk5g8ze05uVxDU6sv8B6lNpukewwxkQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 201, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc185ddbca6dac41b1da033cfb60c152869e74b3cd66e9ffdf1b6bc09ed65ee40c", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "XCu_ojybmtB_A4qom0kwvyZ9lAHkJV3p6NoKUHjsgnc", + "y": "4-iCox1eajeeB5OYPM3tOblcQ1OrL_AepTabpHsMMZE", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", + "wx": "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", + "wy": "3547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4U1R4CCmESO215wGt6EzV+xrJVnul6Ptoprkz7EtcyEzA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 202, + "comment": "point duplication during verification", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "32b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcdad612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "LqcTNDIznGnSf5smcoG9Ld1fGdYzjUAKBc02R7FXo4U", + "y": "NUeAgphEjttecBrehM1fsayVZ7pej7aKa5M-xLXMhMw", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", + "wx": "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", + "wy": "00cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4XKuH99Z7txJKGP5SF7MqBOU2qYRaFwSXWUbME6SjN3Yw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 203, + "comment": "duplication bug", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "32b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcdad612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "LqcTNDIznGnSf5smcoG9Ld1fGdYzjUAKBc02R7FXo4U", + "y": "yrh_fWe7cSShj-UhezKgTlNqmEWhcEl1lGzBOkozd2M", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", + "wx": "008aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e", + "wy": "1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiqLGT6nGQ3Vjq/vL0AsgSNSMGMFSoqb0\nkDbedkfr6C4c5kOHmVxooGD6O8A5mwXMBu7H1Zj3UEGkkX5pK39R/w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 204, + "comment": "comparison with point at infinity ", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "55555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c033333333333333333333333333333332f222f8faefdb533f265d461c29a47373", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "iqLGT6nGQ3Vjq_vL0AsgSNSMGMFSoqb0kDbedkfr6C4", + "y": "HOZDh5lcaKBg-jvAOZsFzAbux9WY91BBpJF-aSt_Uf8", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", + "wx": "391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71f", + "wy": "00dd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEORQn/37ngBPBSux9lqigYiCSmKeDg16U\n/WVJ1QL/9x/dZiTsNDrZ/PTZhyGB5Z+EL5ukzMrgmmwJcvtqxrTGvQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 205, + "comment": "extreme value for k and edgecase s", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee555555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "ORQn_37ngBPBSux9lqigYiCSmKeDg16U_WVJ1QL_9x8", + "y": "3WYk7DQ62fz02YchgeWfhC-bpMzK4JpsCXL7asa0xr0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", + "wx": "00e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138e", + "wy": "00c1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE52K4ohm08YAhnMepBZJF5JYb0ZHAOJl4\nnHo0uJ6ME47BUz7wQZu3N24L/ekxnRCgaWh5HZ6g7tnBzmNFrtl1ng==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 206, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "52K4ohm08YAhnMepBZJF5JYb0ZHAOJl4nHo0uJ6ME44", + "y": "wVM-8EGbtzduC_3pMZ0QoGloeR2eoO7Zwc5jRa7ZdZ4", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", + "wx": "009aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952", + "wy": "00fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmu2w0oHbFk4TAADFaX+uDzBe+Ei+b/+0\nOsWT+7lQ6VL6b2MzWb3NgrVrC5+WWwN3idRrmoFBt5GyrvpxP5bBdQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 207, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee599999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "mu2w0oHbFk4TAADFaX-uDzBe-Ei-b_-0OsWT-7lQ6VI", + "y": "-m9jM1m9zYK1awufllsDd4nUa5qBQbeRsq76cT-WwXU", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", + "wx": "008ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee", + "wy": "1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEitRF22KBYmDk5of9GITki5/AY20DFUfW\nMxXnkuGb+u4d5k+Z1fHNi27Jyw94emVK6GmTuj2xAI70PP8GhMsivQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 208, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee566666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "itRF22KBYmDk5of9GITki5_AY20DFUfWMxXnkuGb-u4", + "y": "HeZPmdXxzYtuycsPeHplSuhpk7o9sQCO9Dz_BoTLIr0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", + "wx": "1f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32", + "wy": "00e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH1eZyVvokGOyTybkDLkowahop2+wCUYH\n6AQ9tAnJHDLnVyToE6QZHjqDkAfwji6Jc4iwbUoA3m3mDlNtkfq1Zg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 209, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee549249249249249249249249249249248c79facd43214c011123c1b03a93412a5", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "H1eZyVvokGOyTybkDLkowahop2-wCUYH6AQ9tAnJHDI", + "y": "51ck6BOkGR46g5AH8I4uiXOIsG1KAN5t5g5TbZH6tWY", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", + "wx": "00a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc", + "wy": "28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEozMaThtCI+wsAn7dSCySihTtNY2T8dQh\nfTmr9p/LXMwo1oTSqqvNY4N3XKpiOd4m1MaTe7YD7LQZYIL0z/1QnQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 210, + "comment": "extreme value for k", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee50eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "ozMaThtCI-wsAn7dSCySihTtNY2T8dQhfTmr9p_LXMw", + "y": "KNaE0qqrzWODd1yqYjneJtTGk3u2A-y0GWCC9M_9UJ0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", + "wx": "3f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb24818", + "wy": "5ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPzlSGZd0x885s4tmyxBCpiYNhoCAOEXk\n1DOtujuySBhepJW2jLx+1Bc+5jyQQtxQJiXH634h+wLKmpEU4KOhjQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 211, + "comment": "extreme value for k and edgecase s", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179855555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "PzlSGZd0x885s4tmyxBCpiYNhoCAOEXk1DOtujuySBg", + "y": "XqSVtoy8ftQXPuY8kELcUCYlx-t-IfsCypqRFOCjoY0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", + "wx": "00cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e", + "wy": "054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzfuMD0IuFE4TfCQSyGwXH1/j+j9bu1RO\nkHYojzzteG4FT9ByG3fBHHm+rLPJQhGwoZvaCGUu/q+SUTo7ChY2mA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 212, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "zfuMD0IuFE4TfCQSyGwXH1_j-j9bu1ROkHYojzzteG4", + "y": "BU_Qcht3wRx5vqyzyUIRsKGb2ghlLv6vklE6OwoWNpg", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", + "wx": "73598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3", + "wy": "00cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEc1mKahxoJ4+mv9DOQGTmgjW8HA9rIKko\nEIvjNnMPh+PLrmElGbUDLsyFrtgRJxqV/nk51dNGAUC6MY9NFKujHQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 213, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179899999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "c1mKahxoJ4-mv9DOQGTmgjW8HA9rIKkoEIvjNnMPh-M", + "y": "y65hJRm1Ay7Mha7YEScalf55OdXTRgFAujGPTRSrox0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", + "wx": "58debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a1", + "wy": "6773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWN69mn7iydWRMkeKVECuTV1+1Dcwg2n5\nLqhsghg/EKFnc+dvXtv02g5PG9/6wPVyV+HfpGWEKTEwmiQkX9pqXQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 214, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179866666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "WN69mn7iydWRMkeKVECuTV1-1Dcwg2n5Lqhsghg_EKE", + "y": "Z3Pnb17b9NoOTxvf-sD1clfh36RlhCkxMJokJF_aal0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", + "wx": "008b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b", + "wy": "00950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEi5BN5HlnNAxfjDVypyCSTvdXhjf+qxlJ\nrLJBpaasP1uVCQRJb5gksdY/MxO64huJ+uia/fyBG17OA/1aowGGTw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 215, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179849249249249249249249249249249248c79facd43214c011123c1b03a93412a5", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "i5BN5HlnNAxfjDVypyCSTvdXhjf-qxlJrLJBpaasP1s", + "y": "lQkESW-YJLHWPzMTuuIbifromv38gRtezgP9WqMBhk8", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", + "wx": "00f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a", + "wy": "346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE9IkrbVJcdx4DXyolJwjzeE5II4YEtPlN\nxW6qHlRtlBo0axqgvOaLHFDltS9Qn7VSLlwl4Ci8j4Y0Au23vK2LGw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 216, + "comment": "extreme value for k", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817980eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "9IkrbVJcdx4DXyolJwjzeE5II4YEtPlNxW6qHlRtlBo", + "y": "NGsaoLzmixxQ5bUvUJ-1Ui5cJeAovI-GNALtt7ytixs", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "wx": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "wy": "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 217, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + }, + { + "tcId": 218, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "44a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e2492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "eb5mfvncu6xVoGKVzocLBwKb_NstzijZWfKBWxb4F5g", + "y": "SDradyajxGVdpPv8DhEIqP0XtEimhVQZnEfQj_sQ1Lg", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", + "wx": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "wy": "00b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5i3xSWI2Vw7mqJbBAPx7vdXAuhLt1l6q+ZjuC9vBO8ndw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 219, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + }, + { + "tcId": 220, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "44a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e2492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "eb5mfvncu6xVoGKVzocLBwKb_NstzijZWfKBWxb4F5g", + "y": "t8UliNlcO5qiWwQD8e73VwLoS7dZeqvmY7gvbwTvJ3c", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "wx": "782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963", + "wy": "00af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeCyO0X47Kng7VGTzOwllKnHGeOBexR6E\n4rz8Zjo96WOvmstCgLjH98QvTvmrpiRewewXEv04oPqWQY2M1qphUg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 221, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "", + "sig": "f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dcb303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", + "result": "valid" + }, + { + "tcId": 222, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "4d7367", + "sig": "109cd8ae0374358984a8249c0a843628f2835ffad1df1a9a69aa2fe72355545cac6f00daf53bd8b1e34da329359b6e08019c5b037fed79ee383ae39f85a159c6", + "result": "valid" + }, + { + "tcId": 223, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "313233343030", + "sig": "d035ee1f17fdb0b2681b163e33c359932659990af77dca632012b30b27a057b31939d9f3b2858bc13e3474cb50e6a82be44faa71940f876c1cba4c3e989202b6", + "result": "valid" + }, + { + "tcId": 224, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "0000000000000000000000000000000000000000", + "sig": "4f053f563ad34b74fd8c9934ce59e79c2eb8e6eca0fef5b323ca67d5ac7ed2384d4b05daa0719e773d8617dce5631c5fd6f59c9bdc748e4b55c970040af01be5", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "eCyO0X47Kng7VGTzOwllKnHGeOBexR6E4rz8Zjo96WM", + "y": "r5rLQoC4x_fEL075q6YkXsHsFxL9OKD6lkGNjNaqYVI", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", + "wx": "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", + "wy": "01060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv8AAAABBgSS1aVnPg8l2NUPt+WMSdhtRtQhaVXgqj1A4Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 225, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "6d6a4f556ccce154e7fb9f19e76c3deca13d59cc2aeb4ecad968aab2ded4596553b9fa74803ede0fc4441bf683d56c564d3e274e09ccf47390badd1471c05fb7", + "result": "valid" + }, + { + "tcId": 226, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "aad503de9b9fd66b948e9acf596f0a0e65e700b28b26ec56e6e45e846489b3c4fff223c5d0765447e8447a3f9d31fd0696e89d244422022ff61a110b2a8c2f04", + "result": "valid" + }, + { + "tcId": 227, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "9182cebd3bb8ab572e167174397209ef4b1d439af3b200cdf003620089e43225abb88367d15fe62d1efffb6803da03109ee22e90bc9c78e8b4ed23630b82ea9d", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "boI1VUUpFAmRgsaywdbwtdKNUMzQBa8s4bulQapAyv8", + "y": "AAAAAQYEktWlZz4PJdjVD7fljEnYbUbUIWlV4Ko9QOE", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", + "wx": "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", + "wy": "00fffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv/////++fttKlqYwfDaJyrwSBpztieSuSvelqoeVcK7Tg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 228, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3854a3998aebdf2dbc28adac4181462ccac7873907ab7f212c42db0e69b56ed8c12c09475c772fd0c1b2060d5163e42bf71d727e4ae7c03eeba954bf50b43bb3", + "result": "valid" + }, + { + "tcId": 229, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "e94dbdc38795fe5c904d8f16d969d3b587f0a25d2de90b6d8c5c53ff887e3607856b8c963e9b68dade44750bf97ec4d11b1a0a3804f4cb79aa27bdea78ac14e4", + "result": "valid" + }, + { + "tcId": 230, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "49fc102a08ca47b60e0858cd0284d22cddd7233f94aaffbb2db1dd2cf08425e15b16fca5a12cdb39701697ad8e39ffd6bdec0024298afaa2326aea09200b14d6", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "boI1VUUpFAmRgsaywdbwtdKNUMzQBa8s4bulQapAyv8", + "y": "_____vn7bSpamMHw2icq8Egac7Ynkrkr3paqHlXCu04", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", + "wx": "013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0", + "wy": "00f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAAAAAT/SIkjWTZX3PCm0irSGMYUL5QP9\nAPhGi18PcOD27nqkO8LG/SWx2CaSQcvdnbsNrJbcliMfQwcF+DhxfQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 231, + "comment": "x-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "41efa7d3f05a0010675fcb918a45c693da4b348df21a59d6f9cd73e0d831d67abbab52596c1a1d9484296cdc92cbf07e665259a13791a8fe8845e2c07cf3fc67", + "result": "valid" + }, + { + "tcId": 232, + "comment": "x-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "b615698c358b35920dd883eca625a6c5f7563970cdfc378f8fe0cee17092144cda0b84cd94a41e049ef477aeac157b2a9bfa6b7ac8de06ed3858c5eede6ddd6d", + "result": "valid" + }, + { + "tcId": 233, + "comment": "x-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "87cf8c0eb82d44f69c60a2ff5457d3aaa322e7ec61ae5aecfd678ae1c1932b0ec522c4eea7eafb82914cbf5c1ff76760109f55ddddcf58274d41c9bc4311e06e", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "AAAAAT_SIkjWTZX3PCm0irSGMYUL5QP9APhGi18PcOA", + "y": "9u56pDvCxv0lsdgmkkHL3Z27DayW3JYjH0MHBfg4cX0", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", + "wx": "25afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dffffffff", + "wy": "00fa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJa/WiayrrtZ8Hylt5ZQG+MVQ9XFGoLTs\nLJeHbf/////6RqduUgMi37xJHsTwzBl0IPxOpYg9j23VPDVLxPZ8NQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 234, + "comment": "x-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "62f48ef71ace27bf5a01834de1f7e3f948b9dce1ca1e911d5e13d3b104471d82a1570cc0f388768d3ba7df7f212564caa256ff825df997f21f72f5280d53011f", + "result": "valid" + }, + { + "tcId": 235, + "comment": "x-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "f6b0e2f6fe020cf7c0c20137434344ed7add6c4be51861e2d14cbda472a6ffb49be93722c1a3ad7d4cf91723700cb5486de5479d8c1b38ae4e8e5ba1638e9732", + "result": "valid" + }, + { + "tcId": 236, + "comment": "x-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "db09d8460f05eff23bc7e436b67da563fa4b4edb58ac24ce201fa8a35812505746da116754602940c8999c8d665f786c50f5772c0a3cdbda075e77eabc64df16", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "Ja_WiayrrtZ8Hylt5ZQG-MVQ9XFGoLTsLJeHbf____8", + "y": "-kanblIDIt-8SR7E8MwZdCD8TqWIPY9t1Tw1S8T2fDU", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", + "wx": "00d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb9", + "wy": "3f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0S5sZrZ3NMPITSYBz1013Al+J2N/CspK\nT9t0tqrdO7k/W9/4i9VzbfiY5pkAbtdQ8RzwfFhmzXrXDHEh/////w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 237, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "592c41e16517f12fcabd98267674f974b588e9f35d35406c1a7bb2ed1d19b7b8c19a5f942607c3551484ff0dc97281f0cdc82bc48e2205a0645c0cf3d7f59da0", + "result": "valid" + }, + { + "tcId": 238, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "be0d70887d5e40821a61b68047de4ea03debfdf51cdf4d4b195558b959a032b28266b4d270e24414ecacb14c091a233134b918d37320c6557d60ad0a63544ac4", + "result": "valid" + }, + { + "tcId": 239, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "fae92dfcb2ee392d270af3a5739faa26d4f97bfd39ed3cbee4d29e26af3b206a93645c80605595e02c09a0dc4b17ac2a51846a728b3e8d60442ed6449fd3342b", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "0S5sZrZ3NMPITSYBz1013Al-J2N_CspKT9t0tqrdO7k", + "y": "P1vf-IvVc234mOaZAG7XUPEc8HxYZs161wxxIf____8", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", + "wx": "6d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000", + "wy": "00e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbUp/YNR3Sk8KqLve25U8fup5CUB+MWR1\nVmS8KAAAAADmWdNOTfONnoyeqt+6NmEsdpGVvobHeqw/NueLU4aA+w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 240, + "comment": "x-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "176a2557566ffa518b11226694eb9802ed2098bfe278e5570fe1d5d7af18a943ed6e2095f12a03f2eaf6718f430ec5fe2829fd1646ab648701656fd31221b97d", + "result": "valid" + }, + { + "tcId": 241, + "comment": "x-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "60be20c3dbc162dd34d26780621c104bbe5dace630171b2daef0d826409ee5c2bd8081b27762ab6e8f425956bf604e332fa066a99b59f87e27dc1198b26f5caa", + "result": "valid" + }, + { + "tcId": 242, + "comment": "x-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "edf03cf63f658883289a1a593d1007895b9f236d27c9c1f1313089aaed6b16aee5b22903f7eb23adc2e01057e39b0408d495f694c83f306f1216c9bf87506074", + "result": "valid" + } + ], + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "bUp_YNR3Sk8KqLve25U8fup5CUB-MWR1VmS8KAAAAAA", + "y": "5lnTTk3zjZ6MnqrfujZhLHaRlb6Gx3qsPzbni1OGgPs", + "kid": "none" + } + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "wx": "b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c9", + "wy": "2ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuVIIc0JLi3CZEEpaDrGsrEjhiXGZcbkT\nG/nKjCX0Nskv+AWzbkDWUf+3Vz7dm0mYwvL+OYkbrz2DZw6SQsDUrQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 243, + "comment": "r = 1, x = 1 is valid", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0415f0573de014498f1ee256977a7a21ce5663888d223f841b24495d599a2bd2dfaec48b59fbc8ce644a8d0e5feae572a9dce6d94ab5c1cc04ca5b3d82591aa640", + "wx": "15f0573de014498f1ee256977a7a21ce5663888d223f841b24495d599a2bd2df", + "wy": "aec48b59fbc8ce644a8d0e5feae572a9dce6d94ab5c1cc04ca5b3d82591aa640" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000415f0573de014498f1ee256977a7a21ce5663888d223f841b24495d599a2bd2dfaec48b59fbc8ce644a8d0e5feae572a9dce6d94ab5c1cc04ca5b3d82591aa640", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFfBXPeAUSY8e4laXenohzlZjiI0iP4Qb\nJEldWZor0t+uxItZ+8jOZEqNDl/q5XKp3ObZSrXBzATKWz2CWRqmQA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 244, + "comment": "r = 2, x = 1 is invalid", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "0000000000000000000000000000000000000000000000000000000000000002fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "wx": "b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c9", + "wy": "2ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuVIIc0JLi3CZEEpaDrGsrEjhiXGZcbkT\nG/nKjCX0Nskv+AWzbkDWUf+3Vz7dm0mYwvL+OYkbrz2DZw6SQsDUrQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 245, + "comment": "r = 1 + n, x = 1 is invalid; r was not reduced mod n", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b0fa79bc98baff15d39cf88f8343aea79c0df7f4265361e97a2428b355e460d78fa95eec6e2e02d72c259d20e0ca273468e83f36cee40eed76934c57354ca6a3", + "wx": "b0fa79bc98baff15d39cf88f8343aea79c0df7f4265361e97a2428b355e460d7", + "wy": "8fa95eec6e2e02d72c259d20e0ca273468e83f36cee40eed76934c57354ca6a3" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b0fa79bc98baff15d39cf88f8343aea79c0df7f4265361e97a2428b355e460d78fa95eec6e2e02d72c259d20e0ca273468e83f36cee40eed76934c57354ca6a3", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEsPp5vJi6/xXTnPiPg0Oup5wN9/QmU2Hp\neiQos1XkYNePqV7sbi4C1ywlnSDgyic0aOg/Ns7kDu12k0xXNUymow==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 246, + "comment": "r = n - 3, x = n - 2 is invalid", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413efffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0449be80da98fb7ea4165f898c36c696c50bd9da6485038c6cbda36d82dad41cfd64613a0e2c7224a85e29f774726b434e969db2d4765eafdf3c36004b7202ff3f", + "wx": "49be80da98fb7ea4165f898c36c696c50bd9da6485038c6cbda36d82dad41cfd", + "wy": "64613a0e2c7224a85e29f774726b434e969db2d4765eafdf3c36004b7202ff3f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000449be80da98fb7ea4165f898c36c696c50bd9da6485038c6cbda36d82dad41cfd64613a0e2c7224a85e29f774726b434e969db2d4765eafdf3c36004b7202ff3f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESb6A2pj7fqQWX4mMNsaWxQvZ2mSFA4xs\nvaNtgtrUHP1kYToOLHIkqF4p93Rya0NOlp2y1HZer988NgBLcgL/Pw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 247, + "comment": "r = 2, x = n + 2 is the smallest possible x with a reduction", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "0000000000000000000000000000000000000000000000000000000000000002fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04682cb28dfdcb3e72f200307a6146151338a7143914439c046980c805f0e9d12681d073c1b1dd129e3627d75d8a231a80342149abfcdd8ab9b5775fde215ab9a0", + "wx": "682cb28dfdcb3e72f200307a6146151338a7143914439c046980c805f0e9d126", + "wy": "81d073c1b1dd129e3627d75d8a231a80342149abfcdd8ab9b5775fde215ab9a0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004682cb28dfdcb3e72f200307a6146151338a7143914439c046980c805f0e9d12681d073c1b1dd129e3627d75d8a231a80342149abfcdd8ab9b5775fde215ab9a0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEaCyyjf3LPnLyADB6YUYVEzinFDkUQ5wE\naYDIBfDp0SaB0HPBsd0SnjYn112KIxqANCFJq/zdirm1d1/eIVq5oA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 248, + "comment": "r = 3, x = n + 2 is invalid", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "0000000000000000000000000000000000000000000000000000000000000003fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0493c9400c1fc5ed1aefb9f463e7650ae09778313fc188e84564e711a7b84588867e72afd2a40cd15f7b92c6ce7ea95dc7327e54a5309312f43628273534a86ae9", + "wx": "93c9400c1fc5ed1aefb9f463e7650ae09778313fc188e84564e711a7b8458886", + "wy": "7e72afd2a40cd15f7b92c6ce7ea95dc7327e54a5309312f43628273534a86ae9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000493c9400c1fc5ed1aefb9f463e7650ae09778313fc188e84564e711a7b84588867e72afd2a40cd15f7b92c6ce7ea95dc7327e54a5309312f43628273534a86ae9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEk8lADB/F7RrvufRj52UK4Jd4MT/BiOhF\nZOcRp7hFiIZ+cq/SpAzRX3uSxs5+qV3HMn5UpTCTEvQ2KCc1NKhq6Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 249, + "comment": "r = p - n + 1, x = 1 is invalid; r is too large to compare r + n with x", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "000000000000000000000000000000014551231950b75fc4402da1722fc9baeffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04e7ed253ac1810f174a83443264f57efbc090bb478a1fac8296f637b4694502a86f48fbb04579fa9e3bbce880915211b24de7f21511e3acf63ea49d737fc6459d", + "wx": "e7ed253ac1810f174a83443264f57efbc090bb478a1fac8296f637b4694502a8", + "wy": "6f48fbb04579fa9e3bbce880915211b24de7f21511e3acf63ea49d737fc6459d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004e7ed253ac1810f174a83443264f57efbc090bb478a1fac8296f637b4694502a86f48fbb04579fa9e3bbce880915211b24de7f21511e3acf63ea49d737fc6459d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE5+0lOsGBDxdKg0QyZPV++8CQu0eKH6yC\nlvY3tGlFAqhvSPuwRXn6nju86ICRUhGyTefyFRHjrPY+pJ1zf8ZFnQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 250, + "comment": "r = 2^256 - n + 1, x = 1 is invalid; r + n is too large to compare r + n with x, and overflows 2^256 bits", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "000000000000000000000000000000014551231950b75fc4402da1732fc9bec0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaP1363Verify", + "source": { + "name": "github/davidben/ecdsa-s-pow2", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04315971a60089e7749a8fa1d8374ecbaab259d773b3737e932bbaa960cdbf27f1bfe600bd60a91e650508eab795146b13c766195a447b24709df9d1c561e53dae", + "wx": "315971a60089e7749a8fa1d8374ecbaab259d773b3737e932bbaa960cdbf27f1", + "wy": "bfe600bd60a91e650508eab795146b13c766195a447b24709df9d1c561e53dae" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004315971a60089e7749a8fa1d8374ecbaab259d773b3737e932bbaa960cdbf27f1bfe600bd60a91e650508eab795146b13c766195a447b24709df9d1c561e53dae", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMVlxpgCJ53Saj6HYN07LqrJZ13Ozc36T\nK7qpYM2/J/G/5gC9YKkeZQUI6reVFGsTx2YZWkR7JHCd+dHFYeU9rg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 251, + "comment": "s = 2^128", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "2b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef220000000000000000000000000000000100000000000000000000000000000000", + "result": "valid" + }, + { + "tcId": 252, + "comment": "s = n - 2^128", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "2b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef22fffffffffffffffffffffffffffffffdbaaedce6af48a03bbfd25e8cd0364141", + "result": "valid" + } + ] + } + ] +} diff --git a/thoughts/ec-recover-opt/oracle/ecdsa_secp256k1_sha256_test.json b/thoughts/ec-recover-opt/oracle/ecdsa_secp256k1_sha256_test.json new file mode 100644 index 000000000..48797ce3b --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/ecdsa_secp256k1_sha256_test.json @@ -0,0 +1,7081 @@ +{ + "algorithm": "ECDSA", + "schema": "ecdsa_verify_schema_v1.json", + "numberOfTests": 476, + "header": [ + "Test vectors of type EcdsaVerify are meant for the verification", + "of ASN encoded ECDSA signatures." + ], + "notes": { + "ArithmeticError": { + "bugType": "EDGE_CASE", + "description": "Some implementations of ECDSA have arithmetic errors that occur when intermediate results have extreme values. This test vector has been constructed to test such occurrences.", + "cves": [ + "CVE-2017-18146" + ] + }, + "BerEncodedSignature": { + "bugType": "BER_ENCODING", + "description": "ECDSA signatures are usually DER encoded. This signature contains valid values for r and s, but it uses alternative BER encoding.", + "effect": "Accepting alternative BER encodings may be benign in some cases, or be an issue if protocol requires signature malleability.", + "cves": [ + "CVE-2020-14966", + "CVE-2020-13822", + "CVE-2019-14859", + "CVE-2016-1000342" + ] + }, + "EdgeCasePublicKey": { + "bugType": "EDGE_CASE", + "description": "The test vector uses a special case public key. " + }, + "EdgeCaseShamirMultiplication": { + "bugType": "EDGE_CASE", + "description": "Shamir proposed a fast method for computing the sum of two scalar multiplications efficiently. This test vector has been constructed so that an intermediate result is the point at infinity if Shamir's method is used." + }, + "IntegerOverflow": { + "bugType": "CAN_OF_WORMS", + "description": "The test vector contains an r and s that has been modified, so that the original value is restored if the implementation ignores the most significant bits.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "InvalidEncoding": { + "bugType": "CAN_OF_WORMS", + "description": "ECDSA signatures are encoded using ASN.1. This test vector contains an incorrectly encoded signature. The test vector itself was generated from a valid signature by modifying its encoding.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "InvalidSignature": { + "bugType": "AUTH_BYPASS", + "description": "The signature contains special case values such as r=0 and s=0. Buggy implementations may accept such values, if the implementation does not check boundaries and computes s^(-1) == 0.", + "effect": "Accepting such signatures can have the effect that an adversary can forge signatures without even knowing the message to sign.", + "cves": [ + "CVE-2022-21449", + "CVE-2021-43572", + "CVE-2022-24884" + ] + }, + "InvalidTypesInSignature": { + "bugType": "AUTH_BYPASS", + "description": "The signature contains invalid types. Dynamic typed languages sometime coerce such values of different types into integers. If an implementation is careless and has additional bugs, such as not checking integer boundaries then it may be possible that such signatures are accepted.", + "effect": "Accepting such signatures can have the effect that an adversary can forge signatures without even knowing the message to sign.", + "cves": [ + "CVE-2022-21449" + ] + }, + "MissingZero": { + "bugType": "LEGACY", + "description": "Some implementations of ECDSA and DSA incorrectly encode r and s by not including leading zeros in the ASN encoding of integers when necessary. Hence, some implementations (e.g. jdk) allow signatures with incorrect ASN encodings assuming that the signature is otherwise valid.", + "effect": "While signatures are more malleable if such signatures are accepted, this typically leads to no vulnerability, since a badly encoded signature can be reencoded correctly." + }, + "ModifiedInteger": { + "bugType": "CAN_OF_WORMS", + "description": "The test vector contains an r and s that has been modified. The goal is to check for arithmetic errors.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "ModifiedSignature": { + "bugType": "CAN_OF_WORMS", + "description": "The test vector contains an invalid signature that was generated from a valid signature by modifying it.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "ModularInverse": { + "bugType": "EDGE_CASE", + "description": "The test vectors contains a signature where computing the modular inverse of s hits an edge case.", + "effect": "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", + "cves": [ + "CVE-2019-0865" + ] + }, + "PointDuplication": { + "bugType": "EDGE_CASE", + "description": "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission.", + "cves": [ + "2020-12607", + "CVE-2015-2730" + ] + }, + "RangeCheck": { + "bugType": "CAN_OF_WORMS", + "description": "The test vector contains an r and s that has been modified. By adding or subtracting the order of the group (or other values) the test vector checks whether signature verification verifies the range of r and s.", + "effect": "Without further analysis it is unclear if the modification can be used to forge signatures." + }, + "SmallRandS": { + "bugType": "EDGE_CASE", + "description": "The test vectors contains a signature where both r and s are small integers. Some libraries cannot verify such signatures.", + "effect": "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", + "cves": [ + "2020-13895" + ] + }, + "SpecialCaseHash": { + "bugType": "EDGE_CASE", + "description": "The test vector contains a signature where the hash of the message is a special case, e.g., contains a long run of 0 or 1 bits." + }, + "ValidSignature": { + "bugType": "BASIC", + "description": "The test vector contains a valid signature that was generated pseudorandomly. Such signatures should not fail to verify unless some of the parameters (e.g. curve or hash function) are not supported." + } + }, + "testGroups": [ + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "wx": "782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963", + "wy": "00af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeCyO0X47Kng7VGTzOwllKnHGeOBexR6E\n4rz8Zjo96WOvmstCgLjH98QvTvmrpiRewewXEv04oPqWQY2M1qphUg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 1, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "", + "sig": "3046022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc022100b303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", + "result": "valid" + }, + { + "tcId": 2, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "4d7367", + "sig": "30450220109cd8ae0374358984a8249c0a843628f2835ffad1df1a9a69aa2fe72355545c022100ac6f00daf53bd8b1e34da329359b6e08019c5b037fed79ee383ae39f85a159c6", + "result": "valid" + }, + { + "tcId": 3, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "313233343030", + "sig": "3045022100d035ee1f17fdb0b2681b163e33c359932659990af77dca632012b30b27a057b302201939d9f3b2858bc13e3474cb50e6a82be44faa71940f876c1cba4c3e989202b6", + "result": "valid" + }, + { + "tcId": 4, + "comment": "pseudorandom signature", + "flags": [ + "ValidSignature" + ], + "msg": "0000000000000000000000000000000000000000", + "sig": "304402204f053f563ad34b74fd8c9934ce59e79c2eb8e6eca0fef5b323ca67d5ac7ed23802204d4b05daa0719e773d8617dce5631c5fd6f59c9bdc748e4b55c970040af01be5", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", + "wx": "00b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6f", + "wy": "00f0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\nA3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 5, + "comment": "signature malleability", + "flags": [ + "ValidSignature" + ], + "msg": "313233343030", + "sig": "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022100900e75ad233fcc908509dbff5922647db37c21f4afd3203ae8dc4ae7794b0f87", + "result": "valid" + }, + { + "tcId": 6, + "comment": "Legacy: ASN encoding of r misses leading 0", + "flags": [ + "MissingZero" + ], + "msg": "313233343030", + "sig": "30440220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 7, + "comment": "valid", + "flags": [ + "ValidSignature" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "valid" + }, + { + "tcId": 8, + "comment": "length of sequence [r, s] uses long form encoding", + "flags": [ + "BerEncodedSignature" + ], + "msg": "313233343030", + "sig": "308145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 9, + "comment": "length of sequence [r, s] contains a leading 0", + "flags": [ + "BerEncodedSignature" + ], + "msg": "313233343030", + "sig": "30820045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 10, + "comment": "length of sequence [r, s] uses 70 instead of 69", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 11, + "comment": "length of sequence [r, s] uses 68 instead of 69", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 12, + "comment": "uint32 overflow in length of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30850100000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 13, + "comment": "uint64 overflow in length of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3089010000000000000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 14, + "comment": "length of sequence [r, s] = 2**31 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30847fffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 15, + "comment": "length of sequence [r, s] = 2**31", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "308480000000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 16, + "comment": "length of sequence [r, s] = 2**32 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3084ffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 17, + "comment": "length of sequence [r, s] = 2**40 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3085ffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 18, + "comment": "length of sequence [r, s] = 2**64 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3088ffffffffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 19, + "comment": "incorrect length of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30ff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 20, + "comment": "replaced sequence [r, s] by an indefinite length tag without termination", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 21, + "comment": "removing sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "", + "result": "invalid" + }, + { + "tcId": 22, + "comment": "lonely sequence tag", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30", + "result": "invalid" + }, + { + "tcId": 23, + "comment": "appending 0's to sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 24, + "comment": "prepending 0's to sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "30470000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 25, + "comment": "appending unused 0's to sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 26, + "comment": "appending null value to sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", + "result": "invalid" + }, + { + "tcId": 27, + "comment": "prepending garbage to sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304a4981773045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 28, + "comment": "prepending garbage to sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304925003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 29, + "comment": "appending garbage to sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", + "result": "invalid" + }, + { + "tcId": 30, + "comment": "including undefined tags", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "304daa00bb00cd003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 31, + "comment": "including undefined tags", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304d2229aa00bb00cd00022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 32, + "comment": "including undefined tags", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652228aa00bb00cd0002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 33, + "comment": "truncated length of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3081", + "result": "invalid" + }, + { + "tcId": 34, + "comment": "including undefined tags to sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "304baa02aabb3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 35, + "comment": "using composition with indefinite length for sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "30803045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 36, + "comment": "using composition with wrong tag for sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "30803145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 37, + "comment": "Replacing sequence [r, s] with NULL", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "0500", + "result": "invalid" + }, + { + "tcId": 38, + "comment": "changing tag value of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "2e45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 39, + "comment": "changing tag value of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "2f45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 40, + "comment": "changing tag value of sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 41, + "comment": "changing tag value of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3245022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 42, + "comment": "changing tag value of sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "ff45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 43, + "comment": "dropping value of sequence [r, s]", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3000", + "result": "invalid" + }, + { + "tcId": 44, + "comment": "using composition for sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304930010230442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 45, + "comment": "truncated sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", + "result": "invalid" + }, + { + "tcId": 46, + "comment": "truncated sequence [r, s]", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 47, + "comment": "sequence [r, s] of size 4166 to check for overflows", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30821046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 48, + "comment": "indefinite length", + "flags": [ + "BerEncodedSignature" + ], + "msg": "313233343030", + "sig": "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 49, + "comment": "indefinite length with truncated delimiter", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba00", + "result": "invalid" + }, + { + "tcId": 50, + "comment": "indefinite length with additional element", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba05000000", + "result": "invalid" + }, + { + "tcId": 51, + "comment": "indefinite length with truncated element", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba060811220000", + "result": "invalid" + }, + { + "tcId": 52, + "comment": "indefinite length with garbage", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000fe02beef", + "result": "invalid" + }, + { + "tcId": 53, + "comment": "indefinite length with nonempty EOC", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0002beef", + "result": "invalid" + }, + { + "tcId": 54, + "comment": "prepend empty sequence", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "30473000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 55, + "comment": "append empty sequence", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba3000", + "result": "invalid" + }, + { + "tcId": 56, + "comment": "append zero", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba020100", + "result": "invalid" + }, + { + "tcId": 57, + "comment": "append garbage with high tag number", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31babf7f00", + "result": "invalid" + }, + { + "tcId": 58, + "comment": "append null with explicit tag", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31baa0020500", + "result": "invalid" + }, + { + "tcId": 59, + "comment": "append null with implicit tag", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31baa000", + "result": "invalid" + }, + { + "tcId": 60, + "comment": "sequence of sequence", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 61, + "comment": "truncated sequence: removed last 1 elements", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3023022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365", + "result": "invalid" + }, + { + "tcId": 62, + "comment": "repeating element in sequence", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3067022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 63, + "comment": "flipped bit 0 in r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 64, + "comment": "flipped bit 32 in r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccac983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 65, + "comment": "flipped bit 48 in r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5133ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 66, + "comment": "flipped bit 64 in r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc08b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 67, + "comment": "length of r uses long form encoding", + "flags": [ + "BerEncodedSignature" + ], + "msg": "313233343030", + "sig": "304602812100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 68, + "comment": "length of r contains a leading 0", + "flags": [ + "BerEncodedSignature" + ], + "msg": "313233343030", + "sig": "30470282002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 69, + "comment": "length of r uses 34 instead of 33", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 70, + "comment": "length of r uses 32 instead of 33", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 71, + "comment": "uint32 overflow in length of r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304a0285010000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 72, + "comment": "uint64 overflow in length of r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304e028901000000000000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 73, + "comment": "length of r = 2**31 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304902847fffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 74, + "comment": "length of r = 2**31", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304902848000000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 75, + "comment": "length of r = 2**32 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30490284ffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 76, + "comment": "length of r = 2**40 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304a0285ffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 77, + "comment": "length of r = 2**64 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304d0288ffffffffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 78, + "comment": "incorrect length of r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304502ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 79, + "comment": "replaced r by an indefinite length tag without termination", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045028000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 80, + "comment": "removing r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "302202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 81, + "comment": "lonely integer tag", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30230202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 82, + "comment": "lonely integer tag", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3024022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502", + "result": "invalid" + }, + { + "tcId": 83, + "comment": "appending 0's to r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 84, + "comment": "prepending 0's to r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30470223000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 85, + "comment": "appending unused 0's to r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 86, + "comment": "appending null value to r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 87, + "comment": "prepending garbage to r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304a2226498177022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 88, + "comment": "prepending garbage to r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304922252500022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 89, + "comment": "appending garbage to r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304d2223022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650004deadbeef02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 90, + "comment": "truncated length of r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3024028102206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 91, + "comment": "including undefined tags to r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304b2227aa02aabb022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 92, + "comment": "using composition with indefinite length for r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30492280022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 93, + "comment": "using composition with wrong tag for r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "30492280032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 94, + "comment": "Replacing r with NULL", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3024050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 95, + "comment": "changing tag value of r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 96, + "comment": "changing tag value of r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045012100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 97, + "comment": "changing tag value of r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 98, + "comment": "changing tag value of r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045042100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 99, + "comment": "changing tag value of r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045ff2100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 100, + "comment": "dropping value of r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3024020002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 101, + "comment": "using composition for r", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304922250201000220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 102, + "comment": "modifying first byte of r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045022102813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 103, + "comment": "modifying last byte of r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323e502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 104, + "comment": "truncated r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3044022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832302206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 105, + "comment": "r of size 4130 to check for overflows", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "308210480282102200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 106, + "comment": "leading ff in r", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "30460222ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 107, + "comment": "replaced r by infinity", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "302509018002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 108, + "comment": "replacing r with zero", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "302502010002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 109, + "comment": "flipped bit 0 in s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31bb", + "result": "invalid" + }, + { + "tcId": 110, + "comment": "flipped bit 32 in s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a456eb31ba", + "result": "invalid" + }, + { + "tcId": 111, + "comment": "flipped bit 48 in s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f713a556eb31ba", + "result": "invalid" + }, + { + "tcId": 112, + "comment": "flipped bit 64 in s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758001d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 113, + "comment": "length of s uses long form encoding", + "flags": [ + "BerEncodedSignature" + ], + "msg": "313233343030", + "sig": "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 114, + "comment": "length of s contains a leading 0", + "flags": [ + "BerEncodedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028200206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 115, + "comment": "length of s uses 33 instead of 32", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 116, + "comment": "length of s uses 31 instead of 32", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 117, + "comment": "uint32 overflow in length of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028501000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 118, + "comment": "uint64 overflow in length of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304e022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502890100000000000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 119, + "comment": "length of s = 2**31 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502847fffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 120, + "comment": "length of s = 2**31", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284800000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 121, + "comment": "length of s = 2**32 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284ffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 122, + "comment": "length of s = 2**40 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650285ffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 123, + "comment": "length of s = 2**64 - 1", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650288ffffffffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 124, + "comment": "incorrect length of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 125, + "comment": "replaced s by an indefinite length tag without termination", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502806ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 126, + "comment": "appending 0's to s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 127, + "comment": "prepending 0's to s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022200006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 128, + "comment": "appending null value to s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", + "result": "invalid" + }, + { + "tcId": 129, + "comment": "prepending garbage to s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222549817702206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 130, + "comment": "prepending garbage to s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652224250002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 131, + "comment": "appending garbage to s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", + "result": "invalid" + }, + { + "tcId": 132, + "comment": "truncated length of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281", + "result": "invalid" + }, + { + "tcId": 133, + "comment": "including undefined tags to s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "304b022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652226aa02aabb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 134, + "comment": "using composition with indefinite length for s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 135, + "comment": "using composition with wrong tag for s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228003206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", + "result": "invalid" + }, + { + "tcId": 136, + "comment": "Replacing s with NULL", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650500", + "result": "invalid" + }, + { + "tcId": 137, + "comment": "changing tag value of s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236500206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 138, + "comment": "changing tag value of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236501206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 139, + "comment": "changing tag value of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236503206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 140, + "comment": "changing tag value of s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236504206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 141, + "comment": "changing tag value of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365ff206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 142, + "comment": "dropping value of s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650200", + "result": "invalid" + }, + { + "tcId": 143, + "comment": "using composition for s", + "flags": [ + "InvalidEncoding" + ], + "msg": "313233343030", + "sig": "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222402016f021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 144, + "comment": "modifying first byte of s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206df18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 145, + "comment": "modifying last byte of s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb313a", + "result": "invalid" + }, + { + "tcId": 146, + "comment": "truncated s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", + "result": "invalid" + }, + { + "tcId": 147, + "comment": "truncated s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 148, + "comment": "s of size 4129 to check for overflows", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "30821048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028210216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "result": "invalid" + }, + { + "tcId": 149, + "comment": "leading ff in s", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 150, + "comment": "replaced s by infinity", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365090180", + "result": "invalid" + }, + { + "tcId": 151, + "comment": "replacing s with zero", + "flags": [ + "ModifiedSignature" + ], + "msg": "313233343030", + "sig": "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365020100", + "result": "invalid" + }, + { + "tcId": 152, + "comment": "replaced r by r + n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "3045022101813ef79ccefa9a56f7ba805f0e478583b90deabca4b05c4574e49b5899b964a602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 153, + "comment": "replaced r by r - n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "30440220813ef79ccefa9a56f7ba805f0e47858643b030ef461f1bcdf53fde3ef94ce22402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 154, + "comment": "replaced r by r + 256 * n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "304602220100813ef79ccefa9a56f7ba805f0e47843fad3bf4853e07f7c98770c99bffc4646502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 155, + "comment": "replaced r by -r", + "flags": [ + "ModifiedInteger" + ], + "msg": "313233343030", + "sig": "30450221ff7ec10863310565a908457fa0f1b87a7b01a0f22a0a9843f64aedc334367cdc9b02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 156, + "comment": "replaced r by n - r", + "flags": [ + "ModifiedInteger" + ], + "msg": "313233343030", + "sig": "304402207ec10863310565a908457fa0f1b87a79bc4fcf10b9e0e4320ac021c106b31ddc02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 157, + "comment": "replaced r by -n - r", + "flags": [ + "ModifiedInteger" + ], + "msg": "313233343030", + "sig": "30450221fe7ec10863310565a908457fa0f1b87a7c46f215435b4fa3ba8b1b64a766469b5a02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 158, + "comment": "replaced r by r + 2**256", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "3045022101813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 159, + "comment": "replaced r by r + 2**320", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "304d0229010000000000000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 160, + "comment": "replaced s by s + n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "30450221016ff18a52dcc0336f7af62400a6dd9b7fc1e197d8aebe203c96c87232272172fb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 161, + "comment": "replaced s by s - n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "30450221ff6ff18a52dcc0336f7af62400a6dd9b824c83de0b502cdfc51723b51886b4f07902206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 162, + "comment": "replaced s by s + 256 * n", + "flags": [ + "RangeCheck" + ], + "msg": "313233343030", + "sig": "3046022201006ff18a52dcc0336f7af62400a6dd9a3bb60fa1a14815bbc0a954a0758d2c72ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 163, + "comment": "replaced s by -s", + "flags": [ + "ModifiedInteger" + ], + "msg": "313233343030", + "sig": "30440220900e75ad233fcc908509dbff5922647ef8cd450e008a7fff2909ec5aa914ce4602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 164, + "comment": "replaced s by -n - s", + "flags": [ + "ModifiedInteger" + ], + "msg": "313233343030", + "sig": "30450221fe900e75ad233fcc908509dbff592264803e1e68275141dfc369378dcdd8de8d0502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 165, + "comment": "replaced s by s + 2**256", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "30450221016ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 166, + "comment": "replaced s by s - 2**256", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "30450221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 167, + "comment": "replaced s by s + 2**320", + "flags": [ + "IntegerOverflow" + ], + "msg": "313233343030", + "sig": "304d02290100000000000000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", + "result": "invalid" + }, + { + "tcId": 168, + "comment": "Signature with special case values r=0 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3006020100020100", + "result": "invalid" + }, + { + "tcId": 169, + "comment": "Signature with special case values r=0 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3006020100020101", + "result": "invalid" + }, + { + "tcId": 170, + "comment": "Signature with special case values r=0 and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30060201000201ff", + "result": "invalid" + }, + { + "tcId": 171, + "comment": "Signature with special case values r=0 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 172, + "comment": "Signature with special case values r=0 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 173, + "comment": "Signature with special case values r=0 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 174, + "comment": "Signature with special case values r=0 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 175, + "comment": "Signature with special case values r=0 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 176, + "comment": "Signature with special case values r=1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3006020101020100", + "result": "invalid" + }, + { + "tcId": 177, + "comment": "Signature with special case values r=1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3006020101020101", + "result": "invalid" + }, + { + "tcId": 178, + "comment": "Signature with special case values r=1 and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30060201010201ff", + "result": "invalid" + }, + { + "tcId": 179, + "comment": "Signature with special case values r=1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 180, + "comment": "Signature with special case values r=1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 181, + "comment": "Signature with special case values r=1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 182, + "comment": "Signature with special case values r=1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 183, + "comment": "Signature with special case values r=1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 184, + "comment": "Signature with special case values r=-1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30060201ff020100", + "result": "invalid" + }, + { + "tcId": 185, + "comment": "Signature with special case values r=-1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30060201ff020101", + "result": "invalid" + }, + { + "tcId": 186, + "comment": "Signature with special case values r=-1 and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30060201ff0201ff", + "result": "invalid" + }, + { + "tcId": 187, + "comment": "Signature with special case values r=-1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 188, + "comment": "Signature with special case values r=-1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 189, + "comment": "Signature with special case values r=-1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 190, + "comment": "Signature with special case values r=-1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 191, + "comment": "Signature with special case values r=-1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 192, + "comment": "Signature with special case values r=n and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020100", + "result": "invalid" + }, + { + "tcId": 193, + "comment": "Signature with special case values r=n and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101", + "result": "invalid" + }, + { + "tcId": 194, + "comment": "Signature with special case values r=n and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff", + "result": "invalid" + }, + { + "tcId": 195, + "comment": "Signature with special case values r=n and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 196, + "comment": "Signature with special case values r=n and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 197, + "comment": "Signature with special case values r=n and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 198, + "comment": "Signature with special case values r=n and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 199, + "comment": "Signature with special case values r=n and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 200, + "comment": "Signature with special case values r=n - 1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020100", + "result": "invalid" + }, + { + "tcId": 201, + "comment": "Signature with special case values r=n - 1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020101", + "result": "invalid" + }, + { + "tcId": 202, + "comment": "Signature with special case values r=n - 1 and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641400201ff", + "result": "invalid" + }, + { + "tcId": 203, + "comment": "Signature with special case values r=n - 1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 204, + "comment": "Signature with special case values r=n - 1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 205, + "comment": "Signature with special case values r=n - 1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 206, + "comment": "Signature with special case values r=n - 1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 207, + "comment": "Signature with special case values r=n - 1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 208, + "comment": "Signature with special case values r=n + 1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020100", + "result": "invalid" + }, + { + "tcId": 209, + "comment": "Signature with special case values r=n + 1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020101", + "result": "invalid" + }, + { + "tcId": 210, + "comment": "Signature with special case values r=n + 1 and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641420201ff", + "result": "invalid" + }, + { + "tcId": 211, + "comment": "Signature with special case values r=n + 1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 212, + "comment": "Signature with special case values r=n + 1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 213, + "comment": "Signature with special case values r=n + 1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 214, + "comment": "Signature with special case values r=n + 1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 215, + "comment": "Signature with special case values r=n + 1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 216, + "comment": "Signature with special case values r=p and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020100", + "result": "invalid" + }, + { + "tcId": 217, + "comment": "Signature with special case values r=p and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020101", + "result": "invalid" + }, + { + "tcId": 218, + "comment": "Signature with special case values r=p and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0201ff", + "result": "invalid" + }, + { + "tcId": 219, + "comment": "Signature with special case values r=p and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 220, + "comment": "Signature with special case values r=p and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 221, + "comment": "Signature with special case values r=p and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 222, + "comment": "Signature with special case values r=p and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 223, + "comment": "Signature with special case values r=p and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 224, + "comment": "Signature with special case values r=p + 1 and s=0", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020100", + "result": "invalid" + }, + { + "tcId": 225, + "comment": "Signature with special case values r=p + 1 and s=1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020101", + "result": "invalid" + }, + { + "tcId": 226, + "comment": "Signature with special case values r=p + 1 and s=-1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc300201ff", + "result": "invalid" + }, + { + "tcId": 227, + "comment": "Signature with special case values r=p + 1 and s=n", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "result": "invalid" + }, + { + "tcId": 228, + "comment": "Signature with special case values r=p + 1 and s=n - 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "result": "invalid" + }, + { + "tcId": 229, + "comment": "Signature with special case values r=p + 1 and s=n + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "result": "invalid" + }, + { + "tcId": 230, + "comment": "Signature with special case values r=p + 1 and s=p", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "result": "invalid" + }, + { + "tcId": 231, + "comment": "Signature with special case values r=p + 1 and s=p + 1", + "flags": [ + "InvalidSignature" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "result": "invalid" + }, + { + "tcId": 232, + "comment": "Signature encoding contains incorrect types: r=0, s=0.25", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3008020100090380fe01", + "result": "invalid" + }, + { + "tcId": 233, + "comment": "Signature encoding contains incorrect types: r=0, s=nan", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006020100090142", + "result": "invalid" + }, + { + "tcId": 234, + "comment": "Signature encoding contains incorrect types: r=0, s=True", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006020100010101", + "result": "invalid" + }, + { + "tcId": 235, + "comment": "Signature encoding contains incorrect types: r=0, s=False", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006020100010100", + "result": "invalid" + }, + { + "tcId": 236, + "comment": "Signature encoding contains incorrect types: r=0, s=Null", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201000500", + "result": "invalid" + }, + { + "tcId": 237, + "comment": "Signature encoding contains incorrect types: r=0, s=empyt UTF-8 string", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201000c00", + "result": "invalid" + }, + { + "tcId": 238, + "comment": "Signature encoding contains incorrect types: r=0, s=\"0\"", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060201000c0130", + "result": "invalid" + }, + { + "tcId": 239, + "comment": "Signature encoding contains incorrect types: r=0, s=empty list", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201003000", + "result": "invalid" + }, + { + "tcId": 240, + "comment": "Signature encoding contains incorrect types: r=0, s=list containing 0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30080201003003020100", + "result": "invalid" + }, + { + "tcId": 241, + "comment": "Signature encoding contains incorrect types: r=1, s=0.25", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3008020101090380fe01", + "result": "invalid" + }, + { + "tcId": 242, + "comment": "Signature encoding contains incorrect types: r=1, s=nan", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006020101090142", + "result": "invalid" + }, + { + "tcId": 243, + "comment": "Signature encoding contains incorrect types: r=1, s=True", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006020101010101", + "result": "invalid" + }, + { + "tcId": 244, + "comment": "Signature encoding contains incorrect types: r=1, s=False", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006020101010100", + "result": "invalid" + }, + { + "tcId": 245, + "comment": "Signature encoding contains incorrect types: r=1, s=Null", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201010500", + "result": "invalid" + }, + { + "tcId": 246, + "comment": "Signature encoding contains incorrect types: r=1, s=empyt UTF-8 string", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201010c00", + "result": "invalid" + }, + { + "tcId": 247, + "comment": "Signature encoding contains incorrect types: r=1, s=\"0\"", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060201010c0130", + "result": "invalid" + }, + { + "tcId": 248, + "comment": "Signature encoding contains incorrect types: r=1, s=empty list", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201013000", + "result": "invalid" + }, + { + "tcId": 249, + "comment": "Signature encoding contains incorrect types: r=1, s=list containing 0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30080201013003020100", + "result": "invalid" + }, + { + "tcId": 250, + "comment": "Signature encoding contains incorrect types: r=-1, s=0.25", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30080201ff090380fe01", + "result": "invalid" + }, + { + "tcId": 251, + "comment": "Signature encoding contains incorrect types: r=-1, s=nan", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060201ff090142", + "result": "invalid" + }, + { + "tcId": 252, + "comment": "Signature encoding contains incorrect types: r=-1, s=True", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060201ff010101", + "result": "invalid" + }, + { + "tcId": 253, + "comment": "Signature encoding contains incorrect types: r=-1, s=False", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060201ff010100", + "result": "invalid" + }, + { + "tcId": 254, + "comment": "Signature encoding contains incorrect types: r=-1, s=Null", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201ff0500", + "result": "invalid" + }, + { + "tcId": 255, + "comment": "Signature encoding contains incorrect types: r=-1, s=empyt UTF-8 string", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201ff0c00", + "result": "invalid" + }, + { + "tcId": 256, + "comment": "Signature encoding contains incorrect types: r=-1, s=\"0\"", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060201ff0c0130", + "result": "invalid" + }, + { + "tcId": 257, + "comment": "Signature encoding contains incorrect types: r=-1, s=empty list", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050201ff3000", + "result": "invalid" + }, + { + "tcId": 258, + "comment": "Signature encoding contains incorrect types: r=-1, s=list containing 0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30080201ff3003020100", + "result": "invalid" + }, + { + "tcId": 259, + "comment": "Signature encoding contains incorrect types: r=n, s=0.25", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090380fe01", + "result": "invalid" + }, + { + "tcId": 260, + "comment": "Signature encoding contains incorrect types: r=n, s=nan", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090142", + "result": "invalid" + }, + { + "tcId": 261, + "comment": "Signature encoding contains incorrect types: r=n, s=True", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141010101", + "result": "invalid" + }, + { + "tcId": 262, + "comment": "Signature encoding contains incorrect types: r=n, s=False", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141010100", + "result": "invalid" + }, + { + "tcId": 263, + "comment": "Signature encoding contains incorrect types: r=n, s=Null", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410500", + "result": "invalid" + }, + { + "tcId": 264, + "comment": "Signature encoding contains incorrect types: r=n, s=empyt UTF-8 string", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410c00", + "result": "invalid" + }, + { + "tcId": 265, + "comment": "Signature encoding contains incorrect types: r=n, s=\"0\"", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410c0130", + "result": "invalid" + }, + { + "tcId": 266, + "comment": "Signature encoding contains incorrect types: r=n, s=empty list", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641413000", + "result": "invalid" + }, + { + "tcId": 267, + "comment": "Signature encoding contains incorrect types: r=n, s=list containing 0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641413003020100", + "result": "invalid" + }, + { + "tcId": 268, + "comment": "Signature encoding contains incorrect types: r=p, s=0.25", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090380fe01", + "result": "invalid" + }, + { + "tcId": 269, + "comment": "Signature encoding contains incorrect types: r=p, s=nan", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090142", + "result": "invalid" + }, + { + "tcId": 270, + "comment": "Signature encoding contains incorrect types: r=p, s=True", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f010101", + "result": "invalid" + }, + { + "tcId": 271, + "comment": "Signature encoding contains incorrect types: r=p, s=False", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f010100", + "result": "invalid" + }, + { + "tcId": 272, + "comment": "Signature encoding contains incorrect types: r=p, s=Null", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0500", + "result": "invalid" + }, + { + "tcId": 273, + "comment": "Signature encoding contains incorrect types: r=p, s=empyt UTF-8 string", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0c00", + "result": "invalid" + }, + { + "tcId": 274, + "comment": "Signature encoding contains incorrect types: r=p, s=\"0\"", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0c0130", + "result": "invalid" + }, + { + "tcId": 275, + "comment": "Signature encoding contains incorrect types: r=p, s=empty list", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3000", + "result": "invalid" + }, + { + "tcId": 276, + "comment": "Signature encoding contains incorrect types: r=p, s=list containing 0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3003020100", + "result": "invalid" + }, + { + "tcId": 277, + "comment": "Signature encoding contains incorrect types: r=0.25, s=0.25", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "300a090380fe01090380fe01", + "result": "invalid" + }, + { + "tcId": 278, + "comment": "Signature encoding contains incorrect types: r=nan, s=nan", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006090142090142", + "result": "invalid" + }, + { + "tcId": 279, + "comment": "Signature encoding contains incorrect types: r=True, s=True", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006010101010101", + "result": "invalid" + }, + { + "tcId": 280, + "comment": "Signature encoding contains incorrect types: r=False, s=False", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006010100010100", + "result": "invalid" + }, + { + "tcId": 281, + "comment": "Signature encoding contains incorrect types: r=Null, s=Null", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "300405000500", + "result": "invalid" + }, + { + "tcId": 282, + "comment": "Signature encoding contains incorrect types: r=empyt UTF-8 string, s=empyt UTF-8 string", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30040c000c00", + "result": "invalid" + }, + { + "tcId": 283, + "comment": "Signature encoding contains incorrect types: r=\"0\", s=\"0\"", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060c01300c0130", + "result": "invalid" + }, + { + "tcId": 284, + "comment": "Signature encoding contains incorrect types: r=empty list, s=empty list", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "300430003000", + "result": "invalid" + }, + { + "tcId": 285, + "comment": "Signature encoding contains incorrect types: r=list containing 0, s=list containing 0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "300a30030201003003020100", + "result": "invalid" + }, + { + "tcId": 286, + "comment": "Signature encoding contains incorrect types: r=0.25, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3008090380fe01020100", + "result": "invalid" + }, + { + "tcId": 287, + "comment": "Signature encoding contains incorrect types: r=nan, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006090142020100", + "result": "invalid" + }, + { + "tcId": 288, + "comment": "Signature encoding contains incorrect types: r=True, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006010101020100", + "result": "invalid" + }, + { + "tcId": 289, + "comment": "Signature encoding contains incorrect types: r=False, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "3006010100020100", + "result": "invalid" + }, + { + "tcId": 290, + "comment": "Signature encoding contains incorrect types: r=Null, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050500020100", + "result": "invalid" + }, + { + "tcId": 291, + "comment": "Signature encoding contains incorrect types: r=empyt UTF-8 string, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30050c00020100", + "result": "invalid" + }, + { + "tcId": 292, + "comment": "Signature encoding contains incorrect types: r=\"0\", s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30060c0130020100", + "result": "invalid" + }, + { + "tcId": 293, + "comment": "Signature encoding contains incorrect types: r=empty list, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30053000020100", + "result": "invalid" + }, + { + "tcId": 294, + "comment": "Signature encoding contains incorrect types: r=list containing 0, s=0", + "flags": [ + "InvalidTypesInSignature" + ], + "msg": "313233343030", + "sig": "30083003020100020100", + "result": "invalid" + }, + { + "tcId": 295, + "comment": "Edge case for Shamir multiplication", + "flags": [ + "EdgeCaseShamirMultiplication" + ], + "msg": "3235353835", + "sig": "3045022100dd1b7d09a7bd8218961034a39a87fecf5314f00c4d25eb58a07ac85e85eab516022035138c401ef8d3493d65c9002fe62b43aee568731b744548358996d9cc427e06", + "result": "valid" + }, + { + "tcId": 296, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "343236343739373234", + "sig": "304502210095c29267d972a043d955224546222bba343fc1d4db0fec262a33ac61305696ae02206edfe96713aed56f8a28a6653f57e0b829712e5eddc67f34682b24f0676b2640", + "result": "valid" + }, + { + "tcId": 297, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "37313338363834383931", + "sig": "3045022028f94a894e92024699e345fe66971e3edcd050023386135ab3939d550898fb25022100cd69c1a42be05a6ee1270c821479251e134c21858d800bda6f4e98b37196238e", + "result": "valid" + }, + { + "tcId": 298, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130333539333331363638", + "sig": "3046022100be26b18f9549f89f411a9b52536b15aa270b84548d0e859a1952a27af1a77ac60221008f3e2b05632fc33715572af9124681113f2b84325b80154c044a544dc1a8fa12", + "result": "valid" + }, + { + "tcId": 299, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33393439343031323135", + "sig": "3046022100b1a4b1478e65cc3eafdf225d1298b43f2da19e4bcff7eacc0a2e98cd4b74b114022100e8655ce1cfb33ebd30af8ce8e8ae4d6f7b50cd3e22af51bf69e0a2851760d52b", + "result": "valid" + }, + { + "tcId": 300, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31333434323933303739", + "sig": "30440220325332021261f1bd18f2712aa1e2252da23796da8a4b1ff6ea18cafec7e171f2022040b4f5e287ee61fc3c804186982360891eaa35c75f05a43ecd48b35d984a6648", + "result": "valid" + }, + { + "tcId": 301, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33373036323131373132", + "sig": "3046022100a23ad18d8fc66d81af0903890cbd453a554cb04cdc1a8ca7f7f78e5367ed88a0022100dc1c14d31e3fb158b73c764268c8b55579734a7e2a2c9b5ee5d9d0144ef652eb", + "result": "valid" + }, + { + "tcId": 302, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "333433363838373132", + "sig": "304502202bdea41cda63a2d14bf47353bd20880a690901de7cd6e3cc6d8ed5ba0cdb1091022100c31599433036064073835b1e3eba8335a650c8fd786f94fe235ad7d41dc94c7a", + "result": "valid" + }, + { + "tcId": 303, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31333531353330333730", + "sig": "3046022100d7cd76ec01c1b1079eba9e2aa2a397243c4758c98a1ba0b7404a340b9b00ced6022100ca8affe1e626dd192174c2937b15bc48f77b5bdfe01f073a8aeaf7f24dc6c85b", + "result": "valid" + }, + { + "tcId": 304, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36353533323033313236", + "sig": "3045022100a872c744d936db21a10c361dd5c9063355f84902219652f6fc56dc95a7139d960220400df7575d9756210e9ccc77162c6b593c7746cfb48ac263c42750b421ef4bb9", + "result": "valid" + }, + { + "tcId": 305, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31353634333436363033", + "sig": "30460221009fa9afe07752da10b36d3afcd0fe44bfc40244d75203599cf8f5047fa3453854022100af1f583fec4040ae7e68c968d2bb4b494eec3a33edc7c0ccf95f7f75bc2569c7", + "result": "valid" + }, + { + "tcId": 306, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "34343239353339313137", + "sig": "3045022100885640384d0d910efb177b46be6c3dc5cac81f0b88c3190bb6b5f99c2641f2050220738ed9bff116306d9caa0f8fc608be243e0b567779d8dab03e8e19d553f1dc8e", + "result": "valid" + }, + { + "tcId": 307, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130393533323631333531", + "sig": "304502202d051f91c5a9d440c5676985710483bc4f1a6c611b10c95a2ff0363d90c2a45802210092206b19045a41a797cc2f3ac30de9518165e96d5b86341ecb3bcff231b3fd65", + "result": "valid" + }, + { + "tcId": 308, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35393837333530303431", + "sig": "3045022100f3ac2523967482f53d508522712d583f4379cd824101ff635ea0935117baa54f022027f10812227397e02cea96fb0e680761636dab2b080d1fc5d11685cbe8500cfe", + "result": "valid" + }, + { + "tcId": 309, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33343633303036383738", + "sig": "304602210096447cf68c3ab7266ed7447de3ac52fed7cc08cbdfea391c18a9b8ab370bc913022100f0a1878b2c53f16e70fe377a5e9c6e86f18ae480a22bb499f5b32e7109c07385", + "result": "valid" + }, + { + "tcId": 310, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "39383137333230323837", + "sig": "30450220530a0832b691da0b5619a0b11de6877f3c0971baaa68ed122758c29caaf46b7202210093761bb0a14ccf9f15b4b9ce73c6ec700bd015b8cb1cfac56837f4463f53074e", + "result": "valid" + }, + { + "tcId": 311, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33323232303431303436", + "sig": "30460221009c54c25500bde0b92d72d6ec483dc2482f3654294ca74de796b681255ed58a77022100988bac394a90ad89ce360984c0c149dcbd2684bb64498ace90bcf6b6af1c170e", + "result": "valid" + }, + { + "tcId": 312, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36363636333037313034", + "sig": "3045022100e7909d41439e2f6af29136c7348ca2641a2b070d5b64f91ea9da7070c7a2618b022042d782f132fa1d36c2c88ba27c3d678d80184a5d1eccac7501f0b47e3d205008", + "result": "valid" + }, + { + "tcId": 313, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31303335393531383938", + "sig": "304502205924873209593135a4c3da7bb381227f8a4b6aa9f34fe5bb7f8fbc131a039ffe022100e0e44ee4bbe370155bf0bbdec265bf9fe31c0746faab446de62e3631eacd111f", + "result": "valid" + }, + { + "tcId": 314, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31383436353937313935", + "sig": "3045022100eeb692c9b262969b231c38b5a7f60649e0c875cd64df88f33aa571fa3d29ab0e0220218b3a1eb06379c2c18cf51b06430786d1c64cd2d24c9b232b23e5bac7989acd", + "result": "valid" + }, + { + "tcId": 315, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33313336303436313839", + "sig": "3045022100a40034177f36091c2b653684a0e3eb5d4bff18e4d09f664c2800e7cafda1daf802203a3ec29853704e52031c58927a800a968353adc3d973beba9172cbbeab4dd149", + "result": "valid" + }, + { + "tcId": 316, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "32363633373834323534", + "sig": "3046022100b5d795cc75cea5c434fa4185180cd6bd21223f3d5a86da6670d71d95680dadbf022100ab1b277ef5ffe134460835e3d1402461ba104cb50b16f397fdc7a9abfefef280", + "result": "valid" + }, + { + "tcId": 317, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31363532313030353234", + "sig": "3044022007dc2478d43c1232a4595608c64426c35510051a631ae6a5a6eb1161e57e42e102204a59ea0fdb72d12165cea3bf1ca86ba97517bd188db3dbd21a5a157850021984", + "result": "valid" + }, + { + "tcId": 318, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35373438303831363936", + "sig": "3046022100ddd20c4a05596ca868b558839fce9f6511ddd83d1ccb53f82e5269d559a01552022100a46e8cb8d626cf6c00ddedc3b5da7e613ac376445ee260743f06f79054c7d42a", + "result": "valid" + }, + { + "tcId": 319, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36333433393133343638", + "sig": "30450221009cde6e0ede0a003f02fda0a01b59facfe5dec063318f279ce2de7a9b1062f7b702202886a5b8c679bdf8224c66f908fd6205492cb70b0068d46ae4f33a4149b12a52", + "result": "valid" + }, + { + "tcId": 320, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31353431313033353938", + "sig": "3046022100c5771016d0dd6357143c89f684cd740423502554c0c59aa8c99584f1ff38f609022100ab4bfa0bb88ab99791b9b3ab9c4b02bd2a57ae8dde50b9064063fcf85315cfe5", + "result": "valid" + }, + { + "tcId": 321, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130343738353830313238", + "sig": "3045022100a24ebc0ec224bd67ae397cbe6fa37b3125adbd34891abe2d7c7356921916dfe6022034f6eb6374731bbbafc4924fb8b0bdcdda49456d724cdae6178d87014cb53d8c", + "result": "valid" + }, + { + "tcId": 322, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130353336323835353638", + "sig": "304502202557d64a7aee2e0931c012e4fea1cd3a2c334edae68cdeb7158caf21b68e5a2402210080f93244956ffdc568c77d12684f7f004fa92da7e60ae94a1b98c422e23eda34", + "result": "valid" + }, + { + "tcId": 323, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "393533393034313035", + "sig": "3046022100c4f2eccbb6a24350c8466450b9d61b207ee359e037b3dcedb42a3f2e6dd6aeb5022100cd9c394a65d0aa322e391eb76b2a1a687f8620a88adef3a01eb8e4fb05b6477a", + "result": "valid" + }, + { + "tcId": 324, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "393738383438303339", + "sig": "3046022100eff04781c9cbcd162d0a25a6e2ebcca43506c523385cb515d49ea38a1b12fcad022100ea5328ce6b36e56ab87acb0dcfea498bcec1bba86a065268f6eff3c41c4b0c9c", + "result": "valid" + }, + { + "tcId": 325, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33363130363732343432", + "sig": "3046022100f58b4e3110a64bf1b5db97639ee0e5a9c8dfa49dc59b679891f520fdf0584c87022100d32701ae777511624c1f8abbf02b248b04e7a9eb27938f524f3e8828ba40164a", + "result": "valid" + }, + { + "tcId": 326, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31303534323430373035", + "sig": "3045022100f8abecaa4f0c502de4bf5903d48417f786bf92e8ad72fec0bd7fcb7800c0bbe302204c7f9e231076a30b7ae36b0cebe69ccef1cd194f7cce93a5588fd6814f437c0e", + "result": "valid" + }, + { + "tcId": 327, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35313734343438313937", + "sig": "304402205d5b38bd37ad498b2227a633268a8cca879a5c7c94a4e416bd0a614d09e606d2022012b8d664ea9991062ecbb834e58400e25c46007af84f6007d7f1685443269afe", + "result": "valid" + }, + { + "tcId": 328, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31393637353631323531", + "sig": "304402200c1cd9fe4034f086a2b52d65b9d3834d72aebe7f33dfe8f976da82648177d8e3022013105782e3d0cfe85c2778dec1a848b27ac0ae071aa6da341a9553a946b41e59", + "result": "valid" + }, + { + "tcId": 329, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33343437323533333433", + "sig": "3045022100ae7935fb96ff246b7b5d5662870d1ba587b03d6e1360baf47988b5c02ccc1a5b02205f00c323272083782d4a59f2dfd65e49de0693627016900ef7e61428056664b3", + "result": "valid" + }, + { + "tcId": 330, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "333638323634333138", + "sig": "3045022000a134b5c6ccbcefd4c882b945baeb4933444172795fa6796aae149067547098022100a991b9efa2db276feae1c115c140770901839d87e60e7ec45a2b81cf3b437be6", + "result": "valid" + }, + { + "tcId": 331, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33323631313938363038", + "sig": "304502202e4721363ad3992c139e5a1c26395d2c2d777824aa24fde075e0d7381171309d0221008bf083b6bbe71ecff22baed087d5a77eaeaf726bf14ace2c03fd6e37ba6c26f2", + "result": "valid" + }, + { + "tcId": 332, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "39363738373831303934", + "sig": "304502206852e9d3cd9fe373c2d504877967d365ab1456707b6817a042864694e1960ccf022100f9b4d815ebd4cf77847b37952334d05b2045cb398d4c21ba207922a7a4714d84", + "result": "valid" + }, + { + "tcId": 333, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "34393538383233383233", + "sig": "30440220188a8c5648dc79eace158cf886c62b5468f05fd95f03a7635c5b4c31f09af4c5022036361a0b571a00c6cd5e686ccbfcfa703c4f97e48938346d0c103fdc76dc5867", + "result": "valid" + }, + { + "tcId": 334, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "383234363337383337", + "sig": "3045022100a74f1fb9a8263f62fc4416a5b7d584f4206f3996bb91f6fc8e73b9e92bad0e1302206815032e8c7d76c3ab06a86f33249ce9940148cb36d1f417c2e992e801afa3fa", + "result": "valid" + }, + { + "tcId": 335, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3131303230383333373736", + "sig": "3045022007244865b72ff37e62e3146f0dc14682badd7197799135f0b00ade7671742bfe022100f27f3ddc7124b1b58579573a835650e7a8bad5eeb96e9da215cd7bf9a2a039ed", + "result": "valid" + }, + { + "tcId": 336, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "313333383731363438", + "sig": "3045022100da7fdd05b5badabd619d805c4ee7d9a84f84ddd5cf9c5bf4d4338140d689ef08022028f1cf4fa1c3c5862cfa149c0013cf5fe6cf5076cae000511063e7de25bb38e5", + "result": "valid" + }, + { + "tcId": 337, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "333232313434313632", + "sig": "3046022100d3027c656f6d4fdfd8ede22093e3c303b0133c340d615e7756f6253aea927238022100f6510f9f371b31068d68bfeeaa720eb9bbdc8040145fcf88d4e0b58de0777d2a", + "result": "valid" + }, + { + "tcId": 338, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3130363836363535353436", + "sig": "304402200bf6c0188dc9571cd0e21eecac5fbb19d2434988e9cc10244593ef3a98099f6902204864a562661f9221ec88e3dd0bc2f6e27ac128c30cc1a80f79ec670a22b042ee", + "result": "valid" + }, + { + "tcId": 339, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "3632313535323436", + "sig": "3045022100ae459640d5d1179be47a47fa538e16d94ddea5585e7a244804a51742c686443a02206c8e30e530a634fae80b3ceb062978b39edbe19777e0a24553b68886181fd897", + "result": "valid" + }, + { + "tcId": 340, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "37303330383138373734", + "sig": "304402201cf3517ba3bf2ab8b9ead4ebb6e866cb88a1deacb6a785d3b63b483ca02ac4950220249a798b73606f55f5f1c70de67cb1a0cff95d7dc50b3a617df861bad3c6b1c9", + "result": "valid" + }, + { + "tcId": 341, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "35393234353233373434", + "sig": "3045022100e69b5238265ea35d77e4dd172288d8cea19810a10292617d5976519dc5757cb802204b03c5bc47e826bdb27328abd38d3056d77476b2130f3df6ec4891af08ba1e29", + "result": "valid" + }, + { + "tcId": 342, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31343935353836363231", + "sig": "304402205f9d7d7c870d085fc1d49fff69e4a275812800d2cf8973e7325866cb40fa2b6f02206d1f5491d9f717a597a15fd540406486d76a44697b3f0d9d6dcef6669f8a0a56", + "result": "valid" + }, + { + "tcId": 343, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "34303035333134343036", + "sig": "304402200a7d5b1959f71df9f817146ee49bd5c89b431e7993e2fdecab6858957da685ae02200f8aad2d254690bdc13f34a4fec44a02fd745a422df05ccbb54635a8b86b9609", + "result": "valid" + }, + { + "tcId": 344, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "33303936343537353132", + "sig": "3044022079e88bf576b74bc07ca142395fda28f03d3d5e640b0b4ff0752c6d94cd553408022032cea05bd2d706c8f6036a507e2ab7766004f0904e2e5c5862749c0073245d6a", + "result": "valid" + }, + { + "tcId": 345, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "32373834303235363230", + "sig": "30450221009d54e037a00212b377bc8874798b8da080564bbdf7e07591b861285809d01488022018b4e557667a82bd95965f0706f81a29243fbdd86968a7ebeb43069db3b18c7f", + "result": "valid" + }, + { + "tcId": 346, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "32363138373837343138", + "sig": "304402202664f1ffa982fedbcc7cab1b8bc6e2cb420218d2a6077ad08e591ba9feab33bd022049f5c7cb515e83872a3d41b4cdb85f242ad9d61a5bfc01debfbb52c6c84ba728", + "result": "valid" + }, + { + "tcId": 347, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "31363432363235323632", + "sig": "304502205827518344844fd6a7de73cbb0a6befdea7b13d2dee4475317f0f18ffc81524b022100b0a334b1f4b774a5a289f553224d286d239ef8a90929ed2d91423e024eb7fa66", + "result": "valid" + }, + { + "tcId": 348, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "36383234313839343336", + "sig": "304602210097ab19bd139cac319325869218b1bce111875d63fb12098a04b0cd59b6fdd3a3022100bce26315c5dbc7b8cfc31425a9b89bccea7aa9477d711a4d377f833dcc28f820", + "result": "valid" + }, + { + "tcId": 349, + "comment": "special case hash", + "flags": [ + "SpecialCaseHash" + ], + "msg": "343834323435343235", + "sig": "3044022052c683144e44119ae2013749d4964ef67509278f6d38ba869adcfa69970e123d02203479910167408f45bda420a626ec9c4ec711c1274be092198b4187c018b562ca", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", + "wx": "07310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc362", + "wy": "26a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEBzEPkKnq4UmghAL1QZSg97SsQnv42b1s\ndoEHHcR9w2ImptN6xG1h/WAMC/G/+HaJ7RF92msOWTGK4BChl6JsoA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 350, + "comment": "k*G has a large x-coordinate", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "30360211014551231950b75fc4402da1722fc9baeb022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + }, + { + "tcId": 351, + "comment": "r too large", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", + "wx": "00bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22", + "wy": "705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvJfnWF7srUjhZoO8QJFwjhqTDGg/xHAB\n1LODWU8sTiJwWYnPadrq3U5OS4FR7YiN/sIPsBco2J1Ws/OPKunIxQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 352, + "comment": "r,s are large", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", + "wx": "44ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252", + "wy": "00b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERK0zmvvCHpq/e2AqXKU16jeBNbbRDYEx\nC92Ck9HfMlK2P/fQd0dw+P4dFyL6g6zQL0NOT8EQoMyPbd3TfVbEYw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 353, + "comment": "r and s^-1 have a large Hamming weight", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203e9a7582886089c62fb840cf3b83061cd1cff3ae4341808bb5bdee6191174177", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", + "wx": "1260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c", + "wy": "5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEmDCEiyeJE4a9RUb7eDDriO1TXxZaIHT\n7rrSHzfdh4xcmgwamt52c3qIEb1qf5KHyXjuOWqonBHkcinSzLVS8A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 354, + "comment": "r and s^-1 have a large Hamming weight", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022024238e70b431b1a64efdf9032669939d4b77f249503fc6905feb7540dea3e6d2", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", + "wx": "1877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce", + "wy": "00821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGHcEW+JdNKHQYA+dXADQZFoqVDebbO76\n0ua/XCozUs6CGlMswXUe4dNtQcPWq06bFD5E7EbXNHjqanmlwOVBWQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 355, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3006020101020101", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", + "wx": "455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50", + "wy": "00aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERVQ5/MPS3uzt3q7OYOe9FzBPNuu2Aq31\noi4Ljx20alCuw4+yuvIh6ajRiHx79iIt0YNGNOdyYzFa9tI2CdBPdw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 356, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3006020101020102", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", + "wx": "2e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece718", + "wy": "0449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELh9GawJMDDrOJDfeCRJ/7QS3BvlLGaIb\nscKs81zs5xgESa41I9clNOlklyz9OzivC93ZYZ5a8iPk0aQPNM+fHQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 357, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3006020101020103", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", + "wx": "008e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a23373", + "wy": "26ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjnq9u9GN50UjdMGHmhw7AdEyYefUVxw7\nR6HHbFWiM3Mm7Yl81Rek9TSduAl4D20vK59imdi1qJB38RGacY/Xsw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 358, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3006020102020101", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", + "wx": "7b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af19", + "wy": "42117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEezM9Q0DT1xjdPmr/fee7+Lcr/WFshCAF\nYFKEI3a5rxlCEXxa/qx1XW83b8Yymn12BRuHEjpKXQvEpTk4DwPeew==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 359, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3006020102020102", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", + "wx": "00d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e5", + "wy": "03a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0wykoN22YWyFHTDO1oLED4PGJ1ih8nWZ\niNZ2OojxwOUDqA1UFWUNQSOXhOji+xI16f6ZHREuu4EYbL8Not46/w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 360, + "comment": "small r and s", + "flags": [ + "SmallRandS", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3006020102020103", + "result": "valid" + }, + { + "tcId": 361, + "comment": "r is larger than n", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143020103", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", + "wx": "48969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24", + "wy": "00b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESJabOZkSl7MyplLT7m4B6QmzmQTnH6I1\nSngwx3ULryS0AS0bgw0ZnMsfyXKzK/3tVfCc1i0lfl6ETiflehWU7A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 362, + "comment": "s is larger than n", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3026020102022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd04917c8", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", + "wx": "02ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee77", + "wy": "7eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAu9NbWz9WpTx13hCJuPipsCkNsVYOWGf\nOPtEcrX57nd+tKzU7r2lzXKHX/0qLyYinC3GtGUAkZpDLIZznzroZg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 363, + "comment": "small r and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "302702020101022100c58b162c58b162c58b162c58b162c58a1b242973853e16db75c8a1a71da4d39d", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", + "wx": "464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584", + "wy": "00b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERk9P9xVynK5Qcso72AHTGVtnrsZemwGq\n0gopQ9y8tYSxr9KdMaOaEdVwqhWXQ5s7LRlxvy8avxVDLQIHsQ0dCA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 364, + "comment": "smallish r and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "302c02072d9b4d347952cc022100fcbc5103d0da267477d1791461cf2aa44bf9d43198f79507bd8779d69a13108e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", + "wx": "157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4c", + "wy": "00deadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFX+P3fNz619Jz88Q2LhTz5HLzX1mXDUi\nun3XON23mkzerfGlxEjqPJ9BkaiZmr/MdXrG1kVn7wcsR/7GE0Q7jw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 365, + "comment": "100-bit r and small s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3032020d1033e67e37b32b445580bf4efc022100906f906f906f906f906f906f906f906ed8e426f7b1968c35a204236a579723d2", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", + "wx": "0934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0", + "wy": "00d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECTSlN0ZsB0MOLEj+uZC7Gft4zsyc7kJO\npNEwKRqiN/DU+S0jtGKAS1toxSVYwByZltv3J/zKu+7bliGkAFNa+g==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 366, + "comment": "small r and 100 bit s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3026020201010220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", + "wx": "00d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c65", + "wy": "4a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1u8gvmbIk/dBqb+Q2bdGddHCoxKWOXrL\nPvF0/QswDGVKDJVHjKADmRYtfw8tyJ79wrKKMPur4oWFcpWksMTiZQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 367, + "comment": "100-bit r and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3031020d062522bbd3ecbe7c39e93e7c260220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", + "wx": "00b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee06", + "wy": "29c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEtykdFATgwMB9q5NyGJ9L1Y0s6qjRXt5U\nTZUUVFup7gYpyaY9XjCHacww7CdqQQ5kZKJ+6v2eWZ2xDwU6T+SoKQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 368, + "comment": "r and s^-1 are close to n", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c1022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", + "wx": "6e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8", + "wy": "186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbigwMwXWQsy5I7ci6oayoLyONzXssm6E\nmxnJ92sv27gYboDWTYyrFk9SOPUxhGG/idTZbuZUTIFsdWaUd3Tg9g==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 369, + "comment": "r and s are 64-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "30160209009c44febf31c3594d020900839ed28247c2b06b", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", + "wx": "375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9", + "wy": "00a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEN1vak/avkvtfj0sbXwU047r6s0y3rZ+5\n0Lci5KXDAqmgC584elo5YJeqIWL8W7z0pSYzcvaByU2lHpeZEgmQ/Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 370, + "comment": "r and s are 100-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "301e020d09df8b682430beef6f5fd7c7cf020d0fd0a62e13778f4222a0d61c8a", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", + "wx": "00d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197", + "wy": "00da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE11toIWur4DriV+lLTjvxxS9E498mbRUk\n/4xepp2nMZfaS/+e0cU/RJF6Z9e5eFmOid81nj1ZE+rqJPOuJZq8RA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 371, + "comment": "r and s are 128-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "30260211008a598e563a89f526c32ebec8de26367a02110084f633e2042630e99dd0f1e16f7a04bf", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", + "wx": "78bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653", + "wy": "118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeLzaFArtI9QwyyPD3A0B9CPbE07pSjqM\ntIPy3qwqxlMRgRT28zBF1OntkQcIUAe/vd+PWP56GiRF1mqZAEVHbg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 372, + "comment": "r and s are 160-bit integer", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "302e021500aa6eeb5823f7fa31b466bb473797f0d0314c0bdf021500e2977c479e6d25703cebbc6bd561938cc9d1bfb9", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", + "wx": "00bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c", + "wy": "1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEu3n2GFf3Q7+htucRHOQJQ3claWnk4VFZ\nEj2VSKzDvmwfnZ+IYNz/0+s23Wwx/y5yJsIAnEyU2NfStWhr96vWdw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 373, + "comment": "s == 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020101", + "result": "valid" + }, + { + "tcId": 374, + "comment": "s == 0", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020100", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", + "wx": "0093591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36", + "wy": "073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEk1kYJ9nmcTtOn66mLHKyjf76aODAUWC1\n1qroj9LjbDYHP1VFrVr0EK8mr/9oZUz3LUXkk0iTESAyRzR6iQ9FGA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 375, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220419d981c515af8cc82545aac0c85e9e308fbb2eab6acd7ed497e0b4145a18fd9", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", + "wx": "31ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0da", + "wy": "00da01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMe0wga7+AB62QCBp7izMGGKTe4WZUUTb\nqVA5Q1h78NraAbjMTfNPWrOxo1lhUgiUbl7jX5jud1uMzs2GzMFlDw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 376, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102201b21717ad71d23bbac60a9ad0baf75b063c9fdf52a00ebf99d022172910993c9", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", + "wx": "7dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea8", + "wy": "54c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEff9m+phQn/Pi5RBF9DkFI9zNpDo7wohe\nWMJICQmQ7qhUx2wrmt62u1cYI+B/18ZchjnPnZBSYAZMjnZ1zm2YtA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 377, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102202f588f66018f3dd14db3e28e77996487e32486b521ed8e5a20f06591951777e9", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", + "wx": "4280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a", + "wy": "2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEQoBQmqtk7fwLSiln5MvOhJy1ROSncxPI\n5uzlefvXQgouif5cwZJ9VU5qO7FAM+p8kizXXLosdBX9q1LyCxhg8Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 378, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220091a08870ff4daf9123b30c20e8c4fc8505758dcf4074fcaff2170c9bfcf74f4", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", + "wx": "4f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb", + "wy": "2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAET43xRRlOPE/D7qJtQ851tALWsXRy3cuy\nVLinmwvz2csqog2ChEyyZjROccp48q0np1oJ5bwPpX5O/Z1GWgiI2w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 379, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102207c370dc0ce8c59a8b273cba44a7c1191fc3186dc03cab96b0567312df0d0b250", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", + "wx": "009598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14", + "wy": "122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElZilfdZ+w+FrWHoziqOhCjo5E7QaOvMu\nPtP/ATWMaxQSKBnt+AdLvFIffUzc6C/velFnBq/7odk9neqcyuGiBw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 380, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022070b59a7d1ee77a2f9e0491c2a7cfcd0ed04df4a35192f6132dcc668c79a6160e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", + "wx": "009171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e", + "wy": "634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkXH+w8oggGvAhPEvB2CRG2CZC9gOWypx\nygOgSLIPg35jT9F4Y3YbKVjSvk4Un409ervcGL4D9FGrbBf6Ch+DMA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 381, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102202736d76e412246e097148e2bf62915614eb7c428913a58eb5e9cd4674a9423de", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", + "wx": "777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9", + "wy": "00ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEd3yJMLbh0nEQD+aM6T8WP6N2EsX/9n9K\nYvw7r689F6ntc9hvYKUbXtkTU6OwVO3AqpLJ68vQt10Yj9yIJ5HWjQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 382, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102204a1e12831fbe93627b02d6e7f24bccdd6ef4b2d0f46739eaf3b1eaf0ca117770", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", + "wx": "00eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf470", + "wy": "0603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE6rwkj2JuCmPh64HEPUYaOaHbqIHrbuIV\nKwfDLXG89HAGA8qoudM9sTr0TG777IoZjtYSSsnrF+qv0oJKVF7AAA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 383, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022006c778d4dfff7dee06ed88bc4e0ed34fc553aad67caf796f2a1c6487c1b2e877", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", + "wx": "009f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001", + "wy": "00f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEn3oTraFYpV+d3xpF8ETwc9m4ADDv3Pyf\nn1hBj7zq8AH4raAXUJD4DUcifWcTtnQPmgCR2IqDfQoc13tYqPKNcw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 384, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102204de459ef9159afa057feb3ec40fef01c45b809f4ab296ea48c206d4249a2b451", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", + "wx": "11c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4db", + "wy": "00bbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEcTz5GHNAZtcBuoM6kxAkMPMPjxdnzxt\nZbQ2gm2ptNu763p35Mv9ogcJfENCNwX3LIBHbaPaxApIOwqw8urRyw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 385, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220745d294978007302033502e1acc48b63ae6500be43adbea1b258d6b423dbb416", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", + "wx": "00e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4", + "wy": "161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE4uGGgtUxI6oBpsXQCwxiPWcbRi6oC93W\nUif9UQWYiqQWGQez/SUESpSepByOLqhFncbxZUhWuLYbMVQ7sbRb2w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 386, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102207b2a785e3896f59b2d69da57648e80ad3c133a750a2847fd2098ccd902042b6c", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", + "wx": "0090f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197da", + "wy": "00fadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkPjUynPeCKZWSq8AUke28P/peFBNzlJg\nX0a3w+Vhl9r62+Uo63DZ7n6g5wcC21T3IVFMe4YErCyyFPHey344PQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 387, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022071ae94a72ca896875e7aa4a4c3d29afdb4b35b6996273e63c47ac519256c5eb1", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", + "wx": "00824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e", + "wy": "3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEgkwZXHPP/fA40QG84Wh7XDthRvOVyIWX\nb3dTsjdrlI483vpvw0fRPk3LxjoLA6FlGAzSvhQxoM90zh6iUILSvA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 388, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102200fa527fa7343c0bc9ec35a6278bfbff4d83301b154fc4bd14aee7eb93445b5f9", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", + "wx": "2788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f", + "wy": "30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJ4ilLweOs/ICxPpz4NM4b6899r6FYANj\nb1mZItT1Jo8wtPIHyRm7315nqL5CZagXR1Szq6jxbldbd/9NWn62Tw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 389, + "comment": "edge case modular inverse", + "flags": [ + "ModularInverse", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102206539c0adadd0525ff42622164ce9314348bd0863b4c80e936b23ca0414264671", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", + "wx": "00d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b4150874", + "wy": "01b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1TO3iaSviQ+nqCofrljEBPmmKlC0mtr6\ns0nFE7QVCHQBtBcbgD52s0qYYeEPe8KJoGb9Ab0p+EyYehCl+xjC1A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 390, + "comment": "point at infinity during verify", + "flags": [ + "PointDuplication", + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", + "wx": "3a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4", + "wy": "221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOjFQeYyK9p0ebpgfOkVAK6HXMvS+gzDF\nFk9J4Q7FVbQiG9hCvF5Nl+/zcWX2DjmYpCTXKkUM+V6kd8eCh9A0Og==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 391, + "comment": "edge case for signature malleability", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", + "wx": "3b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e80", + "wy": "0de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOzffX7NHxpoPF9hcDHyoNzaIOoJeExQ9\nD8/IEB6FHoAN48CQtsohulQ1FzMMBLEvlIxrrfFKY6v/3074x1NwJg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 392, + "comment": "edge case for signature malleability", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", + "wx": "00feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82c", + "wy": "00e87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/rUWOw7OMP8+A8fVXEOA+i+oHuLANUlC\n/28IyZ0M2CzofeBe4b2gidPk4kj6D3IRAqz//fUOZUvigUM5md+Jfg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 393, + "comment": "u1 == 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", + "wx": "238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd4149228976", + "wy": "40683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEI4ztABzyK4hT4C7cicvspQULp+BCp6d/\nk4LNQUkiiXZAaD0wlGQ4QPKViQqkwYqjm0HXfdD7O7JwDk+ewoT/wg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 394, + "comment": "u1 == n - 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", + "wx": "00961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35e", + "wy": "00d2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElhz2SBfAbA5Rs8JzbJIv3hi9jEkG/Nf1\n72bEZ4UI817SxdGBaM++cPLxI710GSMruS3WkRPilBBhiJSBxaAnvw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 395, + "comment": "u2 == 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", + "wx": "13681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b10288", + "wy": "16528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEE2gerhaM1Op88uKkXQUnQtEKn2TnloZ9\nvcuCn+CxAogWUodg0Xc3bAnfed45VXwynMF1NRes/+j6LsKYAmuDhA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 396, + "comment": "u2 == n - 1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b89", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", + "wx": "5aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c2", + "wy": "0091c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWqer/ba0CG1UMyXl15xulc5C+GbSu4SQ\nljOgS7GqMcKRyACIeUkF4dozM22HTi+RzPRcxZGFvt5d1vP3rKrhiw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 397, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e91e1ba6ba898620a46bcb51dc0b8b4ad1dc35dad892c4552d1847b2ce444637", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", + "wx": "277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e4", + "wy": "64108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEACd3kbMFpFsrOVkLLwXTOSpsgYLO9OtU\nASDg9cIGw+RkEIIz+wuMOsiS15744Pv5LtEzrdtFVCcBMlhNxS7vQQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 398, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e36bf0cec06d9b841da81332812f74f30bbaec9f202319206c6f0b8a0a400ff7", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", + "wx": "6efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1a", + "wy": "00c75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbvoJK2jelGDwvMkZAFpfboDhnemJaL48\n0sdwqZSb+xrHXm5Qh9ZVDV+b6x555QKTB7wlUjXi1dyZJBrDq4hsSQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 399, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ea26b57af884b6c06e348efe139c1e4e9ec9518d60c340f6bac7d278ca08d8a6", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", + "wx": "72d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058", + "wy": "00e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEctShnE+dLPWEjqQERbcNRpa18C1jLAxl\nTMfX7rDG0FjoxM2ZQ+RZF0x6wB+nQhmOR+bBmmvbDE9sI3gxwbP5Qg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 400, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205b1d27a7694c146244a5ad0bd0636d9d9ef3b9fb58385418d9c982105077d1b7", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", + "wx": "2a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e7402", + "wy": "58f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEKo6i9Q3M7QwhdXW9+nzUfRxvEABB7A41\nUSeUwb5+dAJY+MFxIu0wP9pxQ+tYvt5wKVtlMmYBOwsOvT8FMTf27A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 401, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d27a7694c146244a5ad0bd0636d9e12abe687897e8e9998ddbd4e59a78520d0f", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", + "wx": "0088de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b8", + "wy": "0c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiN5onOmvHpS+aiCJyKixJT/9u2yOnIYk\nm6IgABpK07gMSZjlSEL0E7ntsYJay7YzXoHk0YSysByL69yF0fKJRg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 402, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100a4f4ed29828c4894b5a17a0c6db3c256c2221449228a92dff7d76ca8206dd8dd", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", + "wx": "00fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7", + "wy": "00b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/qLTH3D5DV+z4A4YasQqs8FhXO5xTgtO\nETGz1NgiW/ewN6GN8qwVND8w90Bn3fKegX1fd/jc4FcU2lnAlPDNqQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 403, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220694c146244a5ad0bd0636d9e12bc9e09e60e68b90d0b5e6c5dddd0cb694d8799", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", + "wx": "7258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db", + "wy": "17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcliRHj1CM0kWZHnb4Lg0Gvf70D0KfhDt\nzLNrbO6lo9sXrCuJknkRKPo7ltwvvUyjv6eC7ygy/GZWlD2xjnNGsA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 404, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203d7f487c07bfc5f30846938a3dcef696444707cf9677254a92b06c63ab867d22", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", + "wx": "4f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914", + "wy": "00c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAETyhGHepkR01rs00Umcl9N7npVjPfHO7q\nrNRQFsmLORTIgYgQuMwG3bQOihJhxSj6pYlFXVpt+Tt3vF4OSTx0cA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 405, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206c7648fc0fbf8a06adb8b839f97b4ff7a800f11b1e37c593b261394599792ba4", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", + "wx": "74f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66", + "wy": "00eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEdPKoFPtdjsqRppteYHEnMrOTfeMoKb6X\nTte2jFwvXWbv8PB8VvmHplf0IZYgX1iMDx2W/YpjpfI4tI9Hh4j+Ow==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 406, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0221009be363a286f23f6322c205449d320baad417953ecb70f6214e90d49d7d1f26a8", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", + "wx": "195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6a", + "wy": "00b2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGVtRp8xKIbgnSnCpDed5gUw8jKNYMoII\nwJop8za4LWqyQWt8kv/9wpw7EoLdKnek0E3390UgRzk9hJmJxc7prQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 407, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022029798c5c45bdf58b4a7b2fdc2c46ab4af1218c7eeb9f0f27a88f1267674de3b0", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", + "wx": "622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa", + "wy": "736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYi/HRzIDS+wt3zvBbTSz0fejJ90qjBm6\ntLtP46JLWKpzay8vrnb0367MkJYzOwEyjVHrP9qckifpDQtEmYPE8A==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 408, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02200b70f22ca2bb3cefadca1a5711fa3a59f4695385eb5aedf3495d0b6d00f8fd85", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", + "wx": "1f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c7", + "wy": "0827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH3+FyvLXVQ56+bZQI+u03ONFAxFpIwnb\nJplpuDS2EccIJ/RbeAIOy7r0hP3Vv6rmhw8RhMIVgbr274K9e1MPkw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 409, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022016e1e459457679df5b9434ae23f474b3e8d2a70bd6b5dbe692ba16da01f1fb0a", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", + "wx": "49c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377a", + "wy": "00efc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEScGX3ICtHaR6Q0K5OJPo4fsLuU/DOoPn\ng8ALJMeBN3rvwg2pK6x2KVH3JHS+zHNNTMIrqBuJXigv2sTfevDzfQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 410, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202252d685e831b6cf095e4f0535eeaf0ddd3bfa91c210c9d9dc17224702eaf88f", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", + "wx": "00d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe", + "wy": "7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2MtoUXthalZACqOGhjXlS29plZii9hZ3\nV2VJgLr2rL5+yM9EnISaoDRhow762kFFPFfG5vvJO7xvpJrabcBVXA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 411, + "comment": "edge case for u1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022075135abd7c425b60371a477f09ce0f274f64a8c6b061a07b5d63e93c65046c53", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", + "wx": "030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3", + "wy": "00b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAwcT+2Pyqm/iyt8bIO/CWcd0Rdr6h9rD\nmLhAZco0ffOyJ4GN4aObWJywcdg+UxfMzcIzjlHjEv4x2Nw0pIAXUA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 412, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d55555555555555555555555555555547c74934474db157d2a8c3f088aced62a", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", + "wx": "00babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7", + "wy": "252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEurs2d7CVWALY6SmkE1VkDq8eoTU/incT\nMcSUbjSAr6clLxlsh+09KlnTsbVZE3/tABP+zvwZ+1qSaCubylG5UA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 413, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100c1777c8853938e536213c02464a936000ba1e21c0fc62075d46c624e23b52f31", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", + "wx": "1aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60", + "wy": "00bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGqsgGHk0cREaig6bFD/eAvyVkgeW06Y9\n4ym0JDlvumC75BMHBRdHkkQbMY06ox3+hXeCHptEbsVz0nLgNsTr6Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 414, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022030bbb794db588363b40679f6c182a50d3ce9679acdd3ffbe36d7813dacbdc818", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", + "wx": "008cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff", + "wy": "47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjLC5CUmcg+qAbNiFsd1GegEZ8GqIoCdu\nsM/aJ0U1qP9HtUKIM7w/LIv52QQRWM8zcYpplhzQFym8ABHR5YardQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 415, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202c37fd995622c4fb7fffffffffffffffc7cee745110cb45ab558ed7c90c15a2f", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", + "wx": "008f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d", + "wy": "3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjwPPGkInK7FTJyMJP3Lm/urIXhcA6fvp\npqLdZC10v107iacYna2M91/CL28ViqJ/nCygDaynhb4zWPK9o4YsoA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 416, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02207fd995622c4fb7ffffffffffffffffff5d883ffab5b32652ccdcaa290fccb97d", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", + "wx": "44de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8ace", + "wy": "00a2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERN47nHpXqMnoIJUnU0IefZh7s9efcfAT\ngFyJfgGPis6iRgdYyPmNP9zhIalDZZ43LDJv/y5fwq5/o/edquE8Eg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 417, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ffb32ac4589f6ffffffffffffffffffebb107ff56b664ca599b954521f9972fa", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", + "wx": "6fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a", + "wy": "0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEb7iytI4zAxJorWpRdITciDnqkPZmnqDH\nrDIz4qwxOUoKyLvn9zwv9N+ZeHJ6wd/C/VhkfSDzH5kQUxa2RnHyBA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 418, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205622c4fb7fffffffffffffffffffffff928a8f1c7ac7bec1808b9f61c01ec327", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", + "wx": "00bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6", + "wy": "00f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvqcRIqBIaT6QX/YCs8+d0Yr2m5/J2EMd\nKx3Sa5Qsleb0PHuLletiCCwS2529p/445Fy+SkiGkH+4G9sMXqkkbA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 419, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022044104104104104104104104104104103b87853fd3b7d3f8e175125b4382f25ed", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", + "wx": "00da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156", + "wy": "00e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2pGMcxugaiDLlO8zt3jpgaQEowXxlB/j\nNma0WwM1MVbiuyaU9XW0UYO+eOXJtSEL879Ij9TIKUUW2JVyyk9TkQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 420, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202739ce739ce739ce739ce739ce739ce705560298d1f2f08dc419ac273a5b54d9", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", + "wx": "3007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d", + "wy": "5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMAfpLDk32t55ZN+jWw7/Ax9+sCrtCgMU\nQREGzetw/j1adUb8BVKZeyDj1vQT514stm4RYyJpcRS3m6xzS/xNxQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 421, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100b777777777777777777777777777777688e6a1fe808a97a348671222ff16b863", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", + "wx": "60e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9b", + "wy": "00d2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYOc071Yk08vw3dN1ARvWY9bWrrxkTrWZ\n/fmNvc0YzpvS2Qs6wx8TmvgyzM9sy7ssbqEfqXNw3JkG2kdNfYp1Zw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 422, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206492492492492492492492492492492406dd3a19b8d5fb875235963c593bd2d3", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", + "wx": "0085a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba337", + "wy": "69744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEhakA6XhY9pPAt9+iYeOA2tbqBG0fZd3u\n7dX32K8LozdpdE0VrdT2wLw7DaKuyTs0y4xl+TQN33TnsACe7szOPA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 423, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100955555555555555555555555555555547c74934474db157d2a8c3f088aced62c", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", + "wx": "38066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046", + "wy": "00a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOAZvddiO/EyT3jb0ngN7I0zBix3lYIdQ\npiyrA0VAEEaj6EvtjPy4Ge9NVQRE8s5LZRdmtp4uKQH4iDb/kANP7Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 424, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b17", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", + "wx": "0098f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabf", + "wy": "00a33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmPaBd9yVwbTL+lJFSIylI6fVYpRw0DXW\nIaRDxy85qr+jPSlUb6HGSPLH1cz3DPHOSrebXbGsBZ2+zQaNvf8biQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 425, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100bffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", + "wx": "5c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277", + "wy": "00e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEXCu/ojybmtB/A4qom0kwvyZ9lAHkJV3p\n6NoKUHjsgnfj6IKjHV5qN54Hk5g8ze05uVxDU6sv8B6lNpukewwxkQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 426, + "comment": "edge case for u2", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220185ddbca6dac41b1da033cfb60c152869e74b3cd66e9ffdf1b6bc09ed65ee40c", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", + "wx": "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", + "wy": "3547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4U1R4CCmESO215wGt6EzV+xrJVnul6Ptoprkz7EtcyEzA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 427, + "comment": "point duplication during verification", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", + "wx": "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", + "wy": "00cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4XKuH99Z7txJKGP5SF7MqBOU2qYRaFwSXWUbME6SjN3Yw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 428, + "comment": "duplication bug", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", + "wx": "008aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e", + "wy": "1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiqLGT6nGQ3Vjq/vL0AsgSNSMGMFSoqb0\nkDbedkfr6C4c5kOHmVxooGD6O8A5mwXMBu7H1Zj3UEGkkX5pK39R/w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 429, + "comment": "comparison with point at infinity ", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0022033333333333333333333333333333332f222f8faefdb533f265d461c29a47373", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", + "wx": "391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71f", + "wy": "00dd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEORQn/37ngBPBSux9lqigYiCSmKeDg16U\n/WVJ1QL/9x/dZiTsNDrZ/PTZhyGB5Z+EL5ukzMrgmmwJcvtqxrTGvQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 430, + "comment": "extreme value for k and edgecase s", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", + "wx": "00e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138e", + "wy": "00c1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE52K4ohm08YAhnMepBZJF5JYb0ZHAOJl4\nnHo0uJ6ME47BUz7wQZu3N24L/ekxnRCgaWh5HZ6g7tnBzmNFrtl1ng==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 431, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", + "wx": "009aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952", + "wy": "00fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmu2w0oHbFk4TAADFaX+uDzBe+Ei+b/+0\nOsWT+7lQ6VL6b2MzWb3NgrVrC5+WWwN3idRrmoFBt5GyrvpxP5bBdQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 432, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", + "wx": "008ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee", + "wy": "1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEitRF22KBYmDk5of9GITki5/AY20DFUfW\nMxXnkuGb+u4d5k+Z1fHNi27Jyw94emVK6GmTuj2xAI70PP8GhMsivQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 433, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", + "wx": "1f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32", + "wy": "00e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH1eZyVvokGOyTybkDLkowahop2+wCUYH\n6AQ9tAnJHDLnVyToE6QZHjqDkAfwji6Jc4iwbUoA3m3mDlNtkfq1Zg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 434, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", + "wx": "00a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc", + "wy": "28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEozMaThtCI+wsAn7dSCySihTtNY2T8dQh\nfTmr9p/LXMwo1oTSqqvNY4N3XKpiOd4m1MaTe7YD7LQZYIL0z/1QnQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 435, + "comment": "extreme value for k", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", + "wx": "3f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb24818", + "wy": "5ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPzlSGZd0x885s4tmyxBCpiYNhoCAOEXk\n1DOtujuySBhepJW2jLx+1Bc+5jyQQtxQJiXH634h+wLKmpEU4KOhjQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 436, + "comment": "extreme value for k and edgecase s", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", + "wx": "00cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e", + "wy": "054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzfuMD0IuFE4TfCQSyGwXH1/j+j9bu1RO\nkHYojzzteG4FT9ByG3fBHHm+rLPJQhGwoZvaCGUu/q+SUTo7ChY2mA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 437, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", + "wx": "73598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3", + "wy": "00cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEc1mKahxoJ4+mv9DOQGTmgjW8HA9rIKko\nEIvjNnMPh+PLrmElGbUDLsyFrtgRJxqV/nk51dNGAUC6MY9NFKujHQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 438, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", + "wx": "58debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a1", + "wy": "6773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWN69mn7iydWRMkeKVECuTV1+1Dcwg2n5\nLqhsghg/EKFnc+dvXtv02g5PG9/6wPVyV+HfpGWEKTEwmiQkX9pqXQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 439, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", + "wx": "008b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b", + "wy": "00950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEi5BN5HlnNAxfjDVypyCSTvdXhjf+qxlJ\nrLJBpaasP1uVCQRJb5gksdY/MxO64huJ+uia/fyBG17OA/1aowGGTw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 440, + "comment": "extreme value for k and s^-1", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", + "wx": "00f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a", + "wy": "346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE9IkrbVJcdx4DXyolJwjzeE5II4YEtPlN\nxW6qHlRtlBo0axqgvOaLHFDltS9Qn7VSLlwl4Ci8j4Y0Au23vK2LGw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 441, + "comment": "extreme value for k", + "flags": [ + "ArithmeticError" + ], + "msg": "313233343030", + "sig": "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "wx": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "wy": "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 442, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + }, + { + "tcId": 443, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", + "wx": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "wy": "00b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5i3xSWI2Vw7mqJbBAPx7vdXAuhLt1l6q+ZjuC9vBO8ndw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 444, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + }, + { + "tcId": 445, + "comment": "public key shares x-coordinate with generator", + "flags": [ + "PointDuplication" + ], + "msg": "313233343030", + "sig": "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", + "wx": "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", + "wy": "01060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv8AAAABBgSS1aVnPg8l2NUPt+WMSdhtRtQhaVXgqj1A4Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 446, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "304402206d6a4f556ccce154e7fb9f19e76c3deca13d59cc2aeb4ecad968aab2ded45965022053b9fa74803ede0fc4441bf683d56c564d3e274e09ccf47390badd1471c05fb7", + "result": "valid" + }, + { + "tcId": 447, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3046022100aad503de9b9fd66b948e9acf596f0a0e65e700b28b26ec56e6e45e846489b3c4022100fff223c5d0765447e8447a3f9d31fd0696e89d244422022ff61a110b2a8c2f04", + "result": "valid" + }, + { + "tcId": 448, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "30460221009182cebd3bb8ab572e167174397209ef4b1d439af3b200cdf003620089e43225022100abb88367d15fe62d1efffb6803da03109ee22e90bc9c78e8b4ed23630b82ea9d", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", + "wx": "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", + "wy": "00fffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv/////++fttKlqYwfDaJyrwSBpztieSuSvelqoeVcK7Tg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 449, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "304502203854a3998aebdf2dbc28adac4181462ccac7873907ab7f212c42db0e69b56ed8022100c12c09475c772fd0c1b2060d5163e42bf71d727e4ae7c03eeba954bf50b43bb3", + "result": "valid" + }, + { + "tcId": 450, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3046022100e94dbdc38795fe5c904d8f16d969d3b587f0a25d2de90b6d8c5c53ff887e3607022100856b8c963e9b68dade44750bf97ec4d11b1a0a3804f4cb79aa27bdea78ac14e4", + "result": "valid" + }, + { + "tcId": 451, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3044022049fc102a08ca47b60e0858cd0284d22cddd7233f94aaffbb2db1dd2cf08425e102205b16fca5a12cdb39701697ad8e39ffd6bdec0024298afaa2326aea09200b14d6", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", + "wx": "013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0", + "wy": "00f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAAAAAT/SIkjWTZX3PCm0irSGMYUL5QP9\nAPhGi18PcOD27nqkO8LG/SWx2CaSQcvdnbsNrJbcliMfQwcF+DhxfQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 452, + "comment": "x-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3045022041efa7d3f05a0010675fcb918a45c693da4b348df21a59d6f9cd73e0d831d67a022100bbab52596c1a1d9484296cdc92cbf07e665259a13791a8fe8845e2c07cf3fc67", + "result": "valid" + }, + { + "tcId": 453, + "comment": "x-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3046022100b615698c358b35920dd883eca625a6c5f7563970cdfc378f8fe0cee17092144c022100da0b84cd94a41e049ef477aeac157b2a9bfa6b7ac8de06ed3858c5eede6ddd6d", + "result": "valid" + }, + { + "tcId": 454, + "comment": "x-coordinate of the public key is small", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "304602210087cf8c0eb82d44f69c60a2ff5457d3aaa322e7ec61ae5aecfd678ae1c1932b0e022100c522c4eea7eafb82914cbf5c1ff76760109f55ddddcf58274d41c9bc4311e06e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", + "wx": "25afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dffffffff", + "wy": "00fa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJa/WiayrrtZ8Hylt5ZQG+MVQ9XFGoLTs\nLJeHbf/////6RqduUgMi37xJHsTwzBl0IPxOpYg9j23VPDVLxPZ8NQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 455, + "comment": "x-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3045022062f48ef71ace27bf5a01834de1f7e3f948b9dce1ca1e911d5e13d3b104471d82022100a1570cc0f388768d3ba7df7f212564caa256ff825df997f21f72f5280d53011f", + "result": "valid" + }, + { + "tcId": 456, + "comment": "x-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3046022100f6b0e2f6fe020cf7c0c20137434344ed7add6c4be51861e2d14cbda472a6ffb40221009be93722c1a3ad7d4cf91723700cb5486de5479d8c1b38ae4e8e5ba1638e9732", + "result": "valid" + }, + { + "tcId": 457, + "comment": "x-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3045022100db09d8460f05eff23bc7e436b67da563fa4b4edb58ac24ce201fa8a358125057022046da116754602940c8999c8d665f786c50f5772c0a3cdbda075e77eabc64df16", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", + "wx": "00d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb9", + "wy": "3f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0S5sZrZ3NMPITSYBz1013Al+J2N/CspK\nT9t0tqrdO7k/W9/4i9VzbfiY5pkAbtdQ8RzwfFhmzXrXDHEh/////w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 458, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "30450220592c41e16517f12fcabd98267674f974b588e9f35d35406c1a7bb2ed1d19b7b8022100c19a5f942607c3551484ff0dc97281f0cdc82bc48e2205a0645c0cf3d7f59da0", + "result": "valid" + }, + { + "tcId": 459, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3046022100be0d70887d5e40821a61b68047de4ea03debfdf51cdf4d4b195558b959a032b20221008266b4d270e24414ecacb14c091a233134b918d37320c6557d60ad0a63544ac4", + "result": "valid" + }, + { + "tcId": 460, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3046022100fae92dfcb2ee392d270af3a5739faa26d4f97bfd39ed3cbee4d29e26af3b206a02210093645c80605595e02c09a0dc4b17ac2a51846a728b3e8d60442ed6449fd3342b", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", + "wx": "6d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000", + "wy": "00e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a034200046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbUp/YNR3Sk8KqLve25U8fup5CUB+MWR1\nVmS8KAAAAADmWdNOTfONnoyeqt+6NmEsdpGVvobHeqw/NueLU4aA+w==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 461, + "comment": "x-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "30450220176a2557566ffa518b11226694eb9802ed2098bfe278e5570fe1d5d7af18a943022100ed6e2095f12a03f2eaf6718f430ec5fe2829fd1646ab648701656fd31221b97d", + "result": "valid" + }, + { + "tcId": 462, + "comment": "x-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3045022060be20c3dbc162dd34d26780621c104bbe5dace630171b2daef0d826409ee5c2022100bd8081b27762ab6e8f425956bf604e332fa066a99b59f87e27dc1198b26f5caa", + "result": "valid" + }, + { + "tcId": 463, + "comment": "x-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCasePublicKey" + ], + "msg": "4d657373616765", + "sig": "3046022100edf03cf63f658883289a1a593d1007895b9f236d27c9c1f1313089aaed6b16ae022100e5b22903f7eb23adc2e01057e39b0408d495f694c83f306f1216c9bf87506074", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-non-minimal-tag", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "wx": "782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963", + "wy": "00af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeCyO0X47Kng7VGTzOwllKnHGeOBexR6E\n4rz8Zjo96WOvmstCgLjH98QvTvmrpiRewewXEv04oPqWQY2M1qphUg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 464, + "comment": "signature with non-minimal SEQUENCE tag", + "flags": [ + "InvalidEncoding" + ], + "msg": "", + "sig": "3f1046022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc022100b303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", + "result": "invalid" + }, + { + "tcId": 465, + "comment": "signature with non-minimal INTEGER tag on r", + "flags": [ + "InvalidEncoding" + ], + "msg": "", + "sig": "30471f022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc022100b303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", + "result": "invalid" + }, + { + "tcId": 466, + "comment": "signature with non-minimal INTEGER tag on s", + "flags": [ + "InvalidEncoding" + ], + "msg": "", + "sig": "3047022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc1f022100b303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "wx": "b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c9", + "wy": "2ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuVIIc0JLi3CZEEpaDrGsrEjhiXGZcbkT\nG/nKjCX0Nskv+AWzbkDWUf+3Vz7dm0mYwvL+OYkbrz2DZw6SQsDUrQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 467, + "comment": "r = 1, x = 1 is valid", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0415f0573de014498f1ee256977a7a21ce5663888d223f841b24495d599a2bd2dfaec48b59fbc8ce644a8d0e5feae572a9dce6d94ab5c1cc04ca5b3d82591aa640", + "wx": "15f0573de014498f1ee256977a7a21ce5663888d223f841b24495d599a2bd2df", + "wy": "aec48b59fbc8ce644a8d0e5feae572a9dce6d94ab5c1cc04ca5b3d82591aa640" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000415f0573de014498f1ee256977a7a21ce5663888d223f841b24495d599a2bd2dfaec48b59fbc8ce644a8d0e5feae572a9dce6d94ab5c1cc04ca5b3d82591aa640", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFfBXPeAUSY8e4laXenohzlZjiI0iP4Qb\nJEldWZor0t+uxItZ+8jOZEqNDl/q5XKp3ObZSrXBzATKWz2CWRqmQA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 468, + "comment": "r = 2, x = 1 is invalid", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "3026020102022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "wx": "b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c9", + "wy": "2ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b9520873424b8b7099104a5a0eb1acac48e189719971b9131bf9ca8c25f436c92ff805b36e40d651ffb7573edd9b4998c2f2fe39891baf3d83670e9242c0d4ad", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuVIIc0JLi3CZEEpaDrGsrEjhiXGZcbkT\nG/nKjCX0Nskv+AWzbkDWUf+3Vz7dm0mYwvL+OYkbrz2DZw6SQsDUrQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 469, + "comment": "r = 1 + n, x = 1 is invalid; r was not reduced mod n", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04b0fa79bc98baff15d39cf88f8343aea79c0df7f4265361e97a2428b355e460d78fa95eec6e2e02d72c259d20e0ca273468e83f36cee40eed76934c57354ca6a3", + "wx": "b0fa79bc98baff15d39cf88f8343aea79c0df7f4265361e97a2428b355e460d7", + "wy": "8fa95eec6e2e02d72c259d20e0ca273468e83f36cee40eed76934c57354ca6a3" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004b0fa79bc98baff15d39cf88f8343aea79c0df7f4265361e97a2428b355e460d78fa95eec6e2e02d72c259d20e0ca273468e83f36cee40eed76934c57354ca6a3", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEsPp5vJi6/xXTnPiPg0Oup5wN9/QmU2Hp\neiQos1XkYNePqV7sbi4C1ywlnSDgyic0aOg/Ns7kDu12k0xXNUymow==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 470, + "comment": "r = n - 3, x = n - 2 is invalid", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0449be80da98fb7ea4165f898c36c696c50bd9da6485038c6cbda36d82dad41cfd64613a0e2c7224a85e29f774726b434e969db2d4765eafdf3c36004b7202ff3f", + "wx": "49be80da98fb7ea4165f898c36c696c50bd9da6485038c6cbda36d82dad41cfd", + "wy": "64613a0e2c7224a85e29f774726b434e969db2d4765eafdf3c36004b7202ff3f" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000449be80da98fb7ea4165f898c36c696c50bd9da6485038c6cbda36d82dad41cfd64613a0e2c7224a85e29f774726b434e969db2d4765eafdf3c36004b7202ff3f", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESb6A2pj7fqQWX4mMNsaWxQvZ2mSFA4xs\nvaNtgtrUHP1kYToOLHIkqF4p93Rya0NOlp2y1HZer988NgBLcgL/Pw==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 471, + "comment": "r = 2, x = n + 2 is the smallest possible x with a reduction", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "3026020102022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "valid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04682cb28dfdcb3e72f200307a6146151338a7143914439c046980c805f0e9d12681d073c1b1dd129e3627d75d8a231a80342149abfcdd8ab9b5775fde215ab9a0", + "wx": "682cb28dfdcb3e72f200307a6146151338a7143914439c046980c805f0e9d126", + "wy": "81d073c1b1dd129e3627d75d8a231a80342149abfcdd8ab9b5775fde215ab9a0" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004682cb28dfdcb3e72f200307a6146151338a7143914439c046980c805f0e9d12681d073c1b1dd129e3627d75d8a231a80342149abfcdd8ab9b5775fde215ab9a0", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEaCyyjf3LPnLyADB6YUYVEzinFDkUQ5wE\naYDIBfDp0SaB0HPBsd0SnjYn112KIxqANCFJq/zdirm1d1/eIVq5oA==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 472, + "comment": "r = 3, x = n + 2 is invalid", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "3026020103022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "0493c9400c1fc5ed1aefb9f463e7650ae09778313fc188e84564e711a7b84588867e72afd2a40cd15f7b92c6ce7ea95dc7327e54a5309312f43628273534a86ae9", + "wx": "93c9400c1fc5ed1aefb9f463e7650ae09778313fc188e84564e711a7b8458886", + "wy": "7e72afd2a40cd15f7b92c6ce7ea95dc7327e54a5309312f43628273534a86ae9" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a0342000493c9400c1fc5ed1aefb9f463e7650ae09778313fc188e84564e711a7b84588867e72afd2a40cd15f7b92c6ce7ea95dc7327e54a5309312f43628273534a86ae9", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEk8lADB/F7RrvufRj52UK4Jd4MT/BiOhF\nZOcRp7hFiIZ+cq/SpAzRX3uSxs5+qV3HMn5UpTCTEvQ2KCc1NKhq6Q==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 473, + "comment": "r = p - n + 1, x = 1 is invalid; r is too large to compare r + n with x", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "30360211014551231950b75fc4402da1722fc9baef022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-r-s-edge-cases", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04e7ed253ac1810f174a83443264f57efbc090bb478a1fac8296f637b4694502a86f48fbb04579fa9e3bbce880915211b24de7f21511e3acf63ea49d737fc6459d", + "wx": "e7ed253ac1810f174a83443264f57efbc090bb478a1fac8296f637b4694502a8", + "wy": "6f48fbb04579fa9e3bbce880915211b24de7f21511e3acf63ea49d737fc6459d" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004e7ed253ac1810f174a83443264f57efbc090bb478a1fac8296f637b4694502a86f48fbb04579fa9e3bbce880915211b24de7f21511e3acf63ea49d737fc6459d", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE5+0lOsGBDxdKg0QyZPV++8CQu0eKH6yC\nlvY3tGlFAqhvSPuwRXn6nju86ICRUhGyTefyFRHjrPY+pJ1zf8ZFnQ==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 474, + "comment": "r = 2^256 - n + 1, x = 1 is invalid; r + n is too large to compare r + n with x, and overflows 2^256 bits", + "flags": [ + "ArithmeticError" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "30360211014551231950b75fc4402da1732fc9bec0022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "result": "invalid" + } + ] + }, + { + "type": "EcdsaVerify", + "source": { + "name": "github/davidben/ecdsa-s-pow2", + "version": "0.1" + }, + "publicKey": { + "type": "EcPublicKey", + "curve": "secp256k1", + "keySize": 256, + "uncompressed": "04315971a60089e7749a8fa1d8374ecbaab259d773b3737e932bbaa960cdbf27f1bfe600bd60a91e650508eab795146b13c766195a447b24709df9d1c561e53dae", + "wx": "315971a60089e7749a8fa1d8374ecbaab259d773b3737e932bbaa960cdbf27f1", + "wy": "bfe600bd60a91e650508eab795146b13c766195a447b24709df9d1c561e53dae" + }, + "publicKeyDer": "3056301006072a8648ce3d020106052b8104000a03420004315971a60089e7749a8fa1d8374ecbaab259d773b3737e932bbaa960cdbf27f1bfe600bd60a91e650508eab795146b13c766195a447b24709df9d1c561e53dae", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMVlxpgCJ53Saj6HYN07LqrJZ13Ozc36T\nK7qpYM2/J/G/5gC9YKkeZQUI6reVFGsTx2YZWkR7JHCd+dHFYeU9rg==\n-----END PUBLIC KEY-----\n", + "sha": "SHA-256", + "tests": [ + { + "tcId": 475, + "comment": "s = 2^128", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "303502202b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef2202110100000000000000000000000000000000", + "result": "valid" + }, + { + "tcId": 476, + "comment": "s = n - 2^128", + "flags": [ + "ValidSignature" + ], + "msg": "68656c6c6f2c20776f726c64", + "sig": "304502202b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef22022100fffffffffffffffffffffffffffffffdbaaedce6af48a03bbfd25e8cd0364141", + "result": "valid" + } + ] + } + ] +} diff --git a/thoughts/ec-recover-opt/oracle/gen_vectors.py b/thoughts/ec-recover-opt/oracle/gen_vectors.py new file mode 100644 index 000000000..a2318205a --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/gen_vectors.py @@ -0,0 +1,95 @@ +"""Generate vectors.json: the canonical ECSM edge-case suite for the z3 gate +and any future implementation. Values come from the oracle (ec_ref), which is +validated by anchors A (Wycheproof), B (ecdsa PyPI), C (repo k256 differential). + +Every entry: x_le / k_le (hex, little-endian byte order as the ABI takes), +x / k (big-endian ints as hex, for humans), expected xr or error kind, +provenance + why-this-case tags. +""" + +import json +import random + +from ec_ref import EcError, GX, N, P, recover_even_y, x_only_mul_ints + +rng = random.Random(424242) + + +def le_hex(v): + return v.to_bytes(32, "little").hex() + + +def random_valid_x(): + while True: + x = rng.randrange(P) + if recover_even_y(x) is not None: + return x + + +def nonresidue_x(): + while True: + x = rng.randrange(P) + if recover_even_y(x) is None: + return x + + +def entry(x, k, why, prov="oracle(ec_ref) anchored A/B/C"): + e = {"x": f"{x:x}", "k": f"{k:x}", "x_le": le_hex(x), "k_le": le_hex(k), + "why": why, "provenance": prov} + try: + e["xr"] = f"{x_only_mul_ints(x, k):x}" + except EcError as err: + e["error"] = err.kind + return e + + +def main(): + vs = [] + # schedule-shaped scalars on G + vs.append(entry(GX, 1, "k=1 echo: no steps, xr == xG")) + vs.append(entry(GX, 2, "k=2: single double row")) + vs.append(entry(GX, 3, "k=3: double+add, minimal add path")) + vs.append(entry(GX, N - 1, "k=N-1: x((N-1)P) == x(P) since (N-1)P = -P")) + vs.append(entry(GX, N - 2, "k=N-2")) + for i in (1, 8, 64, 128, 255): + vs.append(entry(GX, 2**i, f"k=2^{i}: all-double schedule, len_k={i}")) + vs.append(entry(GX, 2**i - 1, f"k=2^{i}-1: double+add every row")) + vs.append(entry(GX, int("10" * 128, 2) % N, "alternating 10 bits")) + vs.append(entry(GX, int("01" * 128, 2), "alternating 01 bits")) + vs.append(entry(GX, (1 << 200) + 1, "long zero run between MSB and LSB")) + vs.append(entry(GX, ((1 << 56) - 1) << 100, "long one-run mid-scalar")) + + # random points x random/edge scalars + for i in range(20): + x = random_valid_x() + vs.append(entry(x, rng.randrange(1, N), f"random point/scalar #{i}")) + x = random_valid_x() + for k in (1, N - 1, 2**255): + vs.append(entry(x, k, "edge scalar on random point")) + + # error paths (exact contract) + vx = random_valid_x() + vs.append(entry(vx, 0, "k=0 -> ScalarIsZero")) + vs.append(entry(vx, N, "k=N -> ScalarOutOfRange")) + vs.append(entry(vx, N + 1, "k=N+1 -> ScalarOutOfRange")) + vs.append(entry(vx, 2**256 - 1, "k=2^256-1 -> ScalarOutOfRange")) + vs.append(entry(P, 5, "x=p -> CoordinateOutOfRange")) + vs.append(entry(P + 1, 5, "x=p+1 -> CoordinateOutOfRange")) + vs.append(entry(2**256 - 1, 5, "x=2^256-1 -> CoordinateOutOfRange")) + vs.append(entry(nonresidue_x(), 5, "non-residue x -> NotOnCurve")) + vs.append(entry(nonresidue_x(), rng.randrange(1, N), "non-residue x, random k")) + # check-order witnesses + vs.append(entry(P, 0, "k=0 beats x=p: ScalarIsZero (order witness)")) + vs.append(entry(nonresidue_x(), N, "k=N beats non-residue: ScalarOutOfRange (order witness)")) + + json.dump({"curve": "secp256k1", "function": "xr = x(k*P), P=(x, even y)", + "abi": "32-byte little-endian x, k, xr; errors trap the VM", + "generated": "2026-07-24 ec-oracle", + "vectors": vs}, open("vectors.json", "w"), indent=1) + ok = sum(1 for v in vs if "xr" in v) + err = sum(1 for v in vs if "error" in v) + print(f"vectors.json: {len(vs)} vectors ({ok} valid, {err} error-path)") + + +if __name__ == "__main__": + main() diff --git a/thoughts/ec-recover-opt/oracle/jacobian_ref.py b/thoughts/ec-recover-opt/oracle/jacobian_ref.py new file mode 100644 index 000000000..7c4655d64 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/jacobian_ref.py @@ -0,0 +1,169 @@ +"""Second independent secp256k1 implementation — Jacobian coordinates. + +Deliberately a DIFFERENT CODE PATH from `ec_ref.py`, not a refactor of it: + +| | `ec_ref.py` | this file | +|---|---|---| +| coordinates | affine, one inversion per step | Jacobian `(X:Y:Z)`, one inversion at the very end | +| infinity | cannot be represented (asserts) | represented as `Z = 0`, handled by the formulas | +| doubling | `lam = 3x^2/(2y)` | `dbl-2009-l` (a = 0), inversion-free | +| addition | `lam = (y2-y1)/(x2-x1)` | `add-2007-bl`, inversion-free, equal-`x` handled | +| scalar mul | MSB-first double-and-add | **LSB-first** (right-to-left) double-and-add | +| lincomb | n/a | two independent scalar muls, then one add | + +The only thing shared with `ec_ref.py` is the SEC2 curve constant `p` (and the +group order `N` for input validation) — both re-stated here from the standard, +so the two files agree on the curve but on nothing else. Formulas are the +standard EFD (Explicit-Formulas Database) short-Weierstrass `a = 0` ones. + +Used by `lincomb2_anchors.py` as the independent side of the lincomb2 +differential, and by `anchor_a_wycheproof.py`'s ECDSA-verify anchor. +""" + +# ── SEC2 published constants (restated, not imported) ─────────────────────── +P = 2**256 - 2**32 - 977 +N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 +B = 7 +GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 +GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 + +# The point at infinity in Jacobian form. Any Z = 0 triple is infinity; this is +# the canonical one produced by the formulas. +INF = (0, 0, 0) + + +def is_inf(pt): + return pt[2] % P == 0 + + +def to_jac(affine): + """(x, y) -> (X:Y:1). `None` means infinity.""" + if affine is None: + return INF + x, y = affine + return (x % P, y % P, 1) + + +def to_affine(pt): + """(X:Y:Z) -> (x, y), or None for infinity. One inversion, at the end.""" + if is_inf(pt): + return None + x, y, z = pt + zi = pow(z, P - 2, P) + zi2 = (zi * zi) % P + return ((x * zi2) % P, (y * zi2 % P * zi) % P) + + +def jac_double(pt): + """EFD `dbl-2009-l` for a = 0. Returns infinity for y = 0 and for infinity.""" + x, y, z = pt + if z % P == 0 or y % P == 0: + return INF + a = (x * x) % P + b = (y * y) % P + c = (b * b) % P + d = (2 * (((x + b) * (x + b) - a - c) % P)) % P + e = (3 * a) % P + f = (e * e) % P + x3 = (f - 2 * d) % P + y3 = (e * (d - x3) - 8 * c) % P + z3 = (2 * y * z) % P + return (x3, y3, z3) + + +def jac_add(p1, p2): + """EFD `add-2007-bl`, with the equal-input cases handled explicitly. + + Complete for our purposes: returns infinity when the inputs are inverses, + and delegates to `jac_double` when they are the same point. + """ + if is_inf(p1): + return p2 + if is_inf(p2): + return p1 + x1, y1, z1 = p1 + x2, y2, z2 = p2 + z1z1 = (z1 * z1) % P + z2z2 = (z2 * z2) % P + u1 = (x1 * z2z2) % P + u2 = (x2 * z1z1) % P + s1 = (y1 * z2 % P * z2z2) % P + s2 = (y2 * z1 % P * z1z1) % P + if u1 == u2: + if s1 != s2: + return INF # P2 = -P1 + return jac_double(p1) # P2 = P1 + h = (u2 - u1) % P + i = (4 * h * h) % P + j = (h * i) % P + r = (2 * (s2 - s1)) % P + v = (u1 * i) % P + x3 = (r * r - j - 2 * v) % P + y3 = (r * (v - x3) - 2 * s1 * j) % P + z3 = ((((z1 + z2) * (z1 + z2)) % P - z1z1 - z2z2) * h) % P + return (x3, y3, z3) + + +def jac_neg(pt): + x, y, z = pt + return (x, (-y) % P, z) + + +def jac_mul(k, pt): + """k·pt, LSB-first (right-to-left) double-and-add. + + Opposite scan direction to `ec_ref.scalar_mul`, and it accumulates into a + running "addend doubling" register rather than into the point itself, so a + bug in either loop cannot cancel against the other. Accepts k = 0 (returns + infinity) and any k >= 0; no range assertion, so out-of-range scalars are + the caller's business. + """ + acc = INF + addend = pt + while k: + if k & 1: + acc = jac_add(acc, addend) + addend = jac_double(addend) + k >>= 1 + return acc + + +def on_curve_affine(affine): + if affine is None: + return True + x, y = affine + if not (0 <= x < P and 0 <= y < P): + return False + return (y * y - x * x % P * x - B) % P == 0 + + +def lincomb2(u1, pt1, u2, pt2): + """Q = u1·pt1 + u2·pt2 over affine inputs; returns affine Q or None (∞). + + Two independent scalar muls plus one group add — structurally as far from + the joint/interleaved Shamir–Straus chain the chip proves as it gets, which + is exactly the point of a differential. + """ + q = jac_add(jac_mul(u1, to_jac(pt1)), jac_mul(u2, to_jac(pt2))) + return to_affine(q) + + +def ecdsa_verify(pubkey, z, r, s): + """Textbook ECDSA verification, on the Jacobian path. + + `pubkey` is affine (x, y), `z` the already-truncated message integer. + Returns True iff the signature is valid. This is the `u1·G + u2·PK` lincomb + shape the Wycheproof ECDSA vectors exercise. + """ + if not (1 <= r < N and 1 <= s < N): + return False + if not on_curve_affine(pubkey) or pubkey is None: + return False + w = pow(s, N - 2, N) + u1 = (z * w) % N + u2 = (r * w) % N + q = jac_add(jac_mul(u1, to_jac((GX, GY))), jac_mul(u2, to_jac(pubkey))) + if is_inf(q): + return False + x, _ = to_affine(q) + return (x % N) == r diff --git a/thoughts/ec-recover-opt/oracle/lincomb2_anchors.py b/thoughts/ec-recover-opt/oracle/lincomb2_anchors.py new file mode 100644 index 000000000..c101102b7 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/lincomb2_anchors.py @@ -0,0 +1,373 @@ +"""Phase-D0 oracle anchors for the lincomb2 precompile. + +Three anchors, all differential against implementations that do NOT share a +code path with `lincomb2_ref.py`: + + L-A >=500 random lincomb2 differentials, 3-way: + `lincomb2_ref.lincomb2` (affine, MSB-first, ec_ref.py lineage) + vs `jacobian_ref.lincomb2` (Jacobian, LSB-first, inversion-free) + vs `ecdsa` PyPI (third lineage, independent package) + plus, per case, the NUMS-blinded joint-chain row list must land on the + same Q and every emitted row must re-satisfy its own group law. + + L-B small-joint-scalar unrollings, u1, u2 in [1, 16] (the phase-E L7 anchor). + Ground truth is FULLY ENUMERATED: u·P computed by u-1 repeated group + additions, no scalar-multiplication algorithm involved at all. Row + schedules are dumped to `lincomb2_small_vectors.json` for the gate. + + L-C row-shape census over the L-A corpus (row counts per ecrecover), so the + layout lock's mean/max are re-derived here rather than asserted. + +Run: /bin/python lincomb2_anchors.py (needs the `ecdsa` package) +""" + +import json +import random +import sys + +import ec_ref +import jacobian_ref +import lincomb2_ref +from ec_ref import GX, GY, N, P, pt_add, pt_double, recover_even_y + +from ecdsa import SECP256k1 +from ecdsa.ellipticcurve import INFINITY, Point + +rng = random.Random(20260724) + +T0, T0_COUNTER = lincomb2_ref.t0_ref() + +# Third lineage: the `ecdsa` package's own group law. +LIB_CURVE = SECP256k1.curve +LIB_G = SECP256k1.generator + + +def lib_lincomb2(u1, pt1, u2, pt2): + """Q = u1*pt1 + u2*pt2 using the `ecdsa` package's Point arithmetic.""" + a = Point(LIB_CURVE, pt1[0], pt1[1]) * u1 + b = Point(LIB_CURVE, pt2[0], pt2[1]) * u2 + q = a + b + if q == INFINITY: + return None + return (q.x(), q.y()) + + +def random_point(): + """A uniformly random on-curve point, both parities exercised.""" + while True: + x = rng.randrange(P) + y = recover_even_y(x) + if y is not None: + break + if rng.random() < 0.5: + y = (P - y) % P + return (x, y) + + +def check_rows(rows, P1, P2, T0_pt, u1, u2, length): + """Re-verify every emitted row from first principles: the slope, the group + law, on-curveness of the result, and the schedule's bit bookkeeping. + Returns a list of failure strings (empty = clean).""" + bad = [] + on_curve = lambda pt: (pt[1] * pt[1] - pt[0] ** 3 - 7) % P == 0 + + seen_digits = {} + acc = None + for i, r in enumerate(rows): + a, g, res, lam, op = r["a"], r["addend"], r["r"], r["lam"], r["op"] + # slope + group law, recomputed independently of the emitter + if op == 0: + want_lam = (3 * a[0] * a[0] * pow((2 * a[1]) % P, P - 2, P)) % P + want = pt_double(a) + else: + if a[0] == g[0]: + bad.append(f"row {i} ({r['sel']}): degenerate add, xa == xg") + continue + want_lam = ((g[1] - a[1]) * pow((g[0] - a[0]) % P, P - 2, P)) % P + want = pt_add(a, g) + if lam != want_lam: + bad.append(f"row {i} ({r['sel']}): lambda mismatch") + if res != want: + bad.append(f"row {i} ({r['sel']}): result mismatch") + if not on_curve(res): + bad.append(f"row {i} ({r['sel']}): result off curve") + + # telescoping: a == previous r, EXCEPT the precompute row (standalone + # chord P1 + P2, off the accumulator line) and the first double (seeded + # at T0). This is the layout-lock's flagged special case. + if r["sel"] == lincomb2_ref.SEL_PRECOMPUTE: + if a != P1 or g != P2: + bad.append(f"row {i}: precompute operands are not (P1, P2)") + else: + expect_a = T0_pt if acc is None else acc + if a != expect_a: + bad.append(f"row {i} ({r['sel']}): accumulator not telescoped") + acc = res + if r["sel"] == lincomb2_ref.SEL_PRECOMPUTE: + continue + + if r["sel"] == lincomb2_ref.SEL_DOUBLE: + if g != (0, 0): + bad.append(f"row {i}: double row carries a nonzero addend") + # the digit bits and the round-successor flag ride the double row + want = ((u1 >> r["round"]) & 1, (u2 >> r["round"]) & 1) + if (r["d1"], r["d2"]) != want: + bad.append(f"row {i}: double row digits {(r['d1'], r['d2'])} != {want}") + if r["nb"] != (want[0] | want[1]): + bad.append(f"row {i}: nb != d1|d2") + elif r["nb"] != 0: + bad.append(f"row {i} ({r['sel']}): nb set on a non-double row") + if r["op"] == 1 and r["sel"] != lincomb2_ref.SEL_CORRECTION: + seen_digits[r["round"]] = (r["d1"], r["d2"]) + + # every nonzero joint digit below `length` consumed exactly once, and no + # add row invented for a zero digit + for rr in range(length): + d = ((u1 >> rr) & 1, (u2 >> rr) & 1) + if d == (0, 0): + if rr in seen_digits: + bad.append(f"round {rr}: add row for a zero joint digit") + else: + if seen_digits.get(rr) != d: + bad.append(f"round {rr}: joint digit {d} not consumed") + n_dbl = sum(1 for r in rows if r["sel"] == lincomb2_ref.SEL_DOUBLE) + if n_dbl != length: + bad.append(f"double count {n_dbl} != len {length}") + return bad + + +# ── L-A: >=500 random lincomb differentials ───────────────────────────────── + +def anchor_a(count=600): + fails = 0 + skipped = 0 + row_counts = [] + dbl_counts = [] + add_counts = [] + cases = [] + + edges = [ + (1, 1), (1, 2), (2, 1), (3, 5), + (N - 1, N - 1), (N - 1, 1), (1, N - 1), + (2**255, 2**255 - 1), (2**255 - 1, 2**255), + (2**128, 2**128 + 1), ((N - 1) // 2, (N + 1) // 2), + ] + for i in range(count + len(edges)): + if i < len(edges): + u1, u2 = edges[i] + else: + u1 = rng.randrange(1, N) + u2 = rng.randrange(1, N) + P1 = (GX, GY) if i % 3 == 0 else random_point() + P2 = random_point() + if P1[0] == P2[0]: + skipped += 1 + continue + + q_ref = lincomb2_ref.lincomb2(u1, P1, u2, P2) + q_jac = jacobian_ref.lincomb2(u1, P1, u2, P2) + q_lib = lib_lincomb2(u1, P1, u2, P2) + if q_ref is None or q_jac is None or q_lib is None: + # Q = infinity: all three must agree that it is degenerate. + if not (q_ref is None and q_jac is None and q_lib is None): + fails += 1 + print(f"FAIL L-A[{i}] infinity disagreement: " + f"ref={q_ref} jac={q_jac} lib={q_lib}") + skipped += 1 + continue + + if q_ref != q_jac: + fails += 1 + print(f"FAIL L-A[{i}] ref != jacobian: u1={u1:x} u2={u2:x} " + f"P1={P1[0]:x} P2={P2[0]:x}") + continue + if q_ref != q_lib: + fails += 1 + print(f"FAIL L-A[{i}] ref != ecdsa-lib: u1={u1:x} u2={u2:x} " + f"P1={P1[0]:x} P2={P2[0]:x}") + continue + + # the blinded joint chain must land on the same Q, row by row + try: + q_chain, length, rows = lincomb2_ref.lincomb2_rows(u1, P1, u2, P2, T0) + except ValueError as e: + fails += 1 + print(f"FAIL L-A[{i}] blinded chain rejected ({e}) on a case the " + f"references computed: u1={u1:x} u2={u2:x}") + continue + if q_chain != q_ref: + fails += 1 + print(f"FAIL L-A[{i}] blinded chain Q != reference Q: u1={u1:x} u2={u2:x}") + continue + bad = check_rows(rows, P1, P2, T0, u1, u2, length) + if bad: + fails += 1 + print(f"FAIL L-A[{i}] row check: {bad[:4]}") + continue + + row_counts.append(len(rows)) + dbl_counts.append(sum(1 for r in rows if r["sel"] == lincomb2_ref.SEL_DOUBLE)) + add_counts.append(sum(1 for r in rows + if r["sel"] in (lincomb2_ref.SEL_ADD_P1, + lincomb2_ref.SEL_ADD_P2, + lincomb2_ref.SEL_ADD_P12))) + cases.append((u1, u2, P1, P2, q_ref)) + + n = len(row_counts) + print(f"ANCHOR L-A (3-way lincomb2 differential + blinded-chain row check): " + f"{'PASS' if fails == 0 else 'FAIL'} " + f"({n} cases compared 3 ways, {skipped} degenerate/skipped, {fails} failures)") + if n: + print(f" row census: doubles mean {sum(dbl_counts)/n:.1f} max {max(dbl_counts)} " + f"adds mean {sum(add_counts)/n:.1f} max {max(add_counts)}") + print(f" total rows: mean {sum(row_counts)/n:.1f} max {max(row_counts)} " + f"min {min(row_counts)}") + return fails, cases + + +# ── L-B: small-joint-scalar unrollings, u1, u2 in [1, 16] ─────────────────── + +def enumerated_mul(u, pt): + """u*pt by u-1 REPEATED GROUP ADDITIONS. No double-and-add, no windowing, + no recursion: the fully-unrolled definition of scalar multiplication. + Returns affine or None (infinity).""" + assert u >= 1 + acc = pt + for _ in range(u - 1): + if acc is None: + return None + if acc[0] == pt[0]: + if acc[1] == pt[1]: + acc = pt_double(acc) + else: + acc = None # acc = -pt -> infinity + else: + acc = pt_add(acc, pt) + return acc + + +def enumerated_lincomb2(u1, pt1, u2, pt2): + a = enumerated_mul(u1, pt1) + b = enumerated_mul(u2, pt2) + if a is None: + return b + if b is None: + return a + if a[0] == b[0]: + return pt_double(a) if a[1] == b[1] else None + return pt_add(a, b) + + +def anchor_b(dump_path="lincomb2_small_vectors.json"): + """u1, u2 in [1, 16] x several point pairs, exhaustively.""" + fails = 0 + checked = 0 + vectors = [] + + G = (GX, GY) + # Point pairs: (label, P1, P2). The (G, 3G) pair carries an extra algebraic + # cross-check -- u1*G + u2*(3G) must equal (u1 + 3*u2)*G. + three_g = ec_ref.scalar_mul(3, G) + pairs = [("G,3G", G, three_g)] + for j in range(3): + pairs.append((f"G,R{j}", G, random_point())) + for j in range(2): + pairs.append((f"R{j},R{j}'", random_point(), random_point())) + + for label, P1, P2 in pairs: + assert P1[0] != P2[0] + for u1 in range(1, 17): + for u2 in range(1, 17): + truth = enumerated_lincomb2(u1, P1, u2, P2) + q_ref = lincomb2_ref.lincomb2(u1, P1, u2, P2) + q_jac = jacobian_ref.lincomb2(u1, P1, u2, P2) + q_lib = lib_lincomb2(u1, P1, u2, P2) + checked += 1 + if not (truth == q_ref == q_jac == q_lib): + fails += 1 + print(f"FAIL L-B[{label} u1={u1} u2={u2}]: " + f"enumerated={truth} ref={q_ref} jac={q_jac} lib={q_lib}") + continue + if label == "G,3G": + want = ec_ref.scalar_mul((u1 + 3 * u2) % N, G) + if want != truth: + fails += 1 + print(f"FAIL L-B[{label} u1={u1} u2={u2}]: " + f"(u1+3u2)*G cross-check disagrees") + continue + + try: + q_chain, length, rows = lincomb2_ref.lincomb2_rows(u1, P1, u2, P2, T0) + except ValueError as e: + fails += 1 + print(f"FAIL L-B[{label} u1={u1} u2={u2}]: chain rejected ({e})") + continue + if q_chain != truth: + fails += 1 + print(f"FAIL L-B[{label} u1={u1} u2={u2}]: chain Q != enumerated Q") + continue + bad = check_rows(rows, P1, P2, T0, u1, u2, length) + if bad: + fails += 1 + print(f"FAIL L-B[{label} u1={u1} u2={u2}] row check: {bad[:4]}") + continue + + rec = { + # P1/P2 live once in the `pairs` header, keyed by `pair`. + "pair": label, + "u1": u1, "u2": u2, + "len": length, + "rows": len(rows), + "Q": [f"{truth[0]:064x}", f"{truth[1]:064x}"], + # compact schedule shape: the row-role sequence, which is + # what the L6/L7 counting arguments are about. + "shape": ",".join(r["sel"] for r in rows), + } + # Full per-row values for a pinned subset only (keeps the file + # in the same size class as `vectors.json`); everything else is + # regenerable by re-running this script. + if label == "G,3G" and u1 <= 8 and u2 <= 8: + rec["schedule"] = [ + {"sel": r["sel"], "round": r["round"], "op": r["op"], + "d1": r["d1"], "d2": r["d2"], + "a": [f"{r['a'][0]:064x}", f"{r['a'][1]:064x}"], + "addend": [f"{r['addend'][0]:064x}", f"{r['addend'][1]:064x}"], + "lam": f"{r['lam']:064x}", + "r": [f"{r['r'][0]:064x}", f"{r['r'][1]:064x}"]} + for r in rows + ] + vectors.append(rec) + + detailed = sum(1 for v in vectors if "schedule" in v) + with open(dump_path, "w") as fh: + json.dump({ + "description": "lincomb2 small-joint-scalar unrollings (phase-E L7 anchor). " + "Ground truth by repeated group addition; row schedules mirror " + "ecsm::lincomb2_witness. `shape` is the row-role sequence for " + "every case; `schedule` (full per-row values) is present on the " + "pinned G,3G u1,u2<=8 subset.", + "T0": {"x": f"{T0[0]:064x}", "y": f"{T0[1]:064x}", "counter": T0_COUNTER}, + "pairs": { + label: {"P1": [f"{a[0]:064x}", f"{a[1]:064x}"], + "P2": [f"{b[0]:064x}", f"{b[1]:064x}"]} + for label, a, b in pairs + }, + "count": len(vectors), + "detailed": detailed, + "vectors": vectors, + }, fh, separators=(",", ":")) + + print(f"ANCHOR L-B (small joint scalars u1,u2 in [1,16], {len(pairs)} point pairs): " + f"{'PASS' if fails == 0 else 'FAIL'} " + f"({checked} pairs enumerated, {fails} failures)") + print(f" wrote {len(vectors)} vectors ({detailed} with full row values) to {dump_path}") + return fails + + +if __name__ == "__main__": + print(f"T0 = ({T0[0]:#x}, {T0[1]:#x}) counter={T0_COUNTER}") + fa, _ = anchor_a() + fb = anchor_b() + total = fa + fb + print(f"PHASE D0 ORACLE: {'ALL GREEN' if total == 0 else f'{total} FAILURES'}") + sys.exit(1 if total else 0) diff --git a/thoughts/ec-recover-opt/oracle/lincomb2_ref.py b/thoughts/ec-recover-opt/oracle/lincomb2_ref.py new file mode 100644 index 000000000..86eda3d7b --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/lincomb2_ref.py @@ -0,0 +1,176 @@ +"""Independent lincomb2 + NUMS-T0 reference, layered on ec_ref.py. + +Written from the group law only (no k256, no repo transcription). Used to +validate the Rust `ecsm::lincomb2_witness` and to pin the T0 blinding point. +""" + +import hashlib +from ec_ref import P, N, B, GX, GY, pt_add, pt_double, pt_neg, scalar_mul, recover_even_y + +T0_TAG = b"lambdavm/ecsm/lincomb2/T0/v1" + + +def t0_ref(): + """NUMS blinding point via try-and-increment: + x = SHA-256(tag || counter_be32) as a big-endian int; accept the first + counter giving x < P that is a valid curve x; pick the EVEN y. + Returns ((x, y), counter).""" + counter = 0 + while True: + h = hashlib.sha256(T0_TAG + counter.to_bytes(4, "big")).digest() + x = int.from_bytes(h, "big") + if x < P: + y = recover_even_y(x) + if y is not None: + return (x, y), counter + counter += 1 + + +def lincomb2(u1, P1, u2, P2): + """Q = u1*P1 + u2*P2 by independent scalar-mul + add. Returns Q or None + (None = Q is the point at infinity: the degenerate output case).""" + assert 1 <= u1 < N and 1 <= u2 < N + A = scalar_mul(u1, P1) + Bp = scalar_mul(u2, P2) + if A[0] == Bp[0]: + if A[1] == Bp[1]: + return pt_double(A) + return None # A = -B -> infinity + return pt_add(A, Bp) + + +def lincomb2_blinded_trace(u1, P1, u2, P2, T0): + """Mirror of the witness algorithm: NUMS-blinded joint Shamir/Straus. + Returns (Q, len, n_double_rows, n_add_rows) and asserts the blinded + accumulator equals Q + 2^len*T0 before correction. Independent check that + the row schedule the Rust builder emits actually computes Q.""" + assert 1 <= u1 < N and 1 <= u2 < N + P12 = None if P1[0] == P2[0] else pt_add(P1, P2) # None => degenerate P1=+-P2 + m = max(u1.bit_length(), u2.bit_length()) # = max_msb + 1 + length = m + acc = T0 + n_dbl = 0 + n_add = 0 + for r in range(length - 1, -1, -1): + acc = pt_double(acc) + n_dbl += 1 + d1 = (u1 >> r) & 1 + d2 = (u2 >> r) & 1 + if d1 and d2: + addend = P12 + elif d1: + addend = P1 + elif d2: + addend = P2 + else: + addend = None + if addend is not None: + acc = pt_add(acc, addend) + n_add += 1 + # 2^len * T0 + tpow = T0 + for _ in range(length): + tpow = pt_double(tpow) + Q = lincomb2(u1, P1, u2, P2) + if Q is not None: + # acc should equal Q + 2^len*T0 + assert acc == pt_add(Q, tpow), "blinded accumulator != Q + 2^len*T0" + # correction: acc + (-tpow) = Q + assert pt_add(acc, pt_neg(tpow)) == Q, "correction did not land on Q" + return Q, length, n_dbl, n_add + + +# ── full row emission, mirroring the Rust `lincomb2_witness` row list ──────── + +# Row roles, matching `witness.rs::JointSel` by name so gate/chip work can key +# off the same strings. +SEL_DOUBLE = "Double" +SEL_ADD_P1 = "AddP1" +SEL_ADD_P2 = "AddP2" +SEL_ADD_P12 = "AddP12" +SEL_PRECOMPUTE = "Precompute" +SEL_CORRECTION = "Correction" + + +def _slope_add(a, g): + return ((g[1] - a[1]) * pow((g[0] - a[0]) % P, P - 2, P)) % P + + +def _slope_dbl(a): + return (3 * a[0] * a[0] * pow((2 * a[1]) % P, P - 2, P)) % P + + +def lincomb2_rows(u1, P1, u2, P2, T0): + """Emit the FULL joint-chain row list, in the order and with the field + values `ecsm::lincomb2_witness` emits. + + Returns `(Q, length, rows)` where each row is a dict + `{sel, round, op, d1, d2, nb, a, addend, r, lam}` with affine `(x, y)` + tuples. Raises `ValueError` for the degenerate cases the Rust side reports + as `Lincomb2Error` (`SumDegenerate`, `ResultInfinity`). + + `d1`/`d2` are the two scalars' bits at the row's round, carried on BOTH the + double and the add of that round (the double needs them for its per-stream + `Bit` sends and to derive `nb`; the add needs them to select the addend), + and zero on the precompute/correction rows, which belong to no round. + + `nb = d1 | d2` on a double row and 0 everywhere else: "an add follows me at + this same round". It is what makes the successor round `round - 1 + nb` a + function of the row's own columns, so a prover cannot stall `round` by + inserting or dropping doublings. + + Row order (matches `witness.rs`): + 1 x Precompute (a = P1, addend = P2, OFF the accumulator line) + then for round = length-1 .. 0: one Double, plus one Add iff the joint + digit is nonzero + 1 x Correction (a = last accumulator, addend = -2^length * T0) + + This is the ground truth the phase-E L7 unrollings compare against. + """ + assert 1 <= u1 < N and 1 <= u2 < N + if P1[0] == P2[0]: + raise ValueError("SumDegenerate") + rows = [] + + P12 = pt_add(P1, P2) + rows.append(dict(sel=SEL_PRECOMPUTE, round=0, op=1, d1=0, d2=0, nb=0, + a=P1, addend=P2, r=P12, lam=_slope_add(P1, P2))) + + length = max(u1.bit_length(), u2.bit_length()) + acc = T0 + for r in range(length - 1, -1, -1): + d1 = (u1 >> r) & 1 + d2 = (u2 >> r) & 1 + lam = _slope_dbl(acc) + nxt = pt_double(acc) + rows.append(dict(sel=SEL_DOUBLE, round=r, op=0, d1=d1, d2=d2, + nb=d1 | d2, a=acc, addend=(0, 0), r=nxt, lam=lam)) + acc = nxt + + if not (d1 or d2): + continue + if d1 and d2: + addend, sel = P12, SEL_ADD_P12 + elif d1: + addend, sel = P1, SEL_ADD_P1 + else: + addend, sel = P2, SEL_ADD_P2 + if acc[0] == addend[0]: + raise ValueError("ResultInfinity") # dlog event under blinding + lam = _slope_add(acc, addend) + nxt = pt_add(acc, addend) + rows.append(dict(sel=sel, round=r, op=1, d1=d1, d2=d2, nb=0, + a=acc, addend=addend, r=nxt, lam=lam)) + acc = nxt + + tpow = T0 + for _ in range(length): + tpow = pt_double(tpow) + neg_tpow = pt_neg(tpow) + if acc[0] == neg_tpow[0]: + raise ValueError("ResultInfinity") + lam = _slope_add(acc, neg_tpow) + Q = pt_add(acc, neg_tpow) + rows.append(dict(sel=SEL_CORRECTION, round=0, op=1, d1=0, d2=0, nb=0, + a=acc, addend=neg_tpow, r=Q, lam=lam)) + return Q, length, rows diff --git a/thoughts/ec-recover-opt/oracle/lincomb2_small_vectors.json b/thoughts/ec-recover-opt/oracle/lincomb2_small_vectors.json new file mode 100644 index 000000000..3f28a2927 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/lincomb2_small_vectors.json @@ -0,0 +1 @@ +{"description":"lincomb2 small-joint-scalar unrollings (phase-E L7 anchor). Ground truth by repeated group addition; row schedules mirror ecsm::lincomb2_witness. `shape` is the row-role sequence for every case; `schedule` (full per-row values) is present on the pinned G,3G u1,u2<=8 subset.","T0":{"x":"af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","y":"1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0","counter":1},"pairs":{"G,3G":{"P1":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"P2":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"]},"G,R0":{"P1":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"P2":["8528bd45d954a2367b95cf05f90f9312ef5e40d044a034b172a74e1250db0e42","10bfb90f13c04668b5d5994f197416829f29dbcea1f2a4e40741b0d393b689d9"]},"G,R1":{"P1":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"P2":["11f6aa20131857a6c8b470cc0b8d186d463dcba3009282070433cf2e11ef937e","450e493e22d99541b7f0bfa97e0259a50f19c92c754af02dff448eda9119f590"]},"G,R2":{"P1":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"P2":["8488d4bdecb9c074665b8819b6e99c983c066c65cd62d6997acb4ae1f0a39fc1","b77945e42f689b776d9a06e5708a92f0576061e219e847b44e75c8ff49369f90"]},"R0,R0'":{"P1":["e6c76d6def77bd898681cbc7df3ed3c7a98feaf25f93969477816566042d8837","232f549e1d84a504ed6152988e157119c6683107ce4e55c3b1e5c567f3275706"],"P2":["0ccb860124af19eb0712b5ef7065f43188fa2c8759e3ee11673730ac84f8bc2f","428d1d30797045f89e4902580f1cd1b240940b2e491606673b7754e7241eb356"]},"R1,R1'":{"P1":["acf1d10c638686f6cfb3761a88022f6bbbbcce2d8aa504f8c733dfd7e0cf9225","89860deb96ca75753b665118f3356eaa7e9f947cf6393f474eb983ff52f21050"],"P2":["f2ec9e823be9909d7bd917eb4479eb8bb49672d8303f533bc792ba46de7f1d41","224e041fc4ab8a7893ab278e43620d2f1439921b3b6e85bffb2cf7c8f88e10d5"]}},"count":1536,"detailed":64,"vectors":[{"pair":"G,3G","u1":1,"u2":1,"len":1,"rows":4,"Q":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"shape":"Precompute,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","84f0188dd00edff8534ae7cada7638fed78d54e5d4edcafd2d281d863df856ec"],"lam":"9bd82df2a2f8bea24aaa30bee80491b19de77d44fde1f2af34e4d867bef9142e","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]}]},{"pair":"G,3G","u1":1,"u2":2,"len":2,"rows":6,"Q":["5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc","6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da"],"shape":"Precompute,Double,AddP2,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"854b1d6db86677dcfcf1ebde9f1964f6261f27e6904084d387838ce3d5701db7","r":["5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc","6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da"]}]},{"pair":"G,3G","u1":1,"u2":3,"len":2,"rows":6,"Q":["a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7","893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"],"shape":"Precompute,Double,AddP2,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"e6d2b69b13db442aaee85fce3990471145d5b06a6bcf653341a4d8db863463db","r":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"b22cd53b15bfbf6b756999cf628cd0a1a53ced3d8d89b64de1a3bd72c3ac51e6","r":["a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7","893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"]}]},{"pair":"G,3G","u1":1,"u2":4,"len":3,"rows":7,"Q":["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"5c8ce5308c4ce3f61f66094c26d7d12132f5439c7430011aa866d1d61fa19fef","r":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"1c529b23c3b4850c5c6bb02c11fa2b787b3680e6b02a1d7d1a86d0fad0bf698e","r":["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"]}]},{"pair":"G,3G","u1":1,"u2":5,"len":3,"rows":7,"Q":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"f0a81a6ba01362cdca979a555c348faae10098660fe3eb9ea1f5011a1f16be7b","r":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"47b883ec2a60236bee54b15d79b911d60dcd7b251369c71f06144773108e25ee","r":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"]}]},{"pair":"G,3G","u1":1,"u2":6,"len":3,"rows":8,"Q":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"ada03edfedd0ee8fa21adc5e0de4cc5941618c0c32ec55e9ce50b0544d04183c","r":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d076cfea243053c8ffbba7ff82ca93fa2774c88c44d5cc49e4aa8cc44f290958","r":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"d3d06ce6cee7ba2a0ee6eea43fe206068af171e1ee03a69a705adbb6149eb3de","r":["b4b9621839906a69ca9eacbd250a9bc06277de113e0fb8d94caced2fbab32e86","b4c4a8149989f0a40cb9ff41b4eaeac5823204cddc3f037fbee0c078fb3a413f"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["b4b9621839906a69ca9eacbd250a9bc06277de113e0fb8d94caced2fbab32e86","b4c4a8149989f0a40cb9ff41b4eaeac5823204cddc3f037fbee0c078fb3a413f"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"705f3dd2619e404b5ed1d6125bb435fe019b9d1c4ed617b6f7bab4448bafd168","r":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"]}]},{"pair":"G,3G","u1":1,"u2":7,"len":3,"rows":8,"Q":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"ada03edfedd0ee8fa21adc5e0de4cc5941618c0c32ec55e9ce50b0544d04183c","r":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d076cfea243053c8ffbba7ff82ca93fa2774c88c44d5cc49e4aa8cc44f290958","r":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"83fa601fabd3e894d4d83777ff8d7b4814e66aef799f1fac3fc492527726a2c0","r":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"02d4efd6fe966ace5a97b87479060a4785f88ef49409e1dfda815a3eda76ac4d","r":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"]}]},{"pair":"G,3G","u1":1,"u2":8,"len":4,"rows":8,"Q":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":3,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"8a240770f0010d0f7329d48939447ebaa5eacfc4bda11fae34687722a2654845","r":["cb0d8843aaa98be72dc7fc2062e609dbe30bee3f6521f2b0e590ab6090c35781","9d1f15438f34b7c895a06371ca39abdb479af871e0b70c173f047411940e5e8d"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["cb0d8843aaa98be72dc7fc2062e609dbe30bee3f6521f2b0e590ab6090c35781","9d1f15438f34b7c895a06371ca39abdb479af871e0b70c173f047411940e5e8d"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"515e1650d6a36fa48e1b5b4be64b99d3537558418de9aaf0d98e17af01a86097","r":["229f5655c2d76919b45555b9d9c2b2668796c84d11b0d1ea67c33d4b2acc44bf","8411508c43d81e4cd7435ed54a247c7612290c5b77c07208ce61bb1f05b4041d"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["229f5655c2d76919b45555b9d9c2b2668796c84d11b0d1ea67c33d4b2acc44bf","8411508c43d81e4cd7435ed54a247c7612290c5b77c07208ce61bb1f05b4041d"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"f79ea5006d90025f1d61efc2569e4f51c389b7947f67db156853440ed53aa4c7","r":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"]}]},{"pair":"G,3G","u1":1,"u2":9,"len":4,"rows":8,"Q":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":1,"u2":10,"len":4,"rows":9,"Q":["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":1,"u2":11,"len":4,"rows":9,"Q":["1be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11","bebc47511ade7308b3ca6265f9400779c076329c75146bc6ff1822f5d1f30e79"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":1,"u2":12,"len":4,"rows":9,"Q":["62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d","80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":1,"u2":13,"len":4,"rows":9,"Q":["91de2f6bb67b11139f0e21203041bf080eacf59a33d99cd9f1929141bb0b4d0b","eb9ef6c031eed31de34e7a1009f8725155b03158202a9d3e9a9a2e83124a7899"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":1,"u2":14,"len":4,"rows":10,"Q":["d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9","eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":1,"u2":15,"len":4,"rows":10,"Q":["f8b0b03d44112259f903b3d100e3950d980fdde9c7e85701c16baedc90235717","bd8e9dc301d9adc96be1883b362f123bd0a986928ac79972517ab5c246242203"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":1,"u2":16,"len":5,"rows":9,"Q":["f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530","e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"],"shape":"Precompute,Double,AddP2,Double,Double,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":2,"u2":1,"len":2,"rows":6,"Q":["2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4","d8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6"],"shape":"Precompute,Double,AddP1,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"c25147e5470841c0d310e811c6cafff1bc05bdf6903c8c9cdd8cedf9914ca4aa","r":["2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4","d8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6"]}]},{"pair":"G,3G","u1":2,"u2":2,"len":2,"rows":5,"Q":["2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01","5c4da8a741539949293d082a132d13b4c2e213d6ba5b7617b5da2cb76cbde904"],"shape":"Precompute,Double,AddP12,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"9683be42d237a05b2a23997ac8a9a4e7e13d02bfe4bf976416288f4c9f793087","r":["2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01","5c4da8a741539949293d082a132d13b4c2e213d6ba5b7617b5da2cb76cbde904"]}]},{"pair":"G,3G","u1":2,"u2":3,"len":2,"rows":6,"Q":["774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb","d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"],"shape":"Precompute,Double,AddP12,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"4ad0a146b53cc8c5fd4a3151cf0889ee49e5122c908b3ddf6bc46ae9fe0fa478","r":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"bc0961497d43d999467106f9cbaa47fae7f11a3db27f9711b287524008f7889e","r":["774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb","d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"]}]},{"pair":"G,3G","u1":2,"u2":4,"len":3,"rows":7,"Q":["499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4","cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"d4a8533bfabeb318e1adc52e9831c72a34f250d69b1d9c06866f35f620249160","r":["499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4","cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b"]}]},{"pair":"G,3G","u1":2,"u2":5,"len":3,"rows":8,"Q":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"0dd1c9d61dc9f7e8ecbc86a4df9f6561337d527ae8ef96d254c3500b9e1efbbb","r":["4d63805afd1307c951bfd9b0ac5e4b5a7e717c3cf79ba68b15e7963fec2565a4","0fed027fdc0f72045d9d26f00d190753b72a7050d9b9ba6b923f1279bcc49c81"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["4d63805afd1307c951bfd9b0ac5e4b5a7e717c3cf79ba68b15e7963fec2565a4","0fed027fdc0f72045d9d26f00d190753b72a7050d9b9ba6b923f1279bcc49c81"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"66b700ad859969b04702415d901261441d510c6fd94f76a3fcd40e3e2377dd6d","r":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"]}]},{"pair":"G,3G","u1":2,"u2":6,"len":3,"rows":7,"Q":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"e6d2b69b13db442aaee85fce3990471145d5b06a6bcf653341a4d8db863463db","r":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"0a65c75b3a0fea71bf5c9f8bb0292698d5795e3bd97b1b7090579c85638dba52","r":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"6e54c4de2a3f9d4039a23a6167d7ac98b83b03a89d687d22c01ffe1984f73d14","r":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"]}]},{"pair":"G,3G","u1":2,"u2":7,"len":3,"rows":8,"Q":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"e6d2b69b13db442aaee85fce3990471145d5b06a6bcf653341a4d8db863463db","r":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"0a65c75b3a0fea71bf5c9f8bb0292698d5795e3bd97b1b7090579c85638dba52","r":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"baa28f52c46d2227912a26b859ac8f377cd1c2c8df765cf632a0d32d1cac32ac","r":["18545ebcd3c0fe4da07f9a4bbf6eedd9a53eeebace45dc09b6cf40d8be84545c","bd939e2b0b532ede389dc97be60a17d88cce8e4f3828467bdb6eadad46c0a47c"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["18545ebcd3c0fe4da07f9a4bbf6eedd9a53eeebace45dc09b6cf40d8be84545c","bd939e2b0b532ede389dc97be60a17d88cce8e4f3828467bdb6eadad46c0a47c"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"92b40d641eb506a16aae72673807831e1bb04e252b261f1b528e133376164512","r":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"]}]},{"pair":"G,3G","u1":2,"u2":8,"len":4,"rows":8,"Q":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":3,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"5c8ce5308c4ce3f61f66094c26d7d12132f5439c7430011aa866d1d61fa19fef","r":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"9cb986b8510536151d4c8ae927ba47b7e4735b6077357e4a8964bd0d188d929a","r":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"824efac08e3651f0dfa480cc1568d2923dbd358481303dcec5c59addeae6de8e","r":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"]}]},{"pair":"G,3G","u1":2,"u2":9,"len":4,"rows":9,"Q":["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":2,"u2":10,"len":4,"rows":8,"Q":["d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65","95038d9d0ae3d5c3b3d6dec9e98380651f760cc364ed819605b3ff1f24106ab9"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":2,"u2":11,"len":4,"rows":9,"Q":["605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479","02972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":2,"u2":12,"len":4,"rows":9,"Q":["b699a30e6e184cdfa88ac16c7d80bffd38e2e1fc705821ea69cd5fdf1691fff7","d505700c51d860ce5a096ee637ebed3bd9d7268126c76a16b745bc318a51ab04"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":2,"u2":13,"len":4,"rows":10,"Q":["7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb","0d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":2,"u2":14,"len":4,"rows":9,"Q":["5d045857332d5b9e541514731622af8d60c180165d971a61e06b70a9b3834765","db2ba972802d45fd2decbab8d098a8c2a1d1f34761c6cf261879a7cabf06fb68"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":2,"u2":15,"len":4,"rows":10,"Q":["77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74","958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":2,"u2":16,"len":5,"rows":9,"Q":["29757774cc6f3be1d5f1774aefa8f02e50bc64404230e7a67e8fde79bd559a9a","c39d07337ddc9268a0eba45a7a41876d151b423eac4033b550bd28c17c470134"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":3,"u2":1,"len":2,"rows":6,"Q":["fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556","ae12777aacfbb620f3be96017f45c560de80f0f6518fe4a03c870c36b075f297"],"shape":"Precompute,Double,AddP1,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"70e11be53053673944b19cb9fcccd90a4931d6e1c16b275653414459c711084a","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"b797ee0ab1bb0c9328e36464aa9fa1d43d3240d30ed20092359b129ae4159b9e","r":["fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556","ae12777aacfbb620f3be96017f45c560de80f0f6518fe4a03c870c36b075f297"]}]},{"pair":"G,3G","u1":3,"u2":2,"len":2,"rows":6,"Q":["acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe","cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37"],"shape":"Precompute,Double,AddP12,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"981d276e318a330f24fa20bdaff6617f7e772ecfa38cf1d9fff34a353580e327","r":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"4ee328b604fc9cf57f421b8f6ff7797b730b2e766ae476e6303906f43bfb4417","r":["acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe","cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37"]}]},{"pair":"G,3G","u1":3,"u2":3,"len":2,"rows":6,"Q":["d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a","a9f34ffdc815e0d7a8b64537e17bd81579238c5dd9a86d526b051b13f4062327"],"shape":"Precompute,Double,AddP12,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"39b697dfbcda19fd61500b911025f17da993c0b1944ae2bb3af0cb55fb4d2868","r":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"],"addend":["03f0bcb55c7dbd41b34aaa2e82d5503a722cbc385fd8aaf74a6505d1ae51e77b","69e0dcfca5c1f8ad68c6f6ed9a7913f671a1b8924e512086287f1a2cd04f7a78"],"lam":"6bdd00dfef7739c4f6c8d828993bbb6e4bec118583a18429a2760d9be4ab390b","r":["d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a","a9f34ffdc815e0d7a8b64537e17bd81579238c5dd9a86d526b051b13f4062327"]}]},{"pair":"G,3G","u1":3,"u2":4,"len":3,"rows":8,"Q":["d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e","581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"628a90d2cabe087687ce9c570c0d6e63ec360a4d8ddf2dd2d49cb8c97ba3d353","r":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"97e38b99a75a51f49bd47019f684ee6704421f3a13eb6b062500e604b63edaab","r":["d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e","581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"]}]},{"pair":"G,3G","u1":3,"u2":5,"len":3,"rows":8,"Q":["5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc","c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"877c5fd80b1d50aa1e5da0e25444ca6bbe07c38ea20ca799226dee880115559f","r":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"3740c5e4d2ed85526d24fe79b80e0e5ceb90d79a6a3f530a5892fd7fe99d9a98","r":["5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc","c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58"]}]},{"pair":"G,3G","u1":3,"u2":6,"len":3,"rows":8,"Q":["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"e6d2b69b13db442aaee85fce3990471145d5b06a6bcf653341a4d8db863463db","r":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"0a65c75b3a0fea71bf5c9f8bb0292698d5795e3bd97b1b7090579c85638dba52","r":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"4943cc93a3e387833c91c6d3174cf066a5b9c22f21f9107d77daac7852283832","r":["194f208b8d80020144054adc6c374c822f9bddc44140309a804e1ca5d9d4217d","1c524bb907d93061674b534ded35f35df9c64c638fa769086457e96bf0658576"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["194f208b8d80020144054adc6c374c822f9bddc44140309a804e1ca5d9d4217d","1c524bb907d93061674b534ded35f35df9c64c638fa769086457e96bf0658576"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"e6c6bbfaa482d308c4642983d3d0acf5b69fea92d16c5bf87b75d71cb09f9916","r":["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"]}]},{"pair":"G,3G","u1":3,"u2":7,"len":3,"rows":8,"Q":["fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce","6851de067ff24a68d3ab47e09d72998101dc88e36b4a9d22978ed2fbcf58c5bf"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"e6d2b69b13db442aaee85fce3990471145d5b06a6bcf653341a4d8db863463db","r":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["4df8902acd2f2a17014ee44e97eb8287b4908081e85ba7994d423fbd4131ad73","73b9f49eb847bca77b7672e76aae00cbb693bb8f1e774205dee395e9cc2ea364"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"0a65c75b3a0fea71bf5c9f8bb0292698d5795e3bd97b1b7090579c85638dba52","r":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"abcab734e5768535cfe76f23871ce9d00602435a9b79b39d00c4d3f32ff2c1c8","r":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"35de2d3c70cb70bb34b25f340365057698a16ae25b4d1331b15e5620f52fafc6","r":["fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce","6851de067ff24a68d3ab47e09d72998101dc88e36b4a9d22978ed2fbcf58c5bf"]}]},{"pair":"G,3G","u1":3,"u2":8,"len":4,"rows":9,"Q":["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":3,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"5c8ce5308c4ce3f61f66094c26d7d12132f5439c7430011aa866d1d61fa19fef","r":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"9cb986b8510536151d4c8ae927ba47b7e4735b6077357e4a8964bd0d188d929a","r":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"7182d33504324b6c95ed3a24bf0cfc42dfd18db409f476187bfa49c73e7848ea","r":["a3e2ee836847541165cffa188033a6c7af56273e6c054924ea0e87d94a03223b","a70dc8144776d838bcb52ee668bce1191188749752b7fbc91a56d613f63af320"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["a3e2ee836847541165cffa188033a6c7af56273e6c054924ea0e87d94a03223b","a70dc8144776d838bcb52ee668bce1191188749752b7fbc91a56d613f63af320"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"8c76944ae29abf02eb6fce4e111f7020b25a59948ae7cb26663de8120bf62c5e","r":["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"]}]},{"pair":"G,3G","u1":3,"u2":9,"len":4,"rows":9,"Q":["6d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00","acb82eb93309ad1cc739ddfa33604a83776238aa0bd5ff248dbac47a17f388fb"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":3,"u2":10,"len":4,"rows":9,"Q":["1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5","b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":3,"u2":11,"len":4,"rows":9,"Q":["e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9","76d458642a2c93adee7a347a5e4681f9bb5b10f4bd8aa51edfd6e3f50e7da3ac"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":3,"u2":12,"len":4,"rows":10,"Q":["80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f","1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":3,"u2":13,"len":4,"rows":10,"Q":["fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af","07b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":3,"u2":14,"len":4,"rows":10,"Q":["049370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963","758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":3,"u2":15,"len":4,"rows":10,"Q":["6eca335d9645307db441656ef4e65b4bfc579b27452bebc19bd870aa1118e5c3","d50123b57a7a0710592f579074b875a03a496a3a3bf8ec34498a2f7805a08668"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":3,"u2":16,"len":5,"rows":10,"Q":["463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b","5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":4,"u2":1,"len":3,"rows":7,"Q":["5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc","6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d1f5843a309274d88b1525b96bdcbfef8a6320c0c691152b26b41b4003bc51e3","r":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"31a7ddd22bc353e9cbb274b6f764095d6f9e29411b6850724b86f46cb469a5e2","r":["33959bad375a41d7e453bc691b0f90f8d5117e68de2e52284b820e7168409cfe","dd1a183666d11f070e33eaeb456a2a9da99c8e508b4eb23b7229c6b5cf091e8d"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["33959bad375a41d7e453bc691b0f90f8d5117e68de2e52284b820e7168409cfe","dd1a183666d11f070e33eaeb456a2a9da99c8e508b4eb23b7229c6b5cf091e8d"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"9f9518d8791bc91441f63cef6967bd9e03269972d4ade9c2e993bd36248ce048","r":["5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc","6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da"]}]},{"pair":"G,3G","u1":4,"u2":2,"len":3,"rows":7,"Q":["a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7","893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"16e82000847bc1a13858822e4f3ccc15e72764c980f29e115dea42e6fdfd74c8","r":["a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7","893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"]}]},{"pair":"G,3G","u1":4,"u2":3,"len":3,"rows":8,"Q":["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"a0e6b647e668fd7983e20264fc01f572212469cad3f3e8c2b4c1178ed56b02cc","r":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"1c529b23c3b4850c5c6bb02c11fa2b787b3680e6b02a1d7d1a86d0fad0bf698e","r":["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"]}]},{"pair":"G,3G","u1":4,"u2":4,"len":3,"rows":6,"Q":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"],"shape":"Precompute,Double,AddP12,Double,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e8c044534047ec1492f7009a2f1e2eac7d4a4307b6faa3d4e6b2777d301d3fa2","r":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"47b883ec2a60236bee54b15d79b911d60dcd7b251369c71f06144773108e25ee","r":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"]}]},{"pair":"G,3G","u1":4,"u2":5,"len":3,"rows":7,"Q":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e8c044534047ec1492f7009a2f1e2eac7d4a4307b6faa3d4e6b2777d301d3fa2","r":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"ec6a7b5491c4ec5d54f1d4b79b4fdb27cf70bae401dbd767667668bc97531b81","r":["b4b9621839906a69ca9eacbd250a9bc06277de113e0fb8d94caced2fbab32e86","b4c4a8149989f0a40cb9ff41b4eaeac5823204cddc3f037fbee0c078fb3a413f"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["b4b9621839906a69ca9eacbd250a9bc06277de113e0fb8d94caced2fbab32e86","b4c4a8149989f0a40cb9ff41b4eaeac5823204cddc3f037fbee0c078fb3a413f"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"705f3dd2619e404b5ed1d6125bb435fe019b9d1c4ed617b6f7bab4448bafd168","r":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"]}]},{"pair":"G,3G","u1":4,"u2":6,"len":3,"rows":7,"Q":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"4ad0a146b53cc8c5fd4a3151cf0889ee49e5122c908b3ddf6bc46ae9fe0fa478","r":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"f19ad4eba6bc1144e8dfe078968982b4cab265de494ce140eaf2445341487b4b","r":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"02d4efd6fe966ace5a97b87479060a4785f88ef49409e1dfda815a3eda76ac4d","r":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"]}]},{"pair":"G,3G","u1":4,"u2":7,"len":3,"rows":8,"Q":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"4ad0a146b53cc8c5fd4a3151cf0889ee49e5122c908b3ddf6bc46ae9fe0fa478","r":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"f19ad4eba6bc1144e8dfe078968982b4cab265de494ce140eaf2445341487b4b","r":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"75ae7f7c7bb56aeda42fe38a426f111d92041f766e1c8a71ddd235e7b2f22ec4","r":["a3acdacae08c9a248465af126d5e1bfaf6063662579200ee1583177fb96c61d6","f1095be42913d22b6d71c2cbd9848ed6f584e0b1189adb676886cfd9c8d529d8"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["a3acdacae08c9a248465af126d5e1bfaf6063662579200ee1583177fb96c61d6","f1095be42913d22b6d71c2cbd9848ed6f584e0b1189adb676886cfd9c8d529d8"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"2d8122de83e5ce7707fd6ccee8dba1029b01ad657eceef61dcc5d319985ce21b","r":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"]}]},{"pair":"G,3G","u1":4,"u2":8,"len":4,"rows":8,"Q":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":3,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"1d1a1360f8a73daba141a1777169e990b322c29d9ff5cf4709cf25eb940c073c","r":["bbe4f4ce5daa6f8efbfab222eb8306ee6e6405738de7d102de39a93d73aae01f","2676a47c5d7bb7c13617d0ad08c71e5e3c39dc72fee7c3803eeb213fdc971dfd"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["bbe4f4ce5daa6f8efbfab222eb8306ee6e6405738de7d102de39a93d73aae01f","2676a47c5d7bb7c13617d0ad08c71e5e3c39dc72fee7c3803eeb213fdc971dfd"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"9ba18d4cad4810d95797ee8990ed056904ea226a3f50428071f6bd469ecd90ab","r":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"]}]},{"pair":"G,3G","u1":4,"u2":9,"len":4,"rows":9,"Q":["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":4,"u2":10,"len":4,"rows":9,"Q":["1be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11","bebc47511ade7308b3ca6265f9400779c076329c75146bc6ff1822f5d1f30e79"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":4,"u2":11,"len":4,"rows":10,"Q":["62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d","80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":4,"u2":12,"len":4,"rows":8,"Q":["91de2f6bb67b11139f0e21203041bf080eacf59a33d99cd9f1929141bb0b4d0b","eb9ef6c031eed31de34e7a1009f8725155b03158202a9d3e9a9a2e83124a7899"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,Correction"},{"pair":"G,3G","u1":4,"u2":13,"len":4,"rows":9,"Q":["d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9","eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":4,"u2":14,"len":4,"rows":9,"Q":["f8b0b03d44112259f903b3d100e3950d980fdde9c7e85701c16baedc90235717","bd8e9dc301d9adc96be1883b362f123bd0a986928ac79972517ab5c246242203"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":4,"u2":15,"len":4,"rows":10,"Q":["f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530","e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":4,"u2":16,"len":5,"rows":9,"Q":["2b22efda32491a9e0294339ca3da761f7d36cfc8814c1b29ca731921025ff695","7ed520327080a9fa4c16662fc134fadcc7048846d46ade0030b83fd19adc87cd"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,Correction"},{"pair":"G,3G","u1":5,"u2":1,"len":3,"rows":7,"Q":["2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01","5c4da8a741539949293d082a132d13b4c2e213d6ba5b7617b5da2cb76cbde904"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d1f5843a309274d88b1525b96bdcbfef8a6320c0c691152b26b41b4003bc51e3","r":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"a1fe7669f01bb263671d1131985b34a6df9b092690dfa8208bba19b742cc851b","r":["401ca18bb435d44e7acf10a174e6f215782329197941238951fac382d5f34124","d1d4ab6e4b509fd8e4fdf87c25866c1dfb153c886737bdbba66376c00fd8d07a"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["401ca18bb435d44e7acf10a174e6f215782329197941238951fac382d5f34124","d1d4ab6e4b509fd8e4fdf87c25866c1dfb153c886737bdbba66376c00fd8d07a"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"73f1962609e0a78cebb4a27836600db6d75df0ca285b1abd4a348c0230df9107","r":["2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01","5c4da8a741539949293d082a132d13b4c2e213d6ba5b7617b5da2cb76cbde904"]}]},{"pair":"G,3G","u1":5,"u2":2,"len":3,"rows":8,"Q":["774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb","d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"5215404ed59f24c30f58f447ba12f2d734acdfdbfa3f3827e0340e8eb7992042","r":["cee1415e71bbcef43ca55aa592fe4c5547f62a43869e5f52f9fcfb336b36ac18","419da6ed106585d35919e3200d8a7ec7e26f6046f6a6808ee34f9a2082fcba13"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["cee1415e71bbcef43ca55aa592fe4c5547f62a43869e5f52f9fcfb336b36ac18","419da6ed106585d35919e3200d8a7ec7e26f6046f6a6808ee34f9a2082fcba13"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"459fd54a95ebf6d3009d660b9f5839fe96f577cffaeff613a8f15aad0ef7af1b","r":["774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb","d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"]}]},{"pair":"G,3G","u1":5,"u2":3,"len":3,"rows":8,"Q":["499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4","cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"c38f0185d3d25d8591d4b675e631fa6130744aeb7c9ecf24e3d77eac4a68e558","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"d4a8533bfabeb318e1adc52e9831c72a34f250d69b1d9c06866f35f620249160","r":["499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4","cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b"]}]},{"pair":"G,3G","u1":5,"u2":4,"len":3,"rows":7,"Q":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e8c044534047ec1492f7009a2f1e2eac7d4a4307b6faa3d4e6b2777d301d3fa2","r":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"9c5edfd8f76cd91d4f7da9ac9472abc694c1ded1f5e692b08a4b87e413a7bbea","r":["4d63805afd1307c951bfd9b0ac5e4b5a7e717c3cf79ba68b15e7963fec2565a4","0fed027fdc0f72045d9d26f00d190753b72a7050d9b9ba6b923f1279bcc49c81"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["4d63805afd1307c951bfd9b0ac5e4b5a7e717c3cf79ba68b15e7963fec2565a4","0fed027fdc0f72045d9d26f00d190753b72a7050d9b9ba6b923f1279bcc49c81"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"66b700ad859969b04702415d901261441d510c6fd94f76a3fcd40e3e2377dd6d","r":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"]}]},{"pair":"G,3G","u1":5,"u2":5,"len":3,"rows":7,"Q":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e8c044534047ec1492f7009a2f1e2eac7d4a4307b6faa3d4e6b2777d301d3fa2","r":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"c6d559ed870e100654e109768aa474ab8338baac403507382e5971261ce92640","r":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["7227a7ede3bed376afc6b1f44e4dd7fa163461578ba97b06c51a37043d42060b","99b96864961cddb84837131f84ba6d0f07f8a49b11552f855146329d1769d71f"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"6e54c4de2a3f9d4039a23a6167d7ac98b83b03a89d687d22c01ffe1984f73d14","r":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"]}]},{"pair":"G,3G","u1":5,"u2":6,"len":3,"rows":8,"Q":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"4ad0a146b53cc8c5fd4a3151cf0889ee49e5122c908b3ddf6bc46ae9fe0fa478","r":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"f19ad4eba6bc1144e8dfe078968982b4cab265de494ce140eaf2445341487b4b","r":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"e4e37ab2dcca1765cb2812a38955b379a6a4c983923413b52b1a24fa3fba4e89","r":["18545ebcd3c0fe4da07f9a4bbf6eedd9a53eeebace45dc09b6cf40d8be84545c","bd939e2b0b532ede389dc97be60a17d88cce8e4f3828467bdb6eadad46c0a47c"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["18545ebcd3c0fe4da07f9a4bbf6eedd9a53eeebace45dc09b6cf40d8be84545c","bd939e2b0b532ede389dc97be60a17d88cce8e4f3828467bdb6eadad46c0a47c"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"92b40d641eb506a16aae72673807831e1bb04e252b261f1b528e133376164512","r":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"]}]},{"pair":"G,3G","u1":5,"u2":7,"len":3,"rows":8,"Q":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"4ad0a146b53cc8c5fd4a3151cf0889ee49e5122c908b3ddf6bc46ae9fe0fa478","r":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["d6fc1c764288018df3730e62bb15836e429dd5203d0bcc7c4d63202a3c78267b","dcf248ebc7b425518e4888e7b11d0153dc5757112f133e040713b7524cfeef29"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"f19ad4eba6bc1144e8dfe078968982b4cab265de494ce140eaf2445341487b4b","r":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"29bee7b124b3d2cd4fd28b5e98acb0018a5bc7aa5994ea85019f95c3b586cea1","r":["fa4caa550fc1e9bce702cd6ddadfabb51e99f902a6ffeb2c10af887fb28f3246","947d278538c714d96523a45d5959718a425da4f23963900f7e553451e1f841f3"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["fa4caa550fc1e9bce702cd6ddadfabb51e99f902a6ffeb2c10af887fb28f3246","947d278538c714d96523a45d5959718a425da4f23963900f7e553451e1f841f3"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"7c8adf293c4b9b8243d69eb9fcc13f4fe60eaa7683383f373cbe18a34bc82b6b","r":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"]}]},{"pair":"G,3G","u1":5,"u2":8,"len":4,"rows":9,"Q":["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":3,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"1d1a1360f8a73daba141a1777169e990b322c29d9ff5cf4709cf25eb940c073c","r":["bbe4f4ce5daa6f8efbfab222eb8306ee6e6405738de7d102de39a93d73aae01f","2676a47c5d7bb7c13617d0ad08c71e5e3c39dc72fee7c3803eeb213fdc971dfd"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["bbe4f4ce5daa6f8efbfab222eb8306ee6e6405738de7d102de39a93d73aae01f","2676a47c5d7bb7c13617d0ad08c71e5e3c39dc72fee7c3803eeb213fdc971dfd"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"c838438e6c5802d441578977897f7971454326f79aa26e2edbd79929f2b64cf9","r":["d8c4354ce93d658173251b6d00fa0de539c11fd3d28dfeb2b94d45aca3797681","f585b6656a1f54daa545723bae8634854ddc31fa297d3f202dea3cd1ff3b2150"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["d8c4354ce93d658173251b6d00fa0de539c11fd3d28dfeb2b94d45aca3797681","f585b6656a1f54daa545723bae8634854ddc31fa297d3f202dea3cd1ff3b2150"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"84bf94a757b933d1c98d8c9d025668661e007248887e793fdfd4cfc1188e1457","r":["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"]}]},{"pair":"G,3G","u1":5,"u2":9,"len":4,"rows":9,"Q":["d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65","95038d9d0ae3d5c3b3d6dec9e98380651f760cc364ed819605b3ff1f24106ab9"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":5,"u2":10,"len":4,"rows":10,"Q":["605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479","02972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":5,"u2":11,"len":4,"rows":10,"Q":["b699a30e6e184cdfa88ac16c7d80bffd38e2e1fc705821ea69cd5fdf1691fff7","d505700c51d860ce5a096ee637ebed3bd9d7268126c76a16b745bc318a51ab04"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":5,"u2":12,"len":4,"rows":9,"Q":["7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb","0d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":5,"u2":13,"len":4,"rows":9,"Q":["5d045857332d5b9e541514731622af8d60c180165d971a61e06b70a9b3834765","db2ba972802d45fd2decbab8d098a8c2a1d1f34761c6cf261879a7cabf06fb68"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":5,"u2":14,"len":4,"rows":10,"Q":["77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74","958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":5,"u2":15,"len":4,"rows":10,"Q":["29757774cc6f3be1d5f1774aefa8f02e50bc64404230e7a67e8fde79bd559a9a","c39d07337ddc9268a0eba45a7a41876d151b423eac4033b550bd28c17c470134"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":5,"u2":16,"len":5,"rows":10,"Q":["f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247","cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":6,"u2":1,"len":3,"rows":8,"Q":["acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe","cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"79f6b1528da78357307bbb0d56411c775da3261db1a7430ee7a27de896f5e038","r":["467cefa356a1237f3a3a04e78eabe2a7ec2d7cd3c7887f83acdf9aa3d085cf7f","38175fa5092072e924ffbe5347be0a9dbb5bf4e9fc41c09cee14d6e454012652"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["467cefa356a1237f3a3a04e78eabe2a7ec2d7cd3c7887f83acdf9aa3d085cf7f","38175fa5092072e924ffbe5347be0a9dbb5bf4e9fc41c09cee14d6e454012652"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"20a42fae63677ac3a36db55f151e8d1e4faebd8449945a9000fdfd147f4a6857","r":["38183cf0676643489395f04765e687368f73caf460658939800558db1a814730","e580881423bd80b306cb4f1b9df8558daf40e142d8c3a1e7cffd67621e70546d"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["38183cf0676643489395f04765e687368f73caf460658939800558db1a814730","e580881423bd80b306cb4f1b9df8558daf40e142d8c3a1e7cffd67621e70546d"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"31911d7098aee97c4158e63f798dcc845f5121ba20c270d5660cac32d0bfa0eb","r":["dd75d36c8976df90fb691eb4b40abcbec896148ea45cff81636426b22caa7d1f","791f729b591ec0bbaafbc1aa429f0778270545009f1c09329aab7643aa6eb8d7"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["dd75d36c8976df90fb691eb4b40abcbec896148ea45cff81636426b22caa7d1f","791f729b591ec0bbaafbc1aa429f0778270545009f1c09329aab7643aa6eb8d7"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"f426d77fd9b52f7847db8f73012ebd4a6f27dcfc01c9c093863f610edee50f40","r":["acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe","cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37"]}]},{"pair":"G,3G","u1":6,"u2":2,"len":3,"rows":7,"Q":["d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a","a9f34ffdc815e0d7a8b64537e17bd81579238c5dd9a86d526b051b13f4062327"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"70e11be53053673944b19cb9fcccd90a4931d6e1c16b275653414459c711084a","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"f4a57344695cb3ca84c42ed1e545a7d7c64fd066cf2165dcda0ba5eef5ceeb10","r":["d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a","a9f34ffdc815e0d7a8b64537e17bd81579238c5dd9a86d526b051b13f4062327"]}]},{"pair":"G,3G","u1":6,"u2":3,"len":3,"rows":8,"Q":["d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e","581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"70e11be53053673944b19cb9fcccd90a4931d6e1c16b275653414459c711084a","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"e45059d422914ccd7a137bdd6f6b08c453ae28270f8ea2a54a3f58621c59a3d2","r":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"97e38b99a75a51f49bd47019f684ee6704421f3a13eb6b062500e604b63edaab","r":["d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e","581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"]}]},{"pair":"G,3G","u1":6,"u2":4,"len":3,"rows":7,"Q":["5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc","c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"981d276e318a330f24fa20bdaff6617f7e772ecfa38cf1d9fff34a353580e327","r":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d076cfea243053c8ffbba7ff82ca93fa2774c88c44d5cc49e4aa8cc44f290958","r":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"3740c5e4d2ed85526d24fe79b80e0e5ceb90d79a6a3f530a5892fd7fe99d9a98","r":["5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc","c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58"]}]},{"pair":"G,3G","u1":6,"u2":5,"len":3,"rows":8,"Q":["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"981d276e318a330f24fa20bdaff6617f7e772ecfa38cf1d9fff34a353580e327","r":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d076cfea243053c8ffbba7ff82ca93fa2774c88c44d5cc49e4aa8cc44f290958","r":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"fa0fb0a6463165ab10540c5f98d9544109a62cf5b32a743e4e3df73cf87344d3","r":["194f208b8d80020144054adc6c374c822f9bddc44140309a804e1ca5d9d4217d","1c524bb907d93061674b534ded35f35df9c64c638fa769086457e96bf0658576"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["194f208b8d80020144054adc6c374c822f9bddc44140309a804e1ca5d9d4217d","1c524bb907d93061674b534ded35f35df9c64c638fa769086457e96bf0658576"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"e6c6bbfaa482d308c4642983d3d0acf5b69fea92d16c5bf87b75d71cb09f9916","r":["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"]}]},{"pair":"G,3G","u1":6,"u2":6,"len":3,"rows":7,"Q":["fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce","6851de067ff24a68d3ab47e09d72998101dc88e36b4a9d22978ed2fbcf58c5bf"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"39b697dfbcda19fd61500b911025f17da993c0b1944ae2bb3af0cb55fb4d2868","r":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e7f325b633184d55f51f62122093aa2cb35dbfab6a1399339fef25eb865edaab","r":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"35de2d3c70cb70bb34b25f340365057698a16ae25b4d1331b15e5620f52fafc6","r":["fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce","6851de067ff24a68d3ab47e09d72998101dc88e36b4a9d22978ed2fbcf58c5bf"]}]},{"pair":"G,3G","u1":6,"u2":7,"len":3,"rows":8,"Q":["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"39b697dfbcda19fd61500b911025f17da993c0b1944ae2bb3af0cb55fb4d2868","r":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e7f325b633184d55f51f62122093aa2cb35dbfab6a1399339fef25eb865edaab","r":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"a16d51e619afc49f4d9dc880f66ab12971021e09b0ecdf06d82f8fa008503bcf","r":["3ec11dfc52f2c37fc9923a020e83aeab1548ff6e89485a5c89eaa9e39b65e20a","9d9d738fe824338abc8cda356fbe6050aa708d2baf64001d4db66b749354e3cc"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["3ec11dfc52f2c37fc9923a020e83aeab1548ff6e89485a5c89eaa9e39b65e20a","9d9d738fe824338abc8cda356fbe6050aa708d2baf64001d4db66b749354e3cc"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"aa7b3f1ea212e7baddde8e2fa300c9e72401bbc5f154e3c98962900105857381","r":["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"]}]},{"pair":"G,3G","u1":6,"u2":8,"len":4,"rows":9,"Q":["6d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00","acb82eb93309ad1cc739ddfa33604a83776238aa0bd5ff248dbac47a17f388fb"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":3,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"628a90d2cabe087687ce9c570c0d6e63ec360a4d8ddf2dd2d49cb8c97ba3d353","r":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"701970edac3fe7342cfc483add587c0043ee022c2b4e30eb9f22892d691d9fee","r":["4f22dfb8f594a91ca8c2f91d95f999aa68e81aae3279f1c2e6b847b3aaaf995f","f8a9aa4374345d421665cd29a7aaf35c11a0943a96d88c3399cd33f0e45f3bb0"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["4f22dfb8f594a91ca8c2f91d95f999aa68e81aae3279f1c2e6b847b3aaaf995f","f8a9aa4374345d421665cd29a7aaf35c11a0943a96d88c3399cd33f0e45f3bb0"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"fc93b5d15921ad534e1f97ee57e5162dec4779aac06b01f6d656cd1f5638e9ad","r":["6d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00","acb82eb93309ad1cc739ddfa33604a83776238aa0bd5ff248dbac47a17f388fb"]}]},{"pair":"G,3G","u1":6,"u2":9,"len":4,"rows":10,"Q":["1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5","b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":6,"u2":10,"len":4,"rows":9,"Q":["e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9","76d458642a2c93adee7a347a5e4681f9bb5b10f4bd8aa51edfd6e3f50e7da3ac"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":6,"u2":11,"len":4,"rows":10,"Q":["80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f","1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":6,"u2":12,"len":4,"rows":9,"Q":["fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af","07b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":6,"u2":13,"len":4,"rows":10,"Q":["049370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963","758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":6,"u2":14,"len":4,"rows":9,"Q":["6eca335d9645307db441656ef4e65b4bfc579b27452bebc19bd870aa1118e5c3","d50123b57a7a0710592f579074b875a03a496a3a3bf8ec34498a2f7805a08668"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":6,"u2":15,"len":4,"rows":10,"Q":["463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b","5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":6,"u2":16,"len":5,"rows":10,"Q":["4fdcb8fa639cee441c8331fd47a2e5ff3447be24500ca7a5249971067c1d506b","25a5208b674bfd4cae4d91eb555010aa422cc82409d5079690f3743d00fdaefb"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":7,"u2":1,"len":3,"rows":8,"Q":["a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7","893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"79f6b1528da78357307bbb0d56411c775da3261db1a7430ee7a27de896f5e038","r":["467cefa356a1237f3a3a04e78eabe2a7ec2d7cd3c7887f83acdf9aa3d085cf7f","38175fa5092072e924ffbe5347be0a9dbb5bf4e9fc41c09cee14d6e454012652"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["467cefa356a1237f3a3a04e78eabe2a7ec2d7cd3c7887f83acdf9aa3d085cf7f","38175fa5092072e924ffbe5347be0a9dbb5bf4e9fc41c09cee14d6e454012652"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"20a42fae63677ac3a36db55f151e8d1e4faebd8449945a9000fdfd147f4a6857","r":["38183cf0676643489395f04765e687368f73caf460658939800558db1a814730","e580881423bd80b306cb4f1b9df8558daf40e142d8c3a1e7cffd67621e70546d"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["38183cf0676643489395f04765e687368f73caf460658939800558db1a814730","e580881423bd80b306cb4f1b9df8558daf40e142d8c3a1e7cffd67621e70546d"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"ab4bf93024b5cf6453d0f53449c08f971df77d11fd21e208b320a961728898a2","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"16e82000847bc1a13858822e4f3ccc15e72764c980f29e115dea42e6fdfd74c8","r":["a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7","893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"]}]},{"pair":"G,3G","u1":7,"u2":2,"len":3,"rows":8,"Q":["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"70e11be53053673944b19cb9fcccd90a4931d6e1c16b275653414459c711084a","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"5c8ce5308c4ce3f61f66094c26d7d12132f5439c7430011aa866d1d61fa19fef","r":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"1c529b23c3b4850c5c6bb02c11fa2b787b3680e6b02a1d7d1a86d0fad0bf698e","r":["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"]}]},{"pair":"G,3G","u1":7,"u2":3,"len":3,"rows":8,"Q":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"70e11be53053673944b19cb9fcccd90a4931d6e1c16b275653414459c711084a","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"208dc0383aa4fff2fdb4bb5c3c70b064fceb6bfe6100f3004352dbfc33f69d4d","r":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["d361cbc4d8e64e1177778782fdfdc5c2e96010daae9ad81339f500671989d47a","e6e6119110b918e288088d450aeebb44d73f24ecd7a83b534b1e075ff41f2a26"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"f0a81a6ba01362cdca979a555c348faae10098660fe3eb9ea1f5011a1f16be7b","r":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"47b883ec2a60236bee54b15d79b911d60dcd7b251369c71f06144773108e25ee","r":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"]}]},{"pair":"G,3G","u1":7,"u2":4,"len":3,"rows":8,"Q":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"981d276e318a330f24fa20bdaff6617f7e772ecfa38cf1d9fff34a353580e327","r":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d076cfea243053c8ffbba7ff82ca93fa2774c88c44d5cc49e4aa8cc44f290958","r":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"d3d06ce6cee7ba2a0ee6eea43fe206068af171e1ee03a69a705adbb6149eb3de","r":["b4b9621839906a69ca9eacbd250a9bc06277de113e0fb8d94caced2fbab32e86","b4c4a8149989f0a40cb9ff41b4eaeac5823204cddc3f037fbee0c078fb3a413f"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["b4b9621839906a69ca9eacbd250a9bc06277de113e0fb8d94caced2fbab32e86","b4c4a8149989f0a40cb9ff41b4eaeac5823204cddc3f037fbee0c078fb3a413f"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"705f3dd2619e404b5ed1d6125bb435fe019b9d1c4ed617b6f7bab4448bafd168","r":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"]}]},{"pair":"G,3G","u1":7,"u2":5,"len":3,"rows":8,"Q":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"981d276e318a330f24fa20bdaff6617f7e772ecfa38cf1d9fff34a353580e327","r":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["e7f334b70e592190fa86027ac07881f2390820fe33aa89d952bb876c6d2b5bff","3960f70a51d50fbbe6d44635312cd7a38e6aa7e62b9c2b05f219fb2373cc5855"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d076cfea243053c8ffbba7ff82ca93fa2774c88c44d5cc49e4aa8cc44f290958","r":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["50e40269eaae769296b0a347536f68c85bbc6b605d37be201b89df925cc8fdf9","6fe4d89589740fec5f97dcc035ab8c579314e8aa79a37aba7fcc5b2faf5cfdf9"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"83fa601fabd3e894d4d83777ff8d7b4814e66aef799f1fac3fc492527726a2c0","r":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["954ac54f24f98eee793ae200999e32b46150fd3da5f1e1c32416b9dba6f312b0","de93c5aae42be12a8ed1e043c6ef3a3325eeeb992b1f530986da2724a340c040"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"02d4efd6fe966ace5a97b87479060a4785f88ef49409e1dfda815a3eda76ac4d","r":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"]}]},{"pair":"G,3G","u1":7,"u2":6,"len":3,"rows":8,"Q":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"39b697dfbcda19fd61500b911025f17da993c0b1944ae2bb3af0cb55fb4d2868","r":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e7f325b633184d55f51f62122093aa2cb35dbfab6a1399339fef25eb865edaab","r":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"9d1244549fc4f024d55e665239533ebb3cfbdc44bb1092c0466ea98153daff4a","r":["a3acdacae08c9a248465af126d5e1bfaf6063662579200ee1583177fb96c61d6","f1095be42913d22b6d71c2cbd9848ed6f584e0b1189adb676886cfd9c8d529d8"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["a3acdacae08c9a248465af126d5e1bfaf6063662579200ee1583177fb96c61d6","f1095be42913d22b6d71c2cbd9848ed6f584e0b1189adb676886cfd9c8d529d8"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"2d8122de83e5ce7707fd6ccee8dba1029b01ad657eceef61dcc5d319985ce21b","r":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"]}]},{"pair":"G,3G","u1":7,"u2":7,"len":3,"rows":8,"Q":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":2,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":1,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"AddP12","round":1,"op":1,"d1":1,"d2":1,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"39b697dfbcda19fd61500b911025f17da993c0b1944ae2bb3af0cb55fb4d2868","r":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":1,"a":["8f6d595d082babe16691238a15e7f30bbe82eac571c2968ebb11b5124faf901b","f41ac0efad87414e2fe7edbe5c337f97ae56f0ea7dbd5d15b29f584060b5d2d3"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e7f325b633184d55f51f62122093aa2cb35dbfab6a1399339fef25eb865edaab","r":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"]},{"sel":"AddP12","round":0,"op":1,"d1":1,"d2":1,"a":["0eb558b7fbc6779fa9bf4a2e563b4ac271e112267ceae322e91b28ab5043fe3c","2ef9c7d945b22a11a39f2400c10c70a159e2cd23cf6193f581c04e2090be5253"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"be511f2e5bed895c467e006fbb0c1d6e0c4eba58aa6d38e2f248e2c41d7db461","r":["864fabab9a43c8102981477adcd78c4f726b56942405774a26740230e48e1d6c","0ddc7141bfe17defcbf991b1a274d4e55e62d7bcb7c69e9bf2ce68e1aaf68667"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["864fabab9a43c8102981477adcd78c4f726b56942405774a26740230e48e1d6c","0ddc7141bfe17defcbf991b1a274d4e55e62d7bcb7c69e9bf2ce68e1aaf68667"],"addend":["8b9c4ebc6954e99651b3f0d8ec9990be08d89e432e79270c89949774dbea0a83","1ee854bd85920fa65d89e7e0c4f22a88d0d26a4a71a42a1cb8a5f4c0c36f69fc"],"lam":"f2d81f600b018d0a90addffe67b0b9da708f1755425011a1838782b3bda0c671","r":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"]}]},{"pair":"G,3G","u1":7,"u2":8,"len":4,"rows":10,"Q":["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":0,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP2","round":3,"op":1,"d1":0,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"37e65f3a65df5aedfefa1edd1875c338a56ac8b65b42e7b7cfe14dbbac6e6825","r":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"]},{"sel":"Double","round":2,"op":0,"d1":1,"d2":0,"a":["130853b5be8f016d30f3ab7a85346e192358857c056af3963a148f85fd925ace","ebc97051056d4e673104acee289725d699ca4c79c19ce512eac0f60e5aa1392c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"03a29285a9ab5b7281d526986ac02dfefefd9ae5c95301c25169a0bc77282b84","r":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"]},{"sel":"AddP1","round":2,"op":1,"d1":1,"d2":0,"a":["2ed875a409e3a44f587d78c08a27a86ebd127dfd2d70b2c952495e3e18a749cf","d0dc69dfc850e39fa19eeb74872884888ee7b7afa77bc3404d211caa263371d8"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"df7809cea2dda6b7a03d450fc7396b1914a107bcb5e560a21e090dcb3ac06618","r":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"]},{"sel":"Double","round":1,"op":0,"d1":1,"d2":0,"a":["77dc3df83d6df78d372be465f0195b593ea3441c31bbbb5643603156fcaa2a19","b4bfb174855e62082105d9abaf8d223bf40436aa7822ca324ba0d24a4c96673d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e2ba41a1d0dc927a202d13906986c7be9dbb1480380281ea84a67ca86684c62c","r":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"]},{"sel":"AddP1","round":1,"op":1,"d1":1,"d2":0,"a":["81fb85405da6e630620eade49f8252e94ece31e0a090954b78cebd56b56d1960","143d56457634e957d753e50a2957be04b52868a06dc70d7ac01d5543f0765244"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"628a90d2cabe087687ce9c570c0d6e63ec360a4d8ddf2dd2d49cb8c97ba3d353","r":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"]},{"sel":"Double","round":0,"op":0,"d1":1,"d2":0,"a":["0c89cf4e1220f94b377234a905162f5a04c5e169539201d9aee3f477e5e36e4f","6928044bc2dedf4141d93675029e0dfa2b6052531a16633cf5ffa5475e427095"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"701970edac3fe7342cfc483add587c0043ee022c2b4e30eb9f22892d691d9fee","r":["4f22dfb8f594a91ca8c2f91d95f999aa68e81aae3279f1c2e6b847b3aaaf995f","f8a9aa4374345d421665cd29a7aaf35c11a0943a96d88c3399cd33f0e45f3bb0"]},{"sel":"AddP1","round":0,"op":1,"d1":1,"d2":0,"a":["4f22dfb8f594a91ca8c2f91d95f999aa68e81aae3279f1c2e6b847b3aaaf995f","f8a9aa4374345d421665cd29a7aaf35c11a0943a96d88c3399cd33f0e45f3bb0"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"be3965d5c29bfa1679405e778387ad5b98ef9d5d7293a796f86ed7ff267172fe","r":["aaff9dad1433bab7886765aced68cb5274c775828cae277e5636afdb4726d459","9c066e6f344cfc20313246593b2ed673a7d039a7453da76799af00d6c149c7bc"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["aaff9dad1433bab7886765aced68cb5274c775828cae277e5636afdb4726d459","9c066e6f344cfc20313246593b2ed673a7d039a7453da76799af00d6c149c7bc"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"d250a10c5df4c4ed51382337b70297cc67dae3b4505a0673f60c89624dfec26c","r":["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"]}]},{"pair":"G,3G","u1":7,"u2":9,"len":4,"rows":10,"Q":["1be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11","bebc47511ade7308b3ca6265f9400779c076329c75146bc6ff1822f5d1f30e79"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":7,"u2":10,"len":4,"rows":10,"Q":["62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d","80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":7,"u2":11,"len":4,"rows":10,"Q":["91de2f6bb67b11139f0e21203041bf080eacf59a33d99cd9f1929141bb0b4d0b","eb9ef6c031eed31de34e7a1009f8725155b03158202a9d3e9a9a2e83124a7899"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":7,"u2":12,"len":4,"rows":10,"Q":["d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9","eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":7,"u2":13,"len":4,"rows":10,"Q":["f8b0b03d44112259f903b3d100e3950d980fdde9c7e85701c16baedc90235717","bd8e9dc301d9adc96be1883b362f123bd0a986928ac79972517ab5c246242203"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":7,"u2":14,"len":4,"rows":10,"Q":["f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530","e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":7,"u2":15,"len":4,"rows":10,"Q":["2b22efda32491a9e0294339ca3da761f7d36cfc8814c1b29ca731921025ff695","7ed520327080a9fa4c16662fc134fadcc7048846d46ade0030b83fd19adc87cd"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":7,"u2":16,"len":5,"rows":11,"Q":["caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1","cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":8,"u2":1,"len":4,"rows":8,"Q":["774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb","d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":3,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":0,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d1f5843a309274d88b1525b96bdcbfef8a6320c0c691152b26b41b4003bc51e3","r":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"b01c2ca6187b26dc9c1a9e312727cbb948d78b44f503de5011a9c2df8dca0081","r":["9552c8b2657dfcc7173da74dbdd5a4c8146050c4183872f96db28337c350ad12","13d95ea031df1cec7f8f9d9726054470789f71dcd26deed8ced6e744c0118d07"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["9552c8b2657dfcc7173da74dbdd5a4c8146050c4183872f96db28337c350ad12","13d95ea031df1cec7f8f9d9726054470789f71dcd26deed8ced6e744c0118d07"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"e88744b5aac41fe0a8c1634aca7776c25bd097629a701fd8a62abc32556bf40f","r":["854d40d5b01d5d0bc97d0dc781e759b0f700f11c84a2c9e1050b0c85ceb71a5e","ed433ca827a62bbdd75dac8257e16b29e8d425678b39cfdca6024f9b8678f937"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["854d40d5b01d5d0bc97d0dc781e759b0f700f11c84a2c9e1050b0c85ceb71a5e","ed433ca827a62bbdd75dac8257e16b29e8d425678b39cfdca6024f9b8678f937"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"c342834b05b13731757b599c5f5c6968e286b9784ad8abe26b60ae04d77e3838","r":["774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb","d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"]}]},{"pair":"G,3G","u1":8,"u2":2,"len":4,"rows":8,"Q":["499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4","cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":3,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":0,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d1f5843a309274d88b1525b96bdcbfef8a6320c0c691152b26b41b4003bc51e3","r":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"31a7ddd22bc353e9cbb274b6f764095d6f9e29411b6850724b86f46cb469a5e2","r":["33959bad375a41d7e453bc691b0f90f8d5117e68de2e52284b820e7168409cfe","dd1a183666d11f070e33eaeb456a2a9da99c8e508b4eb23b7229c6b5cf091e8d"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["33959bad375a41d7e453bc691b0f90f8d5117e68de2e52284b820e7168409cfe","dd1a183666d11f070e33eaeb456a2a9da99c8e508b4eb23b7229c6b5cf091e8d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bbc5daf97a90895c2df1cfff68af301b2136348e486fc01617bda21077146931","r":["a697c30d72fa8916a687bd454287e59e48b2321b6af277aecf9bc2a548272097","2c6c0225dc11d100dd0d5fe2436b0e3b44136ecd0b1e51154f42e41a84411347"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["a697c30d72fa8916a687bd454287e59e48b2321b6af277aecf9bc2a548272097","2c6c0225dc11d100dd0d5fe2436b0e3b44136ecd0b1e51154f42e41a84411347"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"3f3a01c9bc1bddbb8e26e7f2c8fe153fa84d2c63a38aeeb1fb7370e69238a106","r":["499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4","cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b"]}]},{"pair":"G,3G","u1":8,"u2":3,"len":4,"rows":9,"Q":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":3,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":0,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"d1f5843a309274d88b1525b96bdcbfef8a6320c0c691152b26b41b4003bc51e3","r":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["539dab53ad2555c1ee15167a7144380500499459e3a6e505a5cf7dbd0870b745","a0c5c011016b53d24c6633ad2e38e3d4bb7f4710dc1bc8c0c02e7902b936369c"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"31a7ddd22bc353e9cbb274b6f764095d6f9e29411b6850724b86f46cb469a5e2","r":["33959bad375a41d7e453bc691b0f90f8d5117e68de2e52284b820e7168409cfe","dd1a183666d11f070e33eaeb456a2a9da99c8e508b4eb23b7229c6b5cf091e8d"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["33959bad375a41d7e453bc691b0f90f8d5117e68de2e52284b820e7168409cfe","dd1a183666d11f070e33eaeb456a2a9da99c8e508b4eb23b7229c6b5cf091e8d"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bbc5daf97a90895c2df1cfff68af301b2136348e486fc01617bda21077146931","r":["a697c30d72fa8916a687bd454287e59e48b2321b6af277aecf9bc2a548272097","2c6c0225dc11d100dd0d5fe2436b0e3b44136ecd0b1e51154f42e41a84411347"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["a697c30d72fa8916a687bd454287e59e48b2321b6af277aecf9bc2a548272097","2c6c0225dc11d100dd0d5fe2436b0e3b44136ecd0b1e51154f42e41a84411347"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"240dd94afe47330eb35f0a222a3fdc0c18d0d6bbcf72e1d7835a0b363aabc744","r":["e0f18a53e8af6c31c5e9cbba6e7f7954f8d85cb9329c6c117deb2c4cb6f0fade","5d54e4478230df029f9017c859be8fb941e452ab0aabb00a2036db1a8b22309a"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["e0f18a53e8af6c31c5e9cbba6e7f7954f8d85cb9329c6c117deb2c4cb6f0fade","5d54e4478230df029f9017c859be8fb941e452ab0aabb00a2036db1a8b22309a"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"bb0c9fc66679592d2cd8e0a4763e38aeab5863bbfb397e4a43418e02f8ff1db9","r":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"]}]},{"pair":"G,3G","u1":8,"u2":4,"len":4,"rows":8,"Q":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":3,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"886e5d22bed3bd3088e6b98a0099297f6a1a625973ec93b524292e62f3f2ad36","r":["8bac0dc04f2ee419c61e08a80a7a722be78ab4bda89431d55656814ecc10d864","77d4b05ca7ee63b7959d2dc87a070a2ae35bc6ad2ff2f2a03638fbbac2630c80"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["8bac0dc04f2ee419c61e08a80a7a722be78ab4bda89431d55656814ecc10d864","77d4b05ca7ee63b7959d2dc87a070a2ae35bc6ad2ff2f2a03638fbbac2630c80"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"c8cc15b16c9a4e03262b2e328c1fa5bce436072579c89b5d68d676d54d9eb20a","r":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"]}]},{"pair":"G,3G","u1":8,"u2":5,"len":4,"rows":9,"Q":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":3,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"886e5d22bed3bd3088e6b98a0099297f6a1a625973ec93b524292e62f3f2ad36","r":["8bac0dc04f2ee419c61e08a80a7a722be78ab4bda89431d55656814ecc10d864","77d4b05ca7ee63b7959d2dc87a070a2ae35bc6ad2ff2f2a03638fbbac2630c80"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["8bac0dc04f2ee419c61e08a80a7a722be78ab4bda89431d55656814ecc10d864","77d4b05ca7ee63b7959d2dc87a070a2ae35bc6ad2ff2f2a03638fbbac2630c80"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"1ad021b33d5e946500c0ecd258be8582a85643fcd2f3788512eb7ed0d5f7ae7e","r":["057a79c5ebb2de94ccfb0544473b32634a2d3fc592eadbb9a09c3f9aa1239877","1ca88d5f08ec9cbe2301e74274e9f65d989366ccfcfd33482c680c7e0e1d8bae"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["057a79c5ebb2de94ccfb0544473b32634a2d3fc592eadbb9a09c3f9aa1239877","1ca88d5f08ec9cbe2301e74274e9f65d989366ccfcfd33482c680c7e0e1d8bae"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"8cfdcbd6e81e4526e7a0a01e5d3d85f71c26d06e140921c71af9e04c85724207","r":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"]}]},{"pair":"G,3G","u1":8,"u2":6,"len":4,"rows":9,"Q":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":3,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"a0e6b647e668fd7983e20264fc01f572212469cad3f3e8c2b4c1178ed56b02cc","r":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"9cb986b8510536151d4c8ae927ba47b7e4735b6077357e4a8964bd0d188d929a","r":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"824efac08e3651f0dfa480cc1568d2923dbd358481303dcec5c59addeae6de8e","r":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"]}]},{"pair":"G,3G","u1":8,"u2":7,"len":4,"rows":10,"Q":["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":0,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP1","round":3,"op":1,"d1":1,"d2":0,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"lam":"528cbe8e8523cb19d0e72a3caca5ce72635e8248f5242a4c06e047a20999d1a4","r":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":1,"a":["95748d7c17186c78b9eddffd7154854560d878ae9afbe913b1dbe82a26ebfc83","df1cc83e9aceb6925f44cb9240c505838df60097b12cabaad9f8a5eb77ad5798"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"5ae41f655cb2138cd45d50f5f33d7a3114b157c26f50c7edf20501efe9a9fe67","r":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"]},{"sel":"AddP2","round":2,"op":1,"d1":0,"d2":1,"a":["b7c9ddf5c074c0b5d44e48def5597b29fd293f3c0ea13b98a3ac7cda11a43e2b","532ddb93d33cb5472d7ee9702bd0ca9aa35ab1e5c68f7bde19a3cf040625c681"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"46b94b0634c16b06f393f66848afda480bdecc6426aeebe93665fae7073c0830","r":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":1,"a":["8a03f907bcc95e63a7b2cb7cacbfe8e04c0a1970b6192f1d3f22ea40c1d1803c","48814ce6fdead63873f47f1b7adf23f7d8f136eb302e84373bb3e9d7a04faa42"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"34fb8e0a18067b1d35fa5606cc5765643661e725c17b7839b4bd131f1d5d02de","r":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"]},{"sel":"AddP2","round":1,"op":1,"d1":0,"d2":1,"a":["2a1b6b1fea1bea8ce96f7f268d9c53dacca93a5d009451694bf7299c463488b1","66e4851a1f1500da1007bf68bc94cbea1d37d23e6ebad8354771b1722aecb3eb"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"a0e6b647e668fd7983e20264fc01f572212469cad3f3e8c2b4c1178ed56b02cc","r":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":1,"a":["a0fc7169b5ed709b0d53913abf9e2ccfc931c467524b4de042002a929e626c14","d192471c29405380ad819e90404f63696f428eb28039a5a33c19f9c4a7ae4bae"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"9cb986b8510536151d4c8ae927ba47b7e4735b6077357e4a8964bd0d188d929a","r":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"]},{"sel":"AddP2","round":0,"op":1,"d1":0,"d2":1,"a":["71d7ce0d80238bf754f5bb06b20f75eef60ccb1fc24de280b1dd4f3a568232a8","ce9631f9a401b11fb3686a191e1c55d8bccab447c951c707200f1b8fcc6d022d"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"926163de2f2666cbdbb84f47a46600f3df91dcd09f7e81f6fe7cba3977b64eed","r":["d8c4354ce93d658173251b6d00fa0de539c11fd3d28dfeb2b94d45aca3797681","f585b6656a1f54daa545723bae8634854ddc31fa297d3f202dea3cd1ff3b2150"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["d8c4354ce93d658173251b6d00fa0de539c11fd3d28dfeb2b94d45aca3797681","f585b6656a1f54daa545723bae8634854ddc31fa297d3f202dea3cd1ff3b2150"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"84bf94a757b933d1c98d8c9d025668661e007248887e793fdfd4cfc1188e1457","r":["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"]}]},{"pair":"G,3G","u1":8,"u2":8,"len":4,"rows":7,"Q":["d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65","95038d9d0ae3d5c3b3d6dec9e98380651f760cc364ed819605b3ff1f24106ab9"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Correction","schedule":[{"sel":"Precompute","round":0,"op":1,"d1":0,"d2":0,"a":["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"],"addend":["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],"lam":"01e76498623c9bf4359a24f6aa81177b87cc933e25f168b1a5e88351136f7a36","r":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"]},{"sel":"Double","round":3,"op":0,"d1":1,"d2":1,"a":["af319aa90f91a86b297de85edb330a665efba79aa98893db1b49070cb1ae7864","1481a038143c0732071db0bcf3b05b8ca2e624fa217d82193f3c254a606277a0"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"6d099536da51dcd12afd20a815b6281eeb574f33eb9f2b1a269001c80f51ea56","r":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"]},{"sel":"AddP12","round":3,"op":1,"d1":1,"d2":1,"a":["8492b362486c354169292ebf0b65114587965fc0907c7fba9c01773e14b4608f","7b0fe7722ff12007acb518352589c7012872ab1a2b123502d2d7e278c207a543"],"addend":["e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13","51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"],"lam":"6427d20d5d07415db555cf4117fb6e4e621882bb021e0d50cb1b27974106e801","r":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"]},{"sel":"Double","round":2,"op":0,"d1":0,"d2":0,"a":["c77004c1b9bfc2e419812ce13f0462154297b3bd16bb52e60b932e8df01fb4a5","b4dc5b5f63ab2b225d22e91cc7701305c4c002ccb21e23279df572e00869d928"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"bc2ac7263748adca97b83a50cccc66e19b8cf7be80362498e545692d45f494d6","r":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"]},{"sel":"Double","round":1,"op":0,"d1":0,"d2":0,"a":["008999b688ad29760b400086057c60437fcc7a5650236cb1c4675f14ffeffef6","ad73abaee4fb687e5eb37a6cec8cc8d23a9c98ec266dec706e39770af7e7d735"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"e8c044534047ec1492f7009a2f1e2eac7d4a4307b6faa3d4e6b2777d301d3fa2","r":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"]},{"sel":"Double","round":0,"op":0,"d1":0,"d2":0,"a":["ca14f64f1a39ff475afe25c3f2583e472065cdff911094af3c875148b2c3bfcb","b9fe7c991e229a6d3df9f6ebf2da31e460e7450058cdc9b6872c76f544d51288"],"addend":["0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000"],"lam":"a1859f8acc91d4d959015f3b7c678f7bf1049d261537ac4b680d1763f48a6fde","r":["efb500757cd904bcbbb4aa69617935105c1b5f0f2c0ab291b7aa8a4d4a2fdfba","595cfa130877a2a9724f442a1a46bb6839f9e8efdd7eb36eea500f5c074fe928"]},{"sel":"Correction","round":0,"op":1,"d1":0,"d2":0,"a":["efb500757cd904bcbbb4aa69617935105c1b5f0f2c0ab291b7aa8a4d4a2fdfba","595cfa130877a2a9724f442a1a46bb6839f9e8efdd7eb36eea500f5c074fe928"],"addend":["ce8baddbf91b89d7479556d11c315b2e9ea28f366615d8a4e81ab9825a682f03","fcb68824a16f35a68a264240980b86645ca97fffb48c1c25f9e5f0c456eb76d3"],"lam":"faba9e7c1c521648222d1a4b2b94cb4210472fdf096fd01b9c8960c1d53a8855","r":["d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65","95038d9d0ae3d5c3b3d6dec9e98380651f760cc364ed819605b3ff1f24106ab9"]}]},{"pair":"G,3G","u1":8,"u2":9,"len":4,"rows":8,"Q":["605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479","02972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":8,"u2":10,"len":4,"rows":8,"Q":["b699a30e6e184cdfa88ac16c7d80bffd38e2e1fc705821ea69cd5fdf1691fff7","d505700c51d860ce5a096ee637ebed3bd9d7268126c76a16b745bc318a51ab04"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":8,"u2":11,"len":4,"rows":9,"Q":["7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb","0d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":8,"u2":12,"len":4,"rows":8,"Q":["5d045857332d5b9e541514731622af8d60c180165d971a61e06b70a9b3834765","db2ba972802d45fd2decbab8d098a8c2a1d1f34761c6cf261879a7cabf06fb68"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,Correction"},{"pair":"G,3G","u1":8,"u2":13,"len":4,"rows":9,"Q":["77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74","958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":8,"u2":14,"len":4,"rows":9,"Q":["29757774cc6f3be1d5f1774aefa8f02e50bc64404230e7a67e8fde79bd559a9a","c39d07337ddc9268a0eba45a7a41876d151b423eac4033b550bd28c17c470134"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":8,"u2":15,"len":4,"rows":10,"Q":["f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247","cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":8,"u2":16,"len":5,"rows":9,"Q":["bce74de6d5f98dc027740c2bbff05b6aafe5fd8d103f827e48894a2bd3460117","5bea1fa17a41b115525a3e7dbf0d8d5a4f7ce5c6fc73a6f4f216512417c9f6b4"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,Correction"},{"pair":"G,3G","u1":9,"u2":1,"len":4,"rows":8,"Q":["d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a","a9f34ffdc815e0d7a8b64537e17bd81579238c5dd9a86d526b051b13f4062327"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":2,"len":4,"rows":9,"Q":["d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e","581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":9,"u2":3,"len":4,"rows":9,"Q":["5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc","c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":4,"len":4,"rows":9,"Q":["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":9,"u2":5,"len":4,"rows":9,"Q":["fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce","6851de067ff24a68d3ab47e09d72998101dc88e36b4a9d22978ed2fbcf58c5bf"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":6,"len":4,"rows":10,"Q":["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":9,"u2":7,"len":4,"rows":10,"Q":["6d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00","acb82eb93309ad1cc739ddfa33604a83776238aa0bd5ff248dbac47a17f388fb"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":8,"len":4,"rows":8,"Q":["1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5","b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":9,"u2":9,"len":4,"rows":8,"Q":["e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9","76d458642a2c93adee7a347a5e4681f9bb5b10f4bd8aa51edfd6e3f50e7da3ac"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":10,"len":4,"rows":9,"Q":["80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f","1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":9,"u2":11,"len":4,"rows":9,"Q":["fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af","07b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":12,"len":4,"rows":9,"Q":["049370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963","758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":9,"u2":13,"len":4,"rows":9,"Q":["6eca335d9645307db441656ef4e65b4bfc579b27452bebc19bd870aa1118e5c3","d50123b57a7a0710592f579074b875a03a496a3a3bf8ec34498a2f7805a08668"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":14,"len":4,"rows":10,"Q":["463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b","5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":9,"u2":15,"len":4,"rows":10,"Q":["4fdcb8fa639cee441c8331fd47a2e5ff3447be24500ca7a5249971067c1d506b","25a5208b674bfd4cae4d91eb555010aa422cc82409d5079690f3743d00fdaefb"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":9,"u2":16,"len":5,"rows":10,"Q":["2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120","4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":10,"u2":1,"len":4,"rows":9,"Q":["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","0ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":2,"len":4,"rows":8,"Q":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":10,"u2":3,"len":4,"rows":9,"Q":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":4,"len":4,"rows":9,"Q":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":10,"u2":5,"len":4,"rows":10,"Q":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":6,"len":4,"rows":9,"Q":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":10,"u2":7,"len":4,"rows":10,"Q":["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":8,"len":4,"rows":8,"Q":["1be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11","bebc47511ade7308b3ca6265f9400779c076329c75146bc6ff1822f5d1f30e79"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":10,"u2":9,"len":4,"rows":9,"Q":["62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d","80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":10,"len":4,"rows":8,"Q":["91de2f6bb67b11139f0e21203041bf080eacf59a33d99cd9f1929141bb0b4d0b","eb9ef6c031eed31de34e7a1009f8725155b03158202a9d3e9a9a2e83124a7899"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":10,"u2":11,"len":4,"rows":9,"Q":["d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9","eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":12,"len":4,"rows":9,"Q":["f8b0b03d44112259f903b3d100e3950d980fdde9c7e85701c16baedc90235717","bd8e9dc301d9adc96be1883b362f123bd0a986928ac79972517ab5c246242203"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":10,"u2":13,"len":4,"rows":10,"Q":["f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530","e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":14,"len":4,"rows":9,"Q":["2b22efda32491a9e0294339ca3da761f7d36cfc8814c1b29ca731921025ff695","7ed520327080a9fa4c16662fc134fadcc7048846d46ade0030b83fd19adc87cd"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":10,"u2":15,"len":4,"rows":10,"Q":["caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1","cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":10,"u2":16,"len":5,"rows":10,"Q":["45562f033698faca1540cbc9bf962cf4764c1ef4094ee4b6742b761c49b46d3b","9403d11a2b419edaacf931bfbd9c32a264558508362bc5fc99025ec62b034e02"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":11,"u2":1,"len":4,"rows":9,"Q":["499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4","cac2f6c4b54e855190f044e4a7b3d464464279c27a3f95bcc65f40d403a13f5b"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":2,"len":4,"rows":9,"Q":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":11,"u2":3,"len":4,"rows":9,"Q":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":4,"len":4,"rows":10,"Q":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":11,"u2":5,"len":4,"rows":10,"Q":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":6,"len":4,"rows":10,"Q":["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":11,"u2":7,"len":4,"rows":10,"Q":["d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65","95038d9d0ae3d5c3b3d6dec9e98380651f760cc364ed819605b3ff1f24106ab9"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":8,"len":4,"rows":9,"Q":["605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479","02972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":11,"u2":9,"len":4,"rows":9,"Q":["b699a30e6e184cdfa88ac16c7d80bffd38e2e1fc705821ea69cd5fdf1691fff7","d505700c51d860ce5a096ee637ebed3bd9d7268126c76a16b745bc318a51ab04"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":10,"len":4,"rows":9,"Q":["7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb","0d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":11,"u2":11,"len":4,"rows":9,"Q":["5d045857332d5b9e541514731622af8d60c180165d971a61e06b70a9b3834765","db2ba972802d45fd2decbab8d098a8c2a1d1f34761c6cf261879a7cabf06fb68"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":12,"len":4,"rows":10,"Q":["77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74","958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":11,"u2":13,"len":4,"rows":10,"Q":["29757774cc6f3be1d5f1774aefa8f02e50bc64404230e7a67e8fde79bd559a9a","c39d07337ddc9268a0eba45a7a41876d151b423eac4033b550bd28c17c470134"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":14,"len":4,"rows":10,"Q":["f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247","cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":11,"u2":15,"len":4,"rows":10,"Q":["bce74de6d5f98dc027740c2bbff05b6aafe5fd8d103f827e48894a2bd3460117","5bea1fa17a41b115525a3e7dbf0d8d5a4f7ce5c6fc73a6f4f216512417c9f6b4"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":11,"u2":16,"len":5,"rows":11,"Q":["7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435","091b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":12,"u2":1,"len":4,"rows":9,"Q":["d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e","581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":2,"len":4,"rows":9,"Q":["5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc","c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":12,"u2":3,"len":4,"rows":10,"Q":["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":4,"len":4,"rows":8,"Q":["fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce","6851de067ff24a68d3ab47e09d72998101dc88e36b4a9d22978ed2fbcf58c5bf"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,Correction"},{"pair":"G,3G","u1":12,"u2":5,"len":4,"rows":9,"Q":["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":6,"len":4,"rows":9,"Q":["6d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00","acb82eb93309ad1cc739ddfa33604a83776238aa0bd5ff248dbac47a17f388fb"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":12,"u2":7,"len":4,"rows":10,"Q":["1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5","b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":8,"len":4,"rows":8,"Q":["e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9","76d458642a2c93adee7a347a5e4681f9bb5b10f4bd8aa51edfd6e3f50e7da3ac"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,Correction"},{"pair":"G,3G","u1":12,"u2":9,"len":4,"rows":9,"Q":["80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f","1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":10,"len":4,"rows":9,"Q":["fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af","07b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":12,"u2":11,"len":4,"rows":10,"Q":["049370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963","758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":12,"len":4,"rows":8,"Q":["6eca335d9645307db441656ef4e65b4bfc579b27452bebc19bd870aa1118e5c3","d50123b57a7a0710592f579074b875a03a496a3a3bf8ec34498a2f7805a08668"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,Correction"},{"pair":"G,3G","u1":12,"u2":13,"len":4,"rows":9,"Q":["463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b","5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":14,"len":4,"rows":9,"Q":["4fdcb8fa639cee441c8331fd47a2e5ff3447be24500ca7a5249971067c1d506b","25a5208b674bfd4cae4d91eb555010aa422cc82409d5079690f3743d00fdaefb"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":12,"u2":15,"len":4,"rows":10,"Q":["2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120","4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":12,"u2":16,"len":5,"rows":10,"Q":["01257e93a78a5b7d8fe0cf28ff1d8822350c778ac8a30e57d2acfc4d5fb8c192","1124ec11c77d356e042dad154e1116eda7cc69244f295166b54e3d341904a1a7"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,Correction"},{"pair":"G,3G","u1":13,"u2":1,"len":4,"rows":9,"Q":["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":2,"len":4,"rows":10,"Q":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":13,"u2":3,"len":4,"rows":10,"Q":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":4,"len":4,"rows":9,"Q":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":13,"u2":5,"len":4,"rows":9,"Q":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":6,"len":4,"rows":10,"Q":["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":13,"u2":7,"len":4,"rows":10,"Q":["1be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11","bebc47511ade7308b3ca6265f9400779c076329c75146bc6ff1822f5d1f30e79"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":8,"len":4,"rows":9,"Q":["62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d","80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":13,"u2":9,"len":4,"rows":9,"Q":["91de2f6bb67b11139f0e21203041bf080eacf59a33d99cd9f1929141bb0b4d0b","eb9ef6c031eed31de34e7a1009f8725155b03158202a9d3e9a9a2e83124a7899"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":10,"len":4,"rows":10,"Q":["d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9","eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":13,"u2":11,"len":4,"rows":10,"Q":["f8b0b03d44112259f903b3d100e3950d980fdde9c7e85701c16baedc90235717","bd8e9dc301d9adc96be1883b362f123bd0a986928ac79972517ab5c246242203"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":12,"len":4,"rows":9,"Q":["f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530","e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":13,"u2":13,"len":4,"rows":9,"Q":["2b22efda32491a9e0294339ca3da761f7d36cfc8814c1b29ca731921025ff695","7ed520327080a9fa4c16662fc134fadcc7048846d46ade0030b83fd19adc87cd"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":14,"len":4,"rows":10,"Q":["caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1","cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,3G","u1":13,"u2":15,"len":4,"rows":10,"Q":["45562f033698faca1540cbc9bf962cf4764c1ef4094ee4b6742b761c49b46d3b","9403d11a2b419edaacf931bfbd9c32a264558508362bc5fc99025ec62b034e02"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,3G","u1":13,"u2":16,"len":5,"rows":11,"Q":["754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18","0673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,3G","u1":14,"u2":1,"len":4,"rows":10,"Q":["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":2,"len":4,"rows":9,"Q":["4ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97","12ba26dcb10ec1625da61fa10a844c676162948271d96967450288ee9233dc3a"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":14,"u2":3,"len":4,"rows":10,"Q":["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","02de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":4,"len":4,"rows":9,"Q":["6687cdb5b650d558f40cbdefc8e40997c03fe1b2abb840885e5cad81710c4c8a","3fd502b3111178b11a1fa873825c72000ef8e529f033f272b32e83b25c83ad64"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":14,"u2":5,"len":4,"rows":10,"Q":["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":6,"len":4,"rows":9,"Q":["d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65","95038d9d0ae3d5c3b3d6dec9e98380651f760cc364ed819605b3ff1f24106ab9"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":14,"u2":7,"len":4,"rows":10,"Q":["605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479","02972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":8,"len":4,"rows":9,"Q":["b699a30e6e184cdfa88ac16c7d80bffd38e2e1fc705821ea69cd5fdf1691fff7","d505700c51d860ce5a096ee637ebed3bd9d7268126c76a16b745bc318a51ab04"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":14,"u2":9,"len":4,"rows":10,"Q":["7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb","0d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":10,"len":4,"rows":9,"Q":["5d045857332d5b9e541514731622af8d60c180165d971a61e06b70a9b3834765","db2ba972802d45fd2decbab8d098a8c2a1d1f34761c6cf261879a7cabf06fb68"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":14,"u2":11,"len":4,"rows":10,"Q":["77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74","958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":12,"len":4,"rows":9,"Q":["29757774cc6f3be1d5f1774aefa8f02e50bc64404230e7a67e8fde79bd559a9a","c39d07337ddc9268a0eba45a7a41876d151b423eac4033b550bd28c17c470134"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":14,"u2":13,"len":4,"rows":10,"Q":["f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247","cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":14,"len":4,"rows":9,"Q":["bce74de6d5f98dc027740c2bbff05b6aafe5fd8d103f827e48894a2bd3460117","5bea1fa17a41b115525a3e7dbf0d8d5a4f7ce5c6fc73a6f4f216512417c9f6b4"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,3G","u1":14,"u2":15,"len":4,"rows":10,"Q":["7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435","091b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,3G","u1":14,"u2":16,"len":5,"rows":11,"Q":["108443b948d1553584a271333f7fbd043c4d66a91706edecbf07f6894c04f299","4e7b5daba34fbcf9f055520d4db8c49fd60282d32adfca555b04403db9581a9f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,3G","u1":15,"u2":1,"len":4,"rows":10,"Q":["5601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc","c136c1dc0cbeb930e9e298043589351d81d8e0bc736ae2a1f5192e5e8b061d58"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":2,"len":4,"rows":10,"Q":["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":15,"u2":3,"len":4,"rows":10,"Q":["fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce","6851de067ff24a68d3ab47e09d72998101dc88e36b4a9d22978ed2fbcf58c5bf"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":4,"len":4,"rows":10,"Q":["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":15,"u2":5,"len":4,"rows":10,"Q":["6d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00","acb82eb93309ad1cc739ddfa33604a83776238aa0bd5ff248dbac47a17f388fb"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":6,"len":4,"rows":10,"Q":["1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5","b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":15,"u2":7,"len":4,"rows":10,"Q":["e0392cfa338aaf2f0b56c563e3e5e67a5d5fefe3388f85d90c899da20f0198f9","76d458642a2c93adee7a347a5e4681f9bb5b10f4bd8aa51edfd6e3f50e7da3ac"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":8,"len":4,"rows":10,"Q":["80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f","1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":15,"u2":9,"len":4,"rows":10,"Q":["fe8d1eb1bcb3432b1db5833ff5f2226d9cb5e65cee430558c18ed3a3c86ce1af","07b158f244cd0de2134ac7c1d371cffbfae4db40801a2572e531c573cda9b5b4"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":10,"len":4,"rows":10,"Q":["049370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963","758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":15,"u2":11,"len":4,"rows":10,"Q":["6eca335d9645307db441656ef4e65b4bfc579b27452bebc19bd870aa1118e5c3","d50123b57a7a0710592f579074b875a03a496a3a3bf8ec34498a2f7805a08668"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":12,"len":4,"rows":10,"Q":["463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b","5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":15,"u2":13,"len":4,"rows":10,"Q":["4fdcb8fa639cee441c8331fd47a2e5ff3447be24500ca7a5249971067c1d506b","25a5208b674bfd4cae4d91eb555010aa422cc82409d5079690f3743d00fdaefb"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":14,"len":4,"rows":10,"Q":["2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120","4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,3G","u1":15,"u2":15,"len":4,"rows":10,"Q":["01257e93a78a5b7d8fe0cf28ff1d8822350c778ac8a30e57d2acfc4d5fb8c192","1124ec11c77d356e042dad154e1116eda7cc69244f295166b54e3d341904a1a7"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,3G","u1":15,"u2":16,"len":5,"rows":12,"Q":["e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8","59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,3G","u1":16,"u2":1,"len":5,"rows":9,"Q":["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"],"shape":"Precompute,Double,AddP1,Double,Double,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":2,"len":5,"rows":9,"Q":["421f5fc9a21065445c96fdb91c0c1e2f2431741c72713b4b99ddcb316f31e9fc","2b90f16d11dabdb616f6db7e225d1e14743034b37b223115db20717ad1cd6781"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":16,"u2":3,"len":5,"rows":10,"Q":["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":4,"len":5,"rows":9,"Q":["55eb67d7b7238a70a7fa6f64d5dc3c826b31536da6eb344dc39a66f904f97968","7d916a47b2b581400b1e718bf404258540973bce1c95052dd0689f2f493be3c8"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,Correction"},{"pair":"G,3G","u1":16,"u2":5,"len":5,"rows":10,"Q":["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":6,"len":5,"rows":10,"Q":["1be68a5a028f2601d0e80d468c344ba331d611b96c358b6032e8b4da0547fc11","bebc47511ade7308b3ca6265f9400779c076329c75146bc6ff1822f5d1f30e79"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":16,"u2":7,"len":5,"rows":11,"Q":["62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d","80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":8,"len":5,"rows":9,"Q":["91de2f6bb67b11139f0e21203041bf080eacf59a33d99cd9f1929141bb0b4d0b","eb9ef6c031eed31de34e7a1009f8725155b03158202a9d3e9a9a2e83124a7899"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,Correction"},{"pair":"G,3G","u1":16,"u2":9,"len":5,"rows":10,"Q":["d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9","eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":10,"len":5,"rows":10,"Q":["f8b0b03d44112259f903b3d100e3950d980fdde9c7e85701c16baedc90235717","bd8e9dc301d9adc96be1883b362f123bd0a986928ac79972517ab5c246242203"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":16,"u2":11,"len":5,"rows":11,"Q":["f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530","e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":12,"len":5,"rows":10,"Q":["2b22efda32491a9e0294339ca3da761f7d36cfc8814c1b29ca731921025ff695","7ed520327080a9fa4c16662fc134fadcc7048846d46ade0030b83fd19adc87cd"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,Correction"},{"pair":"G,3G","u1":16,"u2":13,"len":5,"rows":11,"Q":["caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1","cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":14,"len":5,"rows":11,"Q":["45562f033698faca1540cbc9bf962cf4764c1ef4094ee4b6742b761c49b46d3b","9403d11a2b419edaacf931bfbd9c32a264558508362bc5fc99025ec62b034e02"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,3G","u1":16,"u2":15,"len":5,"rows":12,"Q":["754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18","0673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,3G","u1":16,"u2":16,"len":5,"rows":8,"Q":["bf23c1542d16eab70b1051eaf832823cfc4c6f1dcdbafd81e37918e6f874ef8b","5cb3866fc33003737ad928a0ba5392e4c522fc54811e2f784dc37efe66831d9f"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Double,Correction"},{"pair":"G,R0","u1":1,"u2":1,"len":1,"rows":4,"Q":["e6a50f6dbac63d32b1fc7f35d06f3ec1a0fca1e7805892b6d9df9aa606378b83","8574b5a33469a90c2cb2b96107c4eb6f0af9bac2e43615a2f089bf5c8f772cd1"],"shape":"Precompute,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":2,"len":2,"rows":6,"Q":["00b0e3bdf996136ef001a852501dce92835cffca3364f412362c079fa45a4af5","883dd562635c01c6d671bf0c764b77b5b48e6862e0d0631e2758f50732dd07c5"],"shape":"Precompute,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":1,"u2":3,"len":2,"rows":6,"Q":["1b3946c1d32bb35145d0567fe0600534f6909671f8802774c0b1b4ef42a2249b","0b9c59d360bf8cedfc8c2d69e8229d6acd7861a22350ed4e98f3cc35cc92ed15"],"shape":"Precompute,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":4,"len":3,"rows":7,"Q":["0b281c7b3367465fac216100405173f5407c2ff7b6feb7df0093ecd9e64f26ba","e0296b06f9583b72498e1fdd321930891d0a37709a4d3990fcd7fa30ef85441f"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":1,"u2":5,"len":3,"rows":7,"Q":["835e2010c1734f8b4c43f1aca88f8bce6f3aeb103fbb7a3510e8648537cc0024","bc725145d79f0673f62ee4a74694ef541bab1b75a262c572bd5ff54fdf3e6690"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":6,"len":3,"rows":8,"Q":["39b0828bfb9a36cccb81361e686997a0f6048e0d2c580fadbe8d7e76cb853774","ede4472d3cf3187c79ff6d0c843fda3634b71680bc2cab61f8cb079583a9c402"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":1,"u2":7,"len":3,"rows":8,"Q":["62c26514fb353b22521fda6aac26b8eb90f1a131c866951f144843534769576e","c091f2d1786f791c08c52392aca6b8ae9bac62f353ec74c895ad61d7129fecbb"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":8,"len":4,"rows":8,"Q":["9f4e5f7b586fcd712f04b78755052fb36ff4974e51f28131423210ab99fb449f","57f3bebff0748194e36e300714e090098c335a728afa2ac94c28030a6cbb283c"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":1,"u2":9,"len":4,"rows":8,"Q":["d7fe39f0504b8ff39afd6259c8de7c967ef8ed2a20e345adb0bd816f72e38c15","f9bb501f11d11b4c6114427810e24ead983c5de8448b052e8fc6ed4ac87b7975"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":10,"len":4,"rows":9,"Q":["a8f7f016ed769cc319ec01402e5ebfe51153be374074cafc3e3d46dec2aed8ea","5c4154a8e868b74b0a927f41c195bc3398d98c4d582326ff3f7a357477e6dbd3"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":1,"u2":11,"len":4,"rows":9,"Q":["ad7eeec2cb2abf50e917289496a5eca5df4b46d91447bab914b6576222f4e34d","3ccfa2ba6376667ed5e61cbb69217a944caf9a574e1d679b85c32772d2456d8f"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":12,"len":4,"rows":9,"Q":["54aab8459680baac072b958b3a860bff0c66997c6b14f008d258b3b3870fdaef","9a580cb94bd0637a7d90364adc584e55a2524ec96554cb5f3e0e1e0d071e6ad6"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":1,"u2":13,"len":4,"rows":9,"Q":["34f112203f7bcc866b3430f8f467f4f692a17cc5560d475dc97fc911e81eb72f","dbb7a90b909650abd196a5d205ab7679c8589aa8c1698b8b289caace9427c794"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":14,"len":4,"rows":10,"Q":["8e403ca0f93b3b6df2504cd377191fd8f927f1bf849795659db374079dfd2ec8","2beb94874cf7e64e8eed1957c92c9b43dc45a139945418c9cab860846b34f96b"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":1,"u2":15,"len":4,"rows":10,"Q":["fafa9bb167677a3054f544c4199b063fe35e6e8718c53e12c5daaa5521624792","1ffb4ad8ae57e53f1455d9a7c1e06bd591c8a198bff564db20cdc7ae743ef020"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":1,"u2":16,"len":5,"rows":9,"Q":["80e8a2af32cb1c00317ab0da02dfa0780d78dc7aa054e7b0caf1eea70c2fb78c","9388a075a337391922801b45f83cb30de5d6b480bf77ed88370cc15516f30504"],"shape":"Precompute,Double,AddP2,Double,Double,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":2,"u2":1,"len":2,"rows":6,"Q":["88eb9f52b8a42cd4ef52ff38153f6fa01c8093fbb8ce6121ac1e6b285f78e6b5","c87e20fed7899212d44cc6e2be02a83fe40262c8f9da18b361f49dd283b7df15"],"shape":"Precompute,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":2,"len":2,"rows":5,"Q":["6fa522b766032a0800ed04c52fcd174d139800f0c7ebe8bd646dc2c41414754b","94ed2a80ac057be523fcaa11358b07c4b464ea8adbadb2062a47e0e942c07a8d"],"shape":"Precompute,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":2,"u2":3,"len":2,"rows":6,"Q":["52da0e5ebbc64d8d6b92ae630e35d23967211fa6bc4be916f3354a7ec1e92b22","03d1ad98cfba92501bc514851aa2afad71c8c04c620f53954ea7ae04f3f5c82d"],"shape":"Precompute,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":4,"len":3,"rows":7,"Q":["0406918548533836313c09d16d4efd9a9378a76d676015687804b52ae7cd73c4","b1815ec6edbc4c04b64ab0cc53854c82a4d2943f2ecc3d4cc277b18648394d00"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":2,"u2":5,"len":3,"rows":8,"Q":["eadb1c1f2e6d5c9fe41e933ed85fe8636d5c5221a05ce579d0565258ee7a5cab","ad6b917f14d99a1d4fa0b474dc56710de40f25addf418aeb17da65770e6acf4d"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":6,"len":3,"rows":7,"Q":["66cf06438d4144a757b1a1ed5f86a4e868eb4d523bb8ef80949cda943a08b51f","a782e3b0ce10bfdaa8ef9d8ad916123125db52ef55a967ec5807c70acd39133c"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":2,"u2":7,"len":3,"rows":8,"Q":["7ffa0760fad86e0f3b26cae874085d4fae6e33dba9ff2dfb9ecfb1799220ebba","aeb89f2a141fdbfbb4fd1ed89e8e6879d247db232e982d2142aea0b4c4c6d931"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":8,"len":4,"rows":8,"Q":["766418051f335206534a82c6c368f6a40f05ba533ff8bdccc1ac323e809a791e","be3a6e802f8bdad116a9bac4ab14bf76fc9b5d2fac111bd641b61c3c363f68bd"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":2,"u2":9,"len":4,"rows":9,"Q":["6aa57e7f77c238c78f61c3a739788ee4e6e18f03452ff25495abce912985ff3a","826f40990aed85b8292c650d5fb1836e49a2b77f0fe3e28e832b75d0bd58dcf8"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":10,"len":4,"rows":8,"Q":["23164c8dd1ce16240a71b052f5eb43acdcf3e9792752ec793deb76043eabd152","db813d0e651c8133a08cf52208ed45434740d48b21377da41aefc322b261538f"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":2,"u2":11,"len":4,"rows":9,"Q":["bdaf2371dbbd442f5c3f054abf4d6f75bd2988ddda8564577cfb189c12b12ec1","c71e4ca09dc4da418a1c2f3bb634d501300eb6aeb030a5d961868570ae6df40d"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":12,"len":4,"rows":9,"Q":["95c52deebb41a9bba3fd72ba6f2c517aea7ebfef0d4ec30c1f238fcadb6ee7d8","400c0a3007f85cb649bf24f36852868f6464ff5cddabf1af7e64aacde6f5015c"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":2,"u2":13,"len":4,"rows":10,"Q":["8ac05e27f26d53f06c7dbb7c5aeafd3ef7907a4d379178e50a0b241dd63d3aaa","2a701e214c842ee1c5ef87ded42ce7aea3678870cb7d7effb33c1c78f69342f3"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":14,"len":4,"rows":9,"Q":["7f1a5a4b3e2598dfeb6ddbeaba9cd721c702b815c8c6a354757058a784309043","350757b9bf976012b07035412cffdca274dea28870576df37f317a270a7c0aa2"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":2,"u2":15,"len":4,"rows":10,"Q":["0ebe83fdfb1e6913d849154f10784cbf51ae4aa49a95805aede3396a69f71c73","61cf148c0712b3b0f0d71a6161417c9ac6dfa1bc9aab6e6a2f07497dbd0407a8"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":2,"u2":16,"len":5,"rows":9,"Q":["8f7ac5b6633f84081d80fd3aaaa9591d932ea63ead24ce2e08c0b138642dd8e3","0669c00262305d56fb6c191df1301addda7dd14964802d8c2d698846a18c7de2"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":3,"u2":1,"len":2,"rows":6,"Q":["9ab55c7a863f6ffbc939d8132bd058604f17b8f785adba909496bc5e7db6e257","74c9eab7f04051a83b544c6dfa95b520317126aaf564eaf93e753372ef74ca9f"],"shape":"Precompute,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":2,"len":2,"rows":6,"Q":["e81f512e8698c13bb418a31058ba362ccc8248f4fbc714f9b9f23eeede7abbf4","23d71fca7c3983701f6c2e8957648f68673d64add73d6a79132035128d748379"],"shape":"Precompute,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":3,"u2":3,"len":2,"rows":6,"Q":["6ac4e5c444df755201c7a24ec94eb18fd8cab814438c5dd34aa4da1bea2b7109","b96fe2c9f492156c497640ed1f2d4a0a61e1371a6873da317bf56da5bfd49a6c"],"shape":"Precompute,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":4,"len":3,"rows":8,"Q":["57fc487fdf62eef32f2a72a63fe7e7929e10a0013971eda4d8024bd13589b688","1c80f2688192c25a705232f7e217004b547d0437643d0f71d1836b409d3bf078"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":3,"u2":5,"len":3,"rows":8,"Q":["483c48021a09e4b5aa9e30e5f58ac3345410d4aeed0ec94b63bd5628a0b1988e","626bf03a76f73d5698b74f7192e1e6822334da278a2d0c39a62d504bc66c961c"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":6,"len":3,"rows":8,"Q":["5de5f9f192b990335fee445465f56b9eb440769c00863cbcd060984aa9f16641","df1ab77ccb4fd127a4fba6da1ccdcfaac4540884ed6befb543bd7c2f9e8aeea8"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":3,"u2":7,"len":3,"rows":8,"Q":["48e3fb583b7d25bbdc4dabe4fb390dd23bb9254cec1c5f4fd8bf21dfba741d62","401e1041a07a92b53254b791ddd5f70b17c0d699624405d8be91c172706bdfbd"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":8,"len":4,"rows":9,"Q":["4e962dc5d88c9fce2e257de76f255159c68c39d04981e487c45f1d8ab6349ca6","7598deefaee482f9bd337c97f5324a6a2481af837b39b3a0df2c48726089d852"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":3,"u2":9,"len":4,"rows":9,"Q":["03c2bb5c0ea6ad6c5aae51cfb179401231b8bf45ac1dfd57aae97637ac619c4a","0dba615b4401a2bbbd45cd2352ed6f86189ad3694ace31728ed809661b23643c"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":10,"len":4,"rows":9,"Q":["215dd142690d0cfb8b29f759a66b0e6efee0ee4e0299f13ff4cf7dd8bae09fa8","edde4c5cc7a9a27069e03825ef56fb030dbe1fcc4ab4c4f6c455f10c1eceb5b4"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":3,"u2":11,"len":4,"rows":9,"Q":["91fffb8f5000bbbd0b90e73b3f5a3e9111380f32ee9124311fb42b93fb5d370a","4ebede02a306d007c2a1733df3a8f9e7ad6aa26c2867c0112d96164852df1563"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":12,"len":4,"rows":10,"Q":["c3d2bffb55f76c4885d205fd40201bbf129c7df043c0797f975198713e27ca14","5618ca9ddb43dfe32f485762bedeadd6e7d9b21e8811992c445180bc3d480c6d"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":3,"u2":13,"len":4,"rows":10,"Q":["3896c983bc9d30a6b06496e9bef6675ebb1b0899a18bb49399e4e32e72a81aaa","07668ecb14a5d99fb98b09ae0652f4ce894409484f2ed0e27e8f989337e4d9aa"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":14,"len":4,"rows":10,"Q":["09d375c6d2866009ca83dc80bfc81f6817bab572e2738ccfaec1cb70210ccbdc","2610b08d42089dee331bb0f0147320496bfc9ca47e80f8aa16fc89784b3d5db9"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":3,"u2":15,"len":4,"rows":10,"Q":["d9fdc9af08e314debe5ce02ea8d46c29d206b41a2561fefe45c105c744401d5e","cd49426071cb22ad3d22f58990b80b3d90902e735a4774ee74bd431f5f46479e"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":3,"u2":16,"len":5,"rows":10,"Q":["6eb812269b32860ad3bf466e5f378cbd14c068246cf7c346fc51025b17bd418b","8ee0b5853162a1e76655605b51e190e5bdc0a0ae172b9197975c0322c416ebd0"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":4,"u2":1,"len":3,"rows":7,"Q":["170afe224ea8bbcafc1afc0921651e78e06dddb5b4c844f7b3476eaf8656ef5a","94dd50bde541cd3814b6d994e7802a65c78d973e4dec248f9c0d173cbbde4ba7"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":2,"len":3,"rows":7,"Q":["20182bed4e0baefe4b1c5cfc0a26d4cccb269ec82eab1f5a1cd07bbfa7e0eb5a","73c73ca26c1370b05af0f4111a766c593b8949c3b45c8e2b40fede5e87bd1ffb"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":4,"u2":3,"len":3,"rows":8,"Q":["db53b3d65c9d8cda13e253f7ad65d0706fa0d4fa5d21947560850fd2ccabbd20","943c29fdac8552f5fbb79f83df1fc21e09b1fd030184d0944c2708b76ad5ed6d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":4,"len":3,"rows":6,"Q":["5db3bf550b1fd821bc157b3d250592622adf7c7abd5be6aea92a7f9f0e9f2f83","6cfc017609706d52f03c80b44fae00b164552e64ce974d98e4a9263c4d631920"],"shape":"Precompute,Double,AddP12,Double,Double,Correction"},{"pair":"G,R0","u1":4,"u2":5,"len":3,"rows":7,"Q":["79144761593e8ec32cc7fc3f24d1f6a767a0c0b490e17671a76480662eb2b947","343d9b5f0a4be0ab307356f55f55a6f36fe496476a6a6fa5e6eb0dd0c7a65a0c"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":6,"len":3,"rows":7,"Q":["35cdba1352405b55340122ab7db77aeb8596499fc66cde00f798ed39255009c9","984aa9bfefc93a4b834b19b560a3a1dd039229afb9dea7bcc8dde0d232e89bdc"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":4,"u2":7,"len":3,"rows":8,"Q":["a9e4b6f5fba7298e589d64949e105cf7b53903a5e6fdbb45b215af7ae226d4da","557df9a1797e5a7663a6ae5e3307b41281c14e34144dfaa9ac84a927b309a24b"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":8,"len":4,"rows":8,"Q":["8ded1061fb6949b59715c4e262ef847692a363c5cbbe84e45a13ca7f15b2b9e9","f8f9df2ae2a5ce08b216966e0e107fcb0695c7b1d73cd3b4155882331407d902"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Correction"},{"pair":"G,R0","u1":4,"u2":9,"len":4,"rows":9,"Q":["e3685064acafde336fb07a3acf771eef7d8ef85f0ead59f3a280da67a128db5f","a36f27f10edefda86c6e3efe37aae96b9dcd0385a59281818555bb7a99bd535d"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":10,"len":4,"rows":9,"Q":["4952370d35e4a9d4679cb226111a42512154f722027b4b6c76fb49b6fcaa59da","b8bb3745732f74b8b537cce1d04f7b5952d572db6691803342675aeb3f57bbe9"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":4,"u2":11,"len":4,"rows":10,"Q":["a0366ddb3116194fac8a3b48ecf0cbb877ebdce38cbe79fcee7eeaced17e35bc","2a4bc013287361a5f62e359b00807a660bee2cf8b69e81dbab2d7265075a8f2c"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":12,"len":4,"rows":8,"Q":["1b0ce5e9dd286301a05003b85bb5070957d151d7dc141fc03fba84d341a4fe24","5fc8887be1287baf30d48e8e4633f1d0fcc3eb2b61f852c06175e8b33081f0d5"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,Correction"},{"pair":"G,R0","u1":4,"u2":13,"len":4,"rows":9,"Q":["cebd6cd39adcc22811058115e8e4096494ed80d75ca7bd61ac9744af34e2c831","ec12cb4cd56b969aafd2d39ef10bbf56e56a5e27f5459ee28fb93285b2683875"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":14,"len":4,"rows":9,"Q":["dab0f43d59b77c8df40e93a5fbdcb769daa1a9d53950c89d430892fc74498a32","6ce5d3413bdefd6a1c2c42575ac9f6fb90a7cd95bcb7cc1d8fe4cc75c709a90d"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":4,"u2":15,"len":4,"rows":10,"Q":["df283a542b7d479e8f273a256647716e7e131f0f06ca27ea5471d9ba06588302","a7cf274d69a5f90d06466c0712dddf2811fb2ece39df035809ec1bcb43ae7864"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":4,"u2":16,"len":5,"rows":9,"Q":["eaf84c93281edbd600eda1f749874c4ddaafaa6e7490c8b9891b5be683b4e80d","ee0ce42bf1fe24b27cf6d58ad66ff5c587fdb91a4ab7375ad7cd036e6ac12ee8"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,Correction"},{"pair":"G,R0","u1":5,"u2":1,"len":3,"rows":7,"Q":["2fac9cf458aa8e046d33d15d30c55d64807bb4be04c55694d563678cf45cdd16","c7fd2fd46bb8212056b4b61506238cdeca0639a066dec75e70df1c713867fe58"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":2,"len":3,"rows":8,"Q":["847284697099c1f03557fc0328da3c7e77fe5f030489c0074d3a35f12007d491","19ce5e23578ee6c2827664d3d5a6b1dc6acd5c578dfa229154f780554f1604ce"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":5,"u2":3,"len":3,"rows":8,"Q":["06ee0b8e2cf3d35fda08f4ee2c8b1a6d5949ad7927932081ac9764e17f16607f","3310ce20b69070234e9bb2dcc55bef9b1b5c7006c21d26636d68a310909c5e5d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":4,"len":3,"rows":7,"Q":["3057d5c3f951eca442495a1d515c411a1a82e441509dd43a3e3b9716f74675dd","c7254dd16024b849d83e319ebc392b3c34b3cc73c6d65f4a7f764f64c0fe32c1"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":5,"u2":5,"len":3,"rows":7,"Q":["bd31edb848e19e35cbae902a6caaa803345af0121a94db3ad48a56b6057f454f","a613de20621b87b0e5e35a1fbea33d04667aa7e5912e8063fb5e7f0964905833"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":6,"len":3,"rows":8,"Q":["d1d03739e6e0aa705b8d2de83d9ebe57d75f24688067154212a0dad9c7345a8b","1ef609fdb706e9257dd5c84ff23ba72d19373d18980f1197306f70577d77bcfd"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":5,"u2":7,"len":3,"rows":8,"Q":["f9bfadc3d2736b9c2dc8e2f5b23dad21eb28398d6a305931dfd89020f7b048df","9e3569ce4398c7b223bfe494e5cae2330e313dc613dc5f9787e914752b0a3197"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":8,"len":4,"rows":9,"Q":["ffb4e5953d00a5064e5d389d8594c53ebcc5f589668a0d1159cabe40a49c7eff","2702b2de299ee685717085531a0b2db01c3c26809d408e1d35a858e2a8c280b7"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":5,"u2":9,"len":4,"rows":9,"Q":["41157f5df5eb921641d20a6fe82e8eb3b9ba56023413200f5e1765b08a67c651","c40b14654eed8d03af29d6654a974f40308a6d8be652ce3352761cca3ce013ae"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":10,"len":4,"rows":10,"Q":["b5a79035fb7155310e170394fb9d80af16e27cc25e2591de90073053beb15325","892b7079c90edc1265ec153343a706520496ac82d017291754c9872196aa9046"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":5,"u2":11,"len":4,"rows":10,"Q":["b7ead445cedf83c110bad823cbe7fcb80ff88771e1948cf92ccfb0b1f50963c1","d2d2c8c81e2e4806e76ed5f59b9591da8f2b002c5ff4977d06b4a163e9ddad87"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":12,"len":4,"rows":9,"Q":["6e9a69302a518eaaeb4c27c8e0ddfea00be1d19ef84f65b24bd567f607a26261","e4b13cd34bd3e1f3a905af6166ff4ee49714328616036cbb5fcd74ebe4d7004c"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":5,"u2":13,"len":4,"rows":9,"Q":["524c2588af7f9d0226f2b5a0b7703f6c4d8f564e1099a4f4a43685a51a4d3748","033cab04bc9ec701623a7a87738015c0076e0559ef23c41216c280b99be2ddb1"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":14,"len":4,"rows":10,"Q":["363305f96623b1f7a938010ad720a3853e654f93a61ee6f2ecf188e089a5f172","719554cd13ffb4692705d60ad50c4d98668cb307bcfbce5bf56fba35fd01795a"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":5,"u2":15,"len":4,"rows":10,"Q":["51866cb1e0d848dcfcd98dea2850ee46a318de2eb30b013e868d85a11808fc4d","abe01d6a191b19cb543079fddb154784b48222823dfc638208e03064534ceef4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":5,"u2":16,"len":5,"rows":10,"Q":["83a1eb166d7a8e6488eed39708e9c62f81634480b1979351a7e579c051576dea","7e8250b493c5151cce82611a05e42e523252fff3f774b9023fc53c4f6a6c804d"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":6,"u2":1,"len":3,"rows":8,"Q":["99261bb410f9f420d63178cc813f5628a4ae7aaea6495a786a07b96ea8a2895b","0be257970ba5da4548e08be5605db470ebc6f72be7dd37aecdcd30ab19222cc7"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":2,"len":3,"rows":7,"Q":["9bb8f8c793cef83ab5cbd65fc70a73fcc67b6e6acdbab594736ba9cf18fab8ec","90aed77bf7ad53f8cdf710c298100b0c24dcac49b63e209a0e2915cdbd1e62f6"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":6,"u2":3,"len":3,"rows":8,"Q":["b217eb395ea306b130bad6d20a2c99a81aacbd0b949ccda99dace59375994305","84d84c27ddc4be48fa8f3c96fe87f62bc69e06d6a4de56cde93d5802c9a007c8"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":4,"len":3,"rows":7,"Q":["7cb22b9c62a571d5d2810bf8797ffa55eaad5202b91a7ea356055d25b8a1d7f3","8e7d8982db74c4e28e3db9794541b7410408c71b382678b4e08c3ad9c1c45fda"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":6,"u2":5,"len":3,"rows":8,"Q":["3bbb9ca9fd358a617a0398cbd58eda7c5fea85a76bbf60ef500df7c9795d274a","909c3098471884b859a646bc584107bb8ed6500bbe1cbeaa64c2ce0314271d2d"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":6,"len":3,"rows":7,"Q":["3280afc9d72de5b3b9c0de8876c3293a0173f850689ef6e531052052d6d4278a","8a2b97094b6fc7ac9e583de8e8596e151965965b84c235819ce7f06b382a9f4a"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":6,"u2":7,"len":3,"rows":8,"Q":["0e2b007007d07896ecea91bb17f0fe8b878ca73676ec7a7847866675ade3b0ee","3f8f8ef0f23f7441152e1d244ff25c9c82ce1bd2b48765935cc1637a84baa777"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":8,"len":4,"rows":9,"Q":["937847be8c8c83481530c00ad07a6d34f6ac2523892b73aaeef18eadd39cd841","f33348c76ee9d5e16aa7f64e6ac3fb94ef480b65da8e38afc05c1228f6b39693"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":6,"u2":9,"len":4,"rows":10,"Q":["b49d20f4a822c3da88ae0cf2d5ad197e677ffe1295bf9c591d141f0bd0d573c2","25a5e4b4d7f207c679a54f28d1f47c11469bdb8a64b53c72c78e44e1623ff726"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":10,"len":4,"rows":9,"Q":["6e59dad05d68981404d09f2ab5c8b04e97e22d1a65e58f318fc35c0a65448e38","9cdaa2dcb25580b02cbc1140c1244c751fa623a3b49b5d440ef2a17f6ead7063"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":6,"u2":11,"len":4,"rows":10,"Q":["e9bf6336ab2a2906564076103a9e0c1036b615d347d8c6bb9cda6fea88ed0e19","4dfb54c57029d87396ad9ace943ad93aac7cf70d7e4498d6a63e1c951d67adfe"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":12,"len":4,"rows":9,"Q":["d80f680421b81f083c3423b49e8589ea6aecf3cfa5a9be642d58cf36fc83d1ac","3283a58481a017c39a7e58964c81ee4e5103e27f84162df8f47a325e67ede601"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":6,"u2":13,"len":4,"rows":10,"Q":["7ee0d6e87c6f05d70a1b13a1bf4c3980c0738bad21d0b5cd19377f6b1354b9dd","9bdb96c82d9eee6f3d656ec91dfe06049561441d4b9fba183de2354f13eef2fd"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":14,"len":4,"rows":9,"Q":["d60568013058bba347002413824954b0352ab5dfb62a243841b534dbaa95cac6","a3c4e3adef30410b563b610d18dc5949e4d2aeff72ef93e2a1cd436734b2092d"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":6,"u2":15,"len":4,"rows":10,"Q":["df4a1e404929c52f55d31c5c788ddedd03c38647b0e62ebe9e27791f89482180","cb873a06200eb36cc872bf3f4ee887f5df737f8207f3d79bb8263664e75f7f5b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":6,"u2":16,"len":5,"rows":10,"Q":["5a26301b444817937be696fb59813d7996ec73bc377e415c425b229657552934","017857f0d1f87c18209805c688e516ed33ad1be0906c40c19dec5433ed0f089b"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":7,"u2":1,"len":3,"rows":8,"Q":["3bf2bbd815bcd9eae5642294a1796147f403e1eb0436e4f0a21a0581d8a52697","c7ee4249a1c405095ea35fc1563b0670d140b459211bdbd7bb9b493a3e0ae341"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":2,"len":3,"rows":8,"Q":["7bb7667e64fb500d1fe4de73d968b067b1e49b017e656d9ea2363ee22cd26eaf","7efcc70c0d1dabb250bb66ccd21c49c3266896aab01e4cb06abf4c598993a3d2"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":7,"u2":3,"len":3,"rows":8,"Q":["0b571bbfbbae74cdde1086fb77627e5661a9ac4ff6df2661daf27389f91056ed","a11a6711e62d5deb1661a8459b7a57c098de92a40b34e7ddf626c831ca93d054"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":4,"len":3,"rows":8,"Q":["fa8a7125424dce65a3976009d26ba2c594c5d931e8d62da28fa0950785ae6c7e","76ddec002078d2777718470fd14f82b566f25c7579f7318954276a24061af98e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":7,"u2":5,"len":3,"rows":8,"Q":["40f92c1ef6fb86a8101ab50102c52f738da318ca9c50a03bfc89b0dd303a41e5","9c5b894ec2f90e467da6b220b0c70b550c93b87b333b61eceb46cadbf495c2be"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":6,"len":3,"rows":8,"Q":["671c62b5959275f7bba130e313ba2de631646cbc95fadbaedfa725f466560dfb","12353850807701ce9362c80ce5967cf5dc38effbf54578c3f3c954417fcf7bf4"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":7,"u2":7,"len":3,"rows":8,"Q":["ebff8f37bdd87c58095de08f321462faf1a10fff37bf745100a30dd51aafb07c","6c52744922cd4405c507d0b2ccadc3b5ca3a8fcf8de25608a71ea8f87af377d8"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":8,"len":4,"rows":10,"Q":["c54f11314d4383f41b41111c24558a4ba4e704860ade432240efa202bf19866b","ce6eab2e5d3b137ce40c0680927e3c4ba942ae05ba9f9652ee1eff81fce617dc"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":7,"u2":9,"len":4,"rows":10,"Q":["cd674e93e330977c8cc4ff503fa3495388f9530311ef87325f7271809b5ab681","a5f1b5aacdb14ae2b00f672510c6c02ea55075bf955a3a28694bc9addc24e712"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":10,"len":4,"rows":10,"Q":["236031e46ede80e78a0cebced6bcc8f7d62a044e9051de09adc9f1b699b2daa4","ac685e8224527c46fb2a739bb868b597b5a93737a9bf99645f01295880651fad"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":7,"u2":11,"len":4,"rows":10,"Q":["4c8e29fa33cad09dfc79f43afa469cbb195138c00b14e57cd31cbab01a37e026","5df28c1841cc76784a010a86f19828dafb7762bcb0d15792e8c9629267c77a43"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":12,"len":4,"rows":10,"Q":["ede70b5e052f4792ddff709e5a70c64f68324c95bead005e9932e410252cda55","a83e9a026328d5f1ff534cbbaa5be8df085539e61a5b74b1b6fd38d25aedf80b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":7,"u2":13,"len":4,"rows":10,"Q":["02ed17963d76d8e47b7551c95d71df983ddb5cd60981bccec65324965bfe292f","8bfd76f48ab22ca022d1f24751a610a2fcd36516ab160856beede479c2b1ada2"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":14,"len":4,"rows":10,"Q":["06989e1533c904e701e57434c94957fefd82b991bdaa97ff798f2247c7a6e6a8","e93960d5899e57d1a998eb504979f19861a274bf6ed0914910186df4a88058e0"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":7,"u2":15,"len":4,"rows":10,"Q":["ef207b25a0acc441872d0ee0205d5548b144fdc6184730ee7dd008ff3112992c","aa14dc050009ff366c59b70dcbc67b659d4d178b1922e23ddcff08b309307ef7"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":7,"u2":16,"len":5,"rows":11,"Q":["321d5dc18bdab6f2830fab6ab6320d12fa5ad7413c81265d82e970f3f104612a","d3e4d078fb1d5bb9aa7efdbf5b01453694c676667d58eae37d63992ad3df2c80"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":8,"u2":1,"len":4,"rows":8,"Q":["58baf0165047133320594dccbad628fb1c476218c0940287ad3f81ea2eb3fba1","f74132d541a3074b12cb2348665dff1e895da090ee47a4c8f6575c2ba8f5ebd3"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":2,"len":4,"rows":8,"Q":["c3b65d796bc0c3c771aa75362b5a462578711e2408c974a8d8bd50f93ab13625","17403684d39d1d61aca997d161aa03be526d4c7622979d18b778fb8903238931"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":8,"u2":3,"len":4,"rows":9,"Q":["e039438fd76c00f903612cd9c0c901edd823aed2842cb87ce0af5412289d2070","9ae4a101eb22602bf05d427e8e51ecb4c3e97bf9a7838df0c557f69b81ed3fd9"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":4,"len":4,"rows":8,"Q":["2a224b9d4e1036ba3d0aae93cc8753ced8589be85e6468a1a02bc7b1084a4e14","ff8d8f7c08cc214e1b2358e529024ba96f2975ac1e7c0c06e35235c48dc47528"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Correction"},{"pair":"G,R0","u1":8,"u2":5,"len":4,"rows":9,"Q":["9960b250fa47fa4539c095c8e6b81ccf5234fceeb27441f7fae855081acc0c4e","b1830afa3be1bd3dd002896f98edd5d3c25f7dbc251582dbae5a2f3d007d5447"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":6,"len":4,"rows":9,"Q":["562f7c2321322b29ef2d7991cbb927bb5d88ba0c375e07c36d32f16b072a2fdd","6af93fa0717b2dbf61d943a8e97f044bb3abf72fbaee6ba5ca66492cf90c78d2"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":8,"u2":7,"len":4,"rows":10,"Q":["16da1ecc36a86f39b73944c273c9f1e2748e1eff3725328638e5f3f9b4b770f0","cfa61c9136a481144ef07d802dd236d6b6593b6902f02b7354689e2815daa39b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":8,"len":4,"rows":7,"Q":["daa0f1be2164f3e1f91549ba00cbe1bfdf3742dca45669b6c9022d072c6ea8f1","85190eafdd8cc8c6f4ae733cd3ef50e1e3e6e3927e40e019dec32201a1e5783e"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Correction"},{"pair":"G,R0","u1":8,"u2":9,"len":4,"rows":8,"Q":["f143c04e58e5f42b29aeaf531e335cb1c566274116c86ac6d0e13ffa943a10c9","e3b00907f40e860c0d35de031d0565c3f590155ac31678b5b628c0b51f89ecdd"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":10,"len":4,"rows":8,"Q":["853149295471645e76eadd1adfd563e8b52118266d38dfed4cf4bbb56158a9c5","75b2689f1b0cd98d70906ccbe683dca22c6e9e6bbbef0947b222a06dd535ac87"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":8,"u2":11,"len":4,"rows":9,"Q":["956c4568d358c5c354cf137f4724ee387edb260a9c23072f091b1ee689b61a4d","f719473643b199842d1a6ac86355f430e5ed7f5302f2fab8d1d80b0daedf06fe"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":12,"len":4,"rows":8,"Q":["6457e746f39814f0231fad9aeeed5adc555d23421cea062190823ca13aad28bb","b170633feaa9ee1f16b2f7608184f5980022c20087fce8b6cded5e37c7c46a70"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,Correction"},{"pair":"G,R0","u1":8,"u2":13,"len":4,"rows":9,"Q":["ecaa5c5edcbc1096d13d46af77cfa76b08a30aefbd289eb95b11cae19dd3c666","cd0a1bf3c1630b9bc26c100087b8a842aada5684d1ef8f84d0522a79ffe0fe19"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":14,"len":4,"rows":9,"Q":["f544eeb87c705b1a9e28d27e4fad70052aceedcb52c00b29ebff209e6f5e4598","92522508f40998f528b01a90901c8e9115067ba92f37df294a0b0f0f807c1c3d"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":8,"u2":15,"len":4,"rows":10,"Q":["d01a752b754fca7d8019188b31017ba235246bbe28039085388ebbc02b54822e","659b41ae9e9e6d00dd06055587fa8a33ad5adddd639fcb69ade3a5d2796da621"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":8,"u2":16,"len":5,"rows":9,"Q":["5732a25728ebe95e8efecef9ed4e6fdfe0a4118b5b93293081c33a5fdc738898","6552303d2dee5d5404b7df0ae8a1dea2638665c0aa72a742ad2aaefb500af115"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,Correction"},{"pair":"G,R0","u1":9,"u2":1,"len":4,"rows":8,"Q":["b20e2813b4f97efa57dfba52284915a200b4d93bf97249bd5bcebbaa78ba8054","6ab1552e01976c4059e7b74996e6d4ee4dce3c5e742c1f88ab46f6319f89240d"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":2,"len":4,"rows":9,"Q":["7a5948ea301832d9ede6d137a40dd7246735f48e0be3bbc06759dcc03a10709d","749db3ed3e3165b3962870df437e9caa22b2a212f9435403838818380e80dc64"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":9,"u2":3,"len":4,"rows":9,"Q":["65e4af473cac04623874cf6100c961eb6de822c08530163217998850044b911e","cff92682eb48035606a68d3ccac3e5ec85891e14b9c4395e0928bec40670ce45"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":4,"len":4,"rows":9,"Q":["e51396558a8c8ab6dd38f1f6d0f363f3505ca3ea781bcd2df43e3c5be8ae0fa8","d66b68018bacf619663484a1583b3f0f90b01cec75d7ece94630b83a236fe186"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":9,"u2":5,"len":4,"rows":9,"Q":["39507bb50ba3cdbc34e01904558dee31456f9020ab7ce21b544fc25d6d642913","bdd4edb351317a9f4d66a98e5adfb3aa8d229b3b70c87274076fda7f5fe86af5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":6,"len":4,"rows":10,"Q":["81c70719dd079ea6d653f9435290e125ace85a9cf25e295a75688881c9cfd456","c9bc6b25978ac270f9ed537c3aa70d08895891f52b53844d5dc9514e56fab0ca"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":9,"u2":7,"len":4,"rows":10,"Q":["61a92a8ecd57f5070fb7ad6f8604fa9e7e9f110a685e7725b76355e91d74204f","cae6b4112c85218c454b16cf72810eb8feb7d2c0d1bb77d5c9a4453d3a9c530d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":8,"len":4,"rows":8,"Q":["d4e8184758c8fa9d30f23167fb9940c1fd2344d96fab617d23d058a5d9457a90","792e2b03b5efeba453e0986ae1bd94f5f79881abd7100e624124c3a69eaa8954"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":9,"u2":9,"len":4,"rows":8,"Q":["9529bfa8c5f27aece3cd5de0651b5ddde4fa07aba7f05fba8eb1ca4763426ea0","9f8de6d35083d7e169e5b415d43071535e7eadd4c8ac81c798b314965a3c5267"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":10,"len":4,"rows":9,"Q":["3b4435fa0d0dd53e2e9cab8b8e903fee081730aae1e623155341fd63406dd63e","6b84a473fd51fa068079e78fde29b0ae205473ba015f3125a33475646cc2ab19"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":9,"u2":11,"len":4,"rows":9,"Q":["a59736b60ffcba4a63c9bedb68cb4275918b1a6484a1cf3852d5c8fec0fccfa4","a05b201fd4966bcd273eaa95841209dc712ce3de6184d2b6b572c04dce0f2221"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":12,"len":4,"rows":9,"Q":["684d45b4652b1645b135e1a8dadbab7a2a1c285c5038fae7cd2577ffde0b0485","45fdcbcae4426a86caa7287ed75714603e48093e8c2c9963525124dabb704c7a"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":9,"u2":13,"len":4,"rows":9,"Q":["bccd548a81c10ee814e723f5c05f0690033ccc1117667edac584d4864d1f2714","ea223eb32faba3be8f4de65875c0ccdd5ecfc41a631fea1d23015a0ef230e3e2"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":14,"len":4,"rows":10,"Q":["1caefef74ebe0cf15f2c895cc030832be926e88c39b69b2fa14863672e3c50bc","3024b6ec36bd34b590996ce7f4751764b82d399905191abdbe003f02a7ea2115"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":9,"u2":15,"len":4,"rows":10,"Q":["ab2b231f3401fee0ed33f5df48e696fa61b178f0f959f2abcff2b1752920a7e3","4752bb56964f835e34d19bb5de254d00f01e154c8c3acc9ef8f1858436906f19"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":9,"u2":16,"len":5,"rows":10,"Q":["03bc2f4d67437c94a395101d34674be0aa7cc022021ed3856707b93b6ee06b20","ea1f87dcffef8adf0b4d992d5dd4cd220786dc80a8e76450281b70a00467280b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":10,"u2":1,"len":4,"rows":9,"Q":["4693a948335d03b54f8751ce2d435a790b2cdd5e178ea504108c2274e86cad68","fa6b47a908c0a35b3cc54659de09508b03fdfb8eeafa927689cd63c1fa93474d"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":2,"len":4,"rows":8,"Q":["d07f81e3baa4aa576768733d706b4af30ed0da01148af2c08949947a968040b6","7fc32fb7cb4e7bc445d521bb53df26a3239f139fc68712da953badea28457976"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":10,"u2":3,"len":4,"rows":9,"Q":["5cd1c900f797efabf63b8eb553e0f5929188427a61bc74ced73c57175e399ce5","44be041b9231a457b5255304686551f512d4947d99577fc722ba7c6e387a3336"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":4,"len":4,"rows":9,"Q":["cd641d7b1e4bc80c1a42843c0e51ba291c68f1cc62545c82d24564e0b00834c3","8c20171c7c27ca9f202fb2a14ddbc0c953af4967d541010430327d7bb1f49ff8"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":10,"u2":5,"len":4,"rows":10,"Q":["f0422afba2d4c7d60991ad2eb9225789a73621d6917f15a0867c8001bbd9bea3","fbd58bb621b991d19ab237874fd34c751df31595a952c7241e85891a2feb63a4"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":6,"len":4,"rows":9,"Q":["33d7124451b27cddf7ce7afcc5dd07661bcbda8c9f6a2949668e9ff7b327a9c0","1e2bd96551b71d8978d61bd92d0ce7dd56ac7b3c87256a94846e9a5718e1038a"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":10,"u2":7,"len":4,"rows":10,"Q":["859ae4df306ec365fcf4e720cf4208b38eb57a212007978af570fdd791e07310","ec77971dec7798333d89370295cb010ff2716c0899f7f9a77648e7e2c90e554b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":8,"len":4,"rows":8,"Q":["eaa41ef1708d5a4d078e03a9b37d3ae2516dbe70353285e6bbbe207231b108e8","f4506b8bc48313d02ed1cd8253bcece6beac30030a4e44e37f68c696afd5b6d5"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":10,"u2":9,"len":4,"rows":9,"Q":["94b471a821a0ec4b17f3de5dffeb12522d6931245243ddba50b7f47e91af5db5","5766e5371cc9d55f5e2afdb44f431100194e058e276c8efa58f39bb1613afd7a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":10,"len":4,"rows":8,"Q":["ea8873227eefeae29bce1b912c6834df05dc51aa843410bd6963e649b1b73c4f","7780648d54156de1859f1fc1211f2ab33176db35ccb011d41d5d77c8f681285b"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":10,"u2":11,"len":4,"rows":9,"Q":["6accb05bc9d73f4d23ffc004932017e4071015cb003de2154314136dd9fef1e0","d4c421bebed598d7d5ff2d1aaa7ee5697c80b68141836dc45a100ebd426ec9a3"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":12,"len":4,"rows":9,"Q":["40801e971c349fb290cebf8d50a7b202a067b6a9f6ca9849df14109920b2bf68","d592b5e1358cc28a32573c51d3c0e16e8160c830d1397ac67665dd23fa3271a6"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":10,"u2":13,"len":4,"rows":10,"Q":["4f2c28ed9fb74b57df6d7c46a1698c0396f40138a27a514698e87a0366b13922","d6b1fa2f97178b01667993d621496782fa8d1dd22b0050c151081786306b749c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":14,"len":4,"rows":9,"Q":["4ad65d855a407ade936d57fd143b1eba1571cbef5743aaab90216f6628ad2704","94e83006df0492b9561c8a53693ada66d7cb635f5cae15f0ec588a3180380aa7"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":10,"u2":15,"len":4,"rows":10,"Q":["e6d65c51c49bdc81d57f8d5dc5482884dac215cf01bf316c2e8b477fa3e8e15e","8caf20c96fb81708aa60889facc75b49d619576a38aab0f33780e771903125ae"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":10,"u2":16,"len":5,"rows":10,"Q":["eb1d4a80c6a7c1a15836fd2dd35c3ac323e208115b67e6b97f426418134ef820","ac9d3ae566f748a2b93b8c948610a6883cce2cfb865951e183880e09c6636e73"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":11,"u2":1,"len":4,"rows":9,"Q":["b88accbfc935659b44228c898c55bc9453504b9f8ed35004726b1c287f93b5d3","009387045f75c19eda175487ad64c494752f57349aa82cac83a8123d7fd73ab1"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":2,"len":4,"rows":9,"Q":["7840799ccd68717a82c7301b4d6be1ca934122fb53b64b65735fcf55de7ba4cb","26c405c4c6c306c5d3e4d25929103b2f199830d522837491c9fc2e9a67a04b7a"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":11,"u2":3,"len":4,"rows":9,"Q":["b0275a41f729934440dd37c0a5b000444fcf5187ac8708d19a2a3ea2a1763526","8a7b5f152c084220ef0d4b1fffb5daa6231ba0a0e1c1e8b9d6b7ee7808e19301"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":4,"len":4,"rows":10,"Q":["e174bf7a794796004f4d77c448ab356759f87db12221aaf26f18a5d952973129","52f700ca40db79867869fd480c7e1ae2e69640edb8bf6c5e06ab2b7a708d93bc"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":11,"u2":5,"len":4,"rows":10,"Q":["724424c4db16da51e53a11a71cfbef2da375d6962d5176065880324ad05de78f","592d8c20658f784518032a6992f9577d9a7e257d32a48207e00cfaa0b283931e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":6,"len":4,"rows":10,"Q":["21324e85273ca0f9396d77ab2d172b5fcf1f3314d683b28c935dd155a1bc6ab6","1a28641aae65325a35a55371295fe2b39a00c8473ca7d90642ee7b256d854185"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":11,"u2":7,"len":4,"rows":10,"Q":["b0d2aa16d4b84413b71e117c33204c3cb6a0c79625b0e0cdeadbaf618fb397c5","aeada9dad239876cdd84999aeee0686a3758bceea8fc9d3c2262eff0c66f4b40"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":8,"len":4,"rows":9,"Q":["3ae26c48d346be24d9d3d8f394b7d969e14ff1a972ffce788e9389e164da76d9","6d6525449f39f2245067155656345653fd67aaa0f6711876c375df50ab40cc3a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":11,"u2":9,"len":4,"rows":9,"Q":["201239bbe70c5ac10d1ceb32329f5dd2a07552772c3b0e53e05ea745e43f9bc4","79c66ae9bd36646c047890877358ef6ba4f5751c5fb36149f14b160d56da82d4"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":10,"len":4,"rows":9,"Q":["363bad7064ca34b9ca52efabde7444afe7f6990b34e73e2b2c5f2473edfc98f0","5e79df68938b22933da753a81a7eba2a6764a5b258412d84d1f23c12ee3aac2a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":11,"u2":11,"len":4,"rows":9,"Q":["a7f9b0174ce38bfeeda51fc460dcf86fc434d3a506a316f4e8abd87e8856d2e1","963ed4299ff0fd613b55fdea04e4c35fb38ddc2ad2e0d7b6e28c8f6b41ceddf1"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":12,"len":4,"rows":10,"Q":["ac2d8031106f997567071bab825abae269baaf016b84ea19534df203a9ec4249","ed7fcb9b1799dba61b1118d25cd05dc40df5152d9b12b175445eeac22b47ca00"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":11,"u2":13,"len":4,"rows":10,"Q":["0dd2c0ef4458636e41e041dab1796caa8e1e8cfcc437f970310d0567777cb94c","a2ed4f63e7e4c1953e0700a76e28ee40e3b5c5963d00d2cac99314011ec16061"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":14,"len":4,"rows":10,"Q":["6cc53467c94c9f6eb89e7c03670689406c5101c53eaba9c8426da805bf3dde54","4d7c94b10e8e5ce432ee72cb3ffd9b6eb2e0e773bdfca39d7349634d69a238ab"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":11,"u2":15,"len":4,"rows":10,"Q":["fe2b329645b3953c2432d0024fae657d26220120f95c40ce0c6ea9a2cd0159bb","1655a098a4a547318b2c180f6cc1638b34df9d2307f8cd99de7bea6a4aa24293"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":11,"u2":16,"len":5,"rows":11,"Q":["d58d2c008f274274283e9daef5f80ef5621c273cbe73a04740e46808d272bd1e","66333d7a960eff42c03d707f8f54ab367b324f68b99f99067bb7d10ffa7916d2"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":12,"u2":1,"len":4,"rows":9,"Q":["adfe671a24c0200901d115e055b9f8bae3ce6766082b782ec801f7771e227e73","6c0ef39c1c38ee294ce9a8d972e5465bc2565295bd3cef52305c3e0cdd22de18"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":2,"len":4,"rows":9,"Q":["15ea1cf5f51c549986997efe52bb98fa51cf5e4b5d498c6d6de9a23d7eb386a2","5e2e9ba469436912f495e2a8479e391f77125bb8493e25a50526d90c47d26885"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":12,"u2":3,"len":4,"rows":10,"Q":["1612720d53d50c4de70399d624801ffbe73a8e83394f2ddb4c29888ff7d9d319","57feb0afb20799f88e1f325706437fed21b27d3d1d8d6fe730bfabeec197938f"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":4,"len":4,"rows":8,"Q":["159ea8548713c3c88126d7bdb57c495d7faaa187d8e54e374b51941ffb55d3c2","5a773d2397d1ef8590dcda4247649247a0e4a591397ff4262a5a2853abdafc5b"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,Correction"},{"pair":"G,R0","u1":12,"u2":5,"len":4,"rows":9,"Q":["a5b75ced0bd36d53b07dd3b0da71e78cf1884d84ee40a36d9005c255b4aeb9b2","101ff3f3b307d9c01e2603df06ce28c464fa8d70e8c0ae8b653432a60ed64a3a"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":6,"len":4,"rows":9,"Q":["bd6f2d443e093c62968bdd63a01e08733625303aa66f33c89e56eae5da74be81","4b29928ef1cc653b145d5eb9a8bf708adc6a1ac87e99e01d5f92f2ab08fbb9a3"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":12,"u2":7,"len":4,"rows":10,"Q":["d36461799d956d4cc0e03b7ab42a56bc45c45a1b686dd24363e03ac32d15c763","dc8d123d239b55bfb763640a53d68ed7273e19775d6cf8cddc0e4e929fdef10d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":8,"len":4,"rows":8,"Q":["93dee3f4bde888c04315593b26d94cafe3fc707d2a83b800a3b7fded62109856","1c7aeec6829c1fbd2e0cbdaf178bd10dff5228251d85394ecd4239420c69f75c"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,Correction"},{"pair":"G,R0","u1":12,"u2":9,"len":4,"rows":9,"Q":["2587d9c66ec6c3e4254349a8144e7b8b48716f5b4d384dcc268133be49819c03","ddb7266443d8ca9dcaa08a7ad1d80cb1206eb7d79636b17ad31eca30a232d0ab"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":10,"len":4,"rows":9,"Q":["f277495afcfc4482ae993d710f4bf557c499b68dcb15e6ea78a7899fbfa471bc","24cc64725dea2ffff229c15ed7ac0c0b2e02872d921f9e24b331a4ea305c957e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":12,"u2":11,"len":4,"rows":10,"Q":["5199c9fbd60bbac5f3a5dbd9d9e91b9afb47eaaa0ab663de0d1db23ab9cf1507","ba0319323a743a854a9a15af70769a8670c9ae3a247ada9614ff6316945ea753"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":12,"len":4,"rows":8,"Q":["8372570378be5fdbc81a32fe70279a2b529a76ae3406349cfd1ae62fa0c31d03","2861fcc767ede3b5c289085dda8e2febcd33484faf23c2c35747f52bd4324aa2"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,Correction"},{"pair":"G,R0","u1":12,"u2":13,"len":4,"rows":9,"Q":["8fd5a1a43a227d4ad6d46e2cda700b03c3ae02caf3305939537efe4739bc729b","658c610e35cbdce7e7466346ad4de235140351dc9914420afee5d51b109ff94f"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":14,"len":4,"rows":9,"Q":["08a26621d9b2ce42232eacd533853e8d6f9fa7696b7faafad34852fa009f9e85","26145703e8bb4855dcf50064cf616cea884752dc818cf3541b0b06684d2cdf73"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":12,"u2":15,"len":4,"rows":10,"Q":["d4da38b8d2677e968426bfa8f3bae0908935e124bd93db5723336a17ac7797c0","984faadb228c8113ac0e5061c13036539da0b74970ff9cb76b07d4eb68cd63dc"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":12,"u2":16,"len":5,"rows":10,"Q":["7cc8ca443dfef581a5380679572e26bd2eeb3a4c685b1d9c67fcca5229c06590","048b05f2083617e0161557c5ba195100c0d9b77ac8cc756cc350a05ba29bc53b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,Correction"},{"pair":"G,R0","u1":13,"u2":1,"len":4,"rows":9,"Q":["179981f8f8860bdf8c7ad0ae65abbc1bcbfde27487a61c1b66f78d23c59366cb","7f9f2e186a2b52aa434ee6a61947ef6a779326848916072ea8d7d0993f2cd92a"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":2,"len":4,"rows":10,"Q":["d0cdcbd98fa9704e136f59a06089a9fe6948e88d942209d7e0b8d801dc275815","5aa58e146da27afc885e54eb246aa54204b811cdaadac9df7e6a203315b13eab"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":13,"u2":3,"len":4,"rows":10,"Q":["31be8c3893bd89bae2df76957838ad9abf00d3ac937a2a89e1134206ad563813","4ac8aadd9794b4049236d6f5600e7df6cccd3eb2fc639151b421edf0847bd3b6"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":4,"len":4,"rows":9,"Q":["ff1820c1c91168ecd41423ecb7a161aa5d71d8b8b515b3696b927c37e9a40294","2f3fb938801a59e85a7b31427848fbde7835ea09274eedcb6b07623846407e2a"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":13,"u2":5,"len":4,"rows":9,"Q":["4097c6a78e30ff21b77e69ca335241c542c262e7692c1e2165ff7363cc870151","6751d118958a2e73d01333934e47fbf73fe0183759844e0f081bdb3f48ba3702"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":6,"len":4,"rows":10,"Q":["1b419b665164599e4d4f6773c6a9a3c59ba22b678527a8d66587a9e5e1211864","6ba0a51ca3313b2b6586518f7cb5a7375e408c15e73652755b89209cfbc6fba4"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":13,"u2":7,"len":4,"rows":10,"Q":["8638620b8be9df65853dbf00ab954f1b6fd2ca7122c5ed697f5df9ca2a70c46d","1172aa142a236f9206475b5f972be10c21223577a0075891073ebbfed347bb0c"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":8,"len":4,"rows":9,"Q":["c710552443e52290e1555de34794df3cd43ea76e6c91e91be3c094f29d8d9582","4b9a889263597a276a97fb25d564027fd3bc2c8692387435305355bd9ad1d19a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":13,"u2":9,"len":4,"rows":9,"Q":["233c6486e203804bfec580c3afc3e9feeb221686c3aed58a5e1c544c45d78d6d","c3dbbd1bdbfe520c845171a3222909b2487052bc54c4a091805849dd0116b048"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":10,"len":4,"rows":10,"Q":["a354c98e308e9dc1622bada829504fb6889809b403056aa97ca422c03fb5b888","a031651e8a934a6415e9e1ad406d3ff729c44364e09c21f71a5e52c89d3972fa"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":13,"u2":11,"len":4,"rows":10,"Q":["f741b74b9559105e4dc0061ff5f8e96918531618dd4c87994d9381a10387626c","e6b9d76e7911bad52dcf01cb3295bfaaf5eeb1f8e945a99c9403368e6b3ecd6a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":12,"len":4,"rows":9,"Q":["377d1b454b36286d2c1523f3c7f617f96c79ec2040b8f98cdc93a5b5443d1a00","731c945da92bb5efc9b083ea3be59178ee54baecead9fe5570d5803f2ca89b92"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":13,"u2":13,"len":4,"rows":9,"Q":["49fa06f52a74959430a38afcc4242fcd5803ccff4cee2f8a174750d62b8ee6ea","3c183dc748405af67c04d49e91b738bfb856f86e59bb2fab5461d7375e021adb"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":14,"len":4,"rows":10,"Q":["71240d88acaf021bc5b619c584e2496ab66afb7061706d4b292b89175d70a22b","16fc3b448f339c99752ca31109ca5b7698698f961dd2fb9dbab587e3d153e410"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R0","u1":13,"u2":15,"len":4,"rows":10,"Q":["838d3bc4e32a81b97aa08aafc812dd937e1cf39bb517619fcdd3f0f871157297","c02f132f86a17f28be3c33f3c13ad85df1a06b37be5ce6362bed13766b0dc59c"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R0","u1":13,"u2":16,"len":5,"rows":11,"Q":["a6493048fea0c7b2418eaf05303515a519551f887153cc4883ad7e04ff163115","f5ca14f892dd06ab7316888d53da73e963e3eae67074495377d2b5e482be5da4"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R0","u1":14,"u2":1,"len":4,"rows":10,"Q":["523a37b9791c6f62c5e8ec3d2b2c592343649a73001b54fb0bba8fe0190c6b2c","991ee095361f0ef4424787374ea8e35fbe1403b2728d2fce0c2c2a80f2b39291"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":2,"len":4,"rows":9,"Q":["cd62b6bb485ac5632dda4d683f6939fcddc7f65719e43f98f63195eb39bbae04","07876046a67f7496fff50f7d0421011c325518d1f719ce83a939e65098e6aba0"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":14,"u2":3,"len":4,"rows":10,"Q":["1f44650b81fc92e6655d10e26fbd0b25cdfa9c170fed6451d709d0333071fe6b","874e50a8c245e6b337e3dab1b6c62dc023fd678ec635f9364c1a4bc624f829b4"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":4,"len":4,"rows":9,"Q":["af9c98f32ad482a8daa50a50d91f71db0011c7a0b66900a9feea4043a6bd394b","30eb339901af0f878088c4e1ec736cb12357ecc7438d9e8464d5466a95e1001f"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":14,"u2":5,"len":4,"rows":10,"Q":["2a6c9e5384ca2f4948e619171f1235ed89b18fa0be0674a129b2514ab7dc8a3a","ed4b6757ecd0e2bed332b7434f7ca2fab4c55bf5a5a8cee8bcbebd068fd6b77d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":6,"len":4,"rows":9,"Q":["7268b5c91c3c39a581f02ce3b8617ea0280193a9bbbc3f15e7a5bc3f0e4cf22d","9b1b7b4ba3fb16985db0bf63a3878422b7baf1648d7c3a19bdcadaf9bd5c9608"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":14,"u2":7,"len":4,"rows":10,"Q":["a5a76200885691ecf645f45af4eee35daa335617aa7fddaad7331197b814d3e7","0af070e5e3b905d004764e0ea443c8de59ae3edaa39fb12b1c949b165d301a56"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":8,"len":4,"rows":9,"Q":["3b247f3655fe6af0a00396d3e27670c9709f29a6dcfb6d2888c60d3ae85f62c3","36919d8666a1ded09fc50e683c0c555c5f0fd91e3bec55690d0966697aa9926b"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":14,"u2":9,"len":4,"rows":10,"Q":["6ea50abda9b226c5afb729415e87105c5338671a0f5829782037b194030c7021","81bbc0bd9f809af7d9b892133b037c536dfb040d3b1e425af5d658732f707212"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":10,"len":4,"rows":9,"Q":["a879cbbaa78d5e171725308797d1e06c12c152e033b532f702b7b533a6b5f012","1afe57782afc9e5b5ce819d5bce607ed5be519b281a323e7d7d1fdda377c2490"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":14,"u2":11,"len":4,"rows":10,"Q":["5b1724f9dc14f815105f438b3ba3c1ce902c1e8cfa4964b148c7912af43060c6","9744b9aa85cf387ae3ca6e6675a81c925790956fffdaa23505f633fce8920fdc"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":12,"len":4,"rows":9,"Q":["eecf3ff9e432cf96cd55f8f18cbebf16c928b9f5aefe4af5700af3bf7cf26c67","dd6ddf05923b15466b1df66e79f0dd916150cae0e13fe632e15e381e79792423"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":14,"u2":13,"len":4,"rows":10,"Q":["697a7ad3c5603ea63237cc88e53de412b75d9b22f9d807176cd16d5f160c1341","33825faad58899006967854975483402e2d51330f3fda8167b92110e438394ab"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":14,"len":4,"rows":9,"Q":["27fa74575b12941db52804eb723f6366bed1192b031c68f29b715c151428d76e","0f36753d1d9caa87e6d82d1a03dce989cee6af96dd9189d2b0b1feacf4d5bfd1"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R0","u1":14,"u2":15,"len":4,"rows":10,"Q":["9843c63d659b226c496b1d782b9a4f24c1558ed82b4c8816a1f671be1aedb3b7","cf278ef1641173dd6b53e186f48a27da912a95b9c5a528bf052e721fecc5c671"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R0","u1":14,"u2":16,"len":5,"rows":11,"Q":["a0451447a02126092fec0a0d4044d040ef1b6e7b01bb06ba63173bbc3d94085a","ee8fea932d77decfffcdc00cbb95e853524fd0f9423920e9639dad26d31ece7b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R0","u1":15,"u2":1,"len":4,"rows":10,"Q":["fbe194e079fad9787b953942ce325f91eca3d6cbe2436d6d75573271fc6a790e","55fe3d191f55470268845b13607f83df6148022c0996e2aa2073cbe845f008dc"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":2,"len":4,"rows":10,"Q":["ef5221e8b59ed64419fdb342769983e9549eae57926082f8588d81bc68bf883a","4af88b1b84bf1cdd04c86b3777fbbacecb8243d4b8ecde5a7a751291ba40a682"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":15,"u2":3,"len":4,"rows":10,"Q":["719bf90bef8cba1b63b2340cd2ca203efdadaaa4ad11a4629818c41391d47242","e505aff2f2a1bc4620a3a74bab67b49aaaa569937d7329b1ed1d0ff5b029b242"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":4,"len":4,"rows":10,"Q":["9f4a4552e7ee843d4a3a537921835bc9c201138e33c1255bff9bc620269be583","f74494ddc5d91246a4a1b92fe76d41d08f7b9e268d50a1ce66769daef1fe539e"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":15,"u2":5,"len":4,"rows":10,"Q":["6df48ac26dadbd42c481b978e908015650e69843cb7db29cef81a2a4cbe223b5","8e2b03b867a063233b956a74a06f68bd98b7748aad06bd8c46e27a7fc6586608"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":6,"len":4,"rows":10,"Q":["33119187dd049068349ee5c569ce0577a93cddfa4b5ba7fc2f50043bf11a2401","276cef78be3a7e40f1ec86f54560203ff12ec608f2b682adbb435200452e38de"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":15,"u2":7,"len":4,"rows":10,"Q":["9a441d54f0e18df2ffeb59ef97abf417fa7d913ec6145b8c9266d58bca7b3e96","4656a2fc10618811cdece7f1a3b9fd7540b012e3c0dc7315297951bb9e211369"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":8,"len":4,"rows":10,"Q":["7b3b655059e23cecb32c3165c00041c7e81028c1ffe3c298636cf70ecfe613c3","fb6109a73641b57d2aa19c93852140ade24a8e1d0200a20c98844f216c384510"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":15,"u2":9,"len":4,"rows":10,"Q":["a8a9fb7299911518c074bf6553bc92461e3102c9f8b67fc0669dcf8edeb3a41a","8cba48cd8fe32bd0eece5a64037b64a49242751dde3dd52bf1f9d055434ac895"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":10,"len":4,"rows":10,"Q":["e1a21f85e866132e618e4c61b4467e3a40096bba932ebf7f68091a541d7ed9e6","213e8ec46f1a319c265f7751a0b07224ba4e7f58baf066ec29fe6a18060ca8ad"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":15,"u2":11,"len":4,"rows":10,"Q":["59aaa0034d752966057f9cec32cfad72a4b8455ff92d20d598639aaf740b1bae","cac064f4b7d4771c9127717de152c15681ab380c905dd4182db9cfb51143f12e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":12,"len":4,"rows":10,"Q":["d7170d6e78a27a2eba0d1a7524680675c91a79e839c4f43d78880d3a30fcf03a","23666724a045caab20bfce4eef7502e445f7ad3dc9383586900b604d4e15f1df"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":15,"u2":13,"len":4,"rows":10,"Q":["b07d23f52caf64c4679565ca9ae9c3dd043c52f2607be079760b2ff1ebb2ac15","2538126e5d473fcde172884f3ad05675f9252291527a7fef9049647a6f722a80"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":14,"len":4,"rows":10,"Q":["3358e175070e5447d37164407d1c4f7d72c4d52234b03c3ec6cbe0160379ef72","9f66b342b3ad703898f63c53018e4ce1557b701722fc715f5ca6ac4aff3c8aaa"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R0","u1":15,"u2":15,"len":4,"rows":10,"Q":["47e68dd0af96539d517feabf6ba169b74f82615d42064dcd36c89ec978e2d5e1","791d070664fd1f69fbb0fe0e82576d600bafb50a13c36b673128f5d864a5b6b6"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R0","u1":15,"u2":16,"len":5,"rows":12,"Q":["04c2f89025fc0b0c3eefab1d4c24cf68474f2879d6ea082b07f920bc96fa48af","b1ec5473007a04547f3033751ab3706d86ae3ffed3834c09a83dec49be34ff48"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R0","u1":16,"u2":1,"len":5,"rows":9,"Q":["518763ab3314e9205878a297387c8294bdeeb7505bbf6555f79ece001f033ecf","cbe55ca74cde319a1f4852ded637117cf536fdb715e6706e6008ad972b866f0f"],"shape":"Precompute,Double,AddP1,Double,Double,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":2,"len":5,"rows":9,"Q":["5ee934c421af2dad1cb6263929a679d7d56ac4c3b709e5871221807707337fbb","84f4cd8608ce3f73a6273b2bd0c0b2644cc8cf3dd6a30709bfc01157b52600b6"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":16,"u2":3,"len":5,"rows":10,"Q":["9136250a56ecb3283ff234d198c73b8359f0426351c326e007a6ce35095ec92c","8951c54f6e1e56a2cc8a58663437fe63c961dbff98e0a31a09dc83674ff1b093"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":4,"len":5,"rows":9,"Q":["a6a9f11790885715a5c90a100442a93edf45e2ce850859e0fa18d1d3e1f3cd46","1d35cf22e7525a81af16ae4874a09811ccf27a2076190be3fba3b16d1c4525ce"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,Correction"},{"pair":"G,R0","u1":16,"u2":5,"len":5,"rows":10,"Q":["5b403dba7155d43a0017837a05fe3c14d3eaf1306f92815e3f3a78738fa4b7a4","fcf05fc08a783f74766ff3b373cea52b023a64a7079809cab255f8c106f80a2c"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":6,"len":5,"rows":10,"Q":["d5389417230be892d7e25c1ec727f970b4e0e1e977b5bd5e81ce8dcaefeeef3f","52325a19b46104405cbd25a795dd2a741430d31908f151384e699c09f0b9d7d1"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":16,"u2":7,"len":5,"rows":11,"Q":["79c5dad5f1cb80ed23f594404d3d05cc778c6d9248fa7369f152bcc930f75166","3c0970f7aa6621f021b9a5d4dcd57b83dd7e7eeb18157a9a2ba226b14500da5b"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":8,"len":5,"rows":9,"Q":["b6095640c9656d32a8e92161c63a5757a34552c945f9bdc681ec11341571e52c","29dbf3d0159d4090e2462f7995509f6e4ffb5741f82c8323b83ee18540878ae9"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,Correction"},{"pair":"G,R0","u1":16,"u2":9,"len":5,"rows":10,"Q":["62a739a20df3c4d7d5cb24b2d0713612fbde14616c18b0bf00cf89a7aae52fde","eccfad82116a57b66e323ade90193df7d6859fadcf70dd7cf03bea33442be3bf"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":10,"len":5,"rows":10,"Q":["3dc31f6f1af6f86e1cebb889274cf50e77b65455c8219e3f52bbdba36b4a53fc","29464b0d64c24ba5b33f570d5b5032a467462a22aeed5a9bb2307042c1e8b7ae"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":16,"u2":11,"len":5,"rows":11,"Q":["2d617051aca316313c67699f7379f900d19479778dbb9a4e1db323a9473c8437","d4cd648bb6a202954f63b081a39575b0b5f573d52106822f0d51701919975f47"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":12,"len":5,"rows":10,"Q":["af468f50c6779004bd5aa1d2af42e6bc8a2fe7e798221c9f951025bb61835969","424f88ceea651840fc862f199634248556bb1e18b7c5bbbfb5ac869609e6c016"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,Correction"},{"pair":"G,R0","u1":16,"u2":13,"len":5,"rows":11,"Q":["004b8821d81f679b27768172c780d93686014210dfa03509c1542b5a4033cfa1","872e2eda73b86ee27fa5c54eafbfc91da7638146ec28d6227e79be0d99b5609c"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":14,"len":5,"rows":11,"Q":["45296d913b7bc54d010ab2f8041b2d4fc4066d8f8b99932997490be66d317959","92cc23bd080f445323d4f258d3a5a3431d672ebb351585d9445ce3f87ddec47d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R0","u1":16,"u2":15,"len":5,"rows":12,"Q":["0c7a67710469d70767ebbcbc41829bb32e8fca05bb917d125f4df703f2a8903c","4d6fcbb291570756eb4634b6e3100455a215383ec8daa3119931b3404d531449"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R0","u1":16,"u2":16,"len":5,"rows":8,"Q":["46f2035d6262764a8a4e39c3d1e72519566c6e06a6c56e48c50259964f52875c","8cf067eb43e74e3006e36554a066f7d67909d0a37d5937aa6f5499ae6311dca1"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Double,Correction"},{"pair":"G,R1","u1":1,"u2":1,"len":1,"rows":4,"Q":["f588e8d20143b670af3b32469f2fe6aab64245e89fe8ae5dd2f3b666c7f32dd5","adb3a2888db9f8abb8686ea101488e85400c35f2030f9a5e2e6679ac40109ab3"],"shape":"Precompute,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":2,"len":2,"rows":6,"Q":["35058c8400a2cb5020f292035dd3e838dce0054f2a5d80904533a4180358882a","3c56074cce692f920f6c32aad94ae8a07499523442b6943d5e64aedeeaca5b58"],"shape":"Precompute,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":1,"u2":3,"len":2,"rows":6,"Q":["e30e8da98f500db279bfc71a1f116dc0c453e66dc8e7b56cea078b17387b8847","c04369ae990e1605543b662eec7b36dc86b1400c4b5b48b23543d03fc3582e33"],"shape":"Precompute,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":4,"len":3,"rows":7,"Q":["dc5a711e4f0c991a2f6393b2603da6fe746b777af809e2c044cd2079341bbcf1","d3caf7f63e5e522543e109270f4eac6efc5481631f6f9c357885d2d9361b0abf"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":1,"u2":5,"len":3,"rows":7,"Q":["7ba98aae37b23e5e9a6d2ddd16ee1fc3b2122f12572a0b5555c780127f3df808","cb41dd6883c0decd71fc059ee43a606745deae5b7499ec3aca2c56b417845aa4"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":6,"len":3,"rows":8,"Q":["09729212dcc31e06e8e57928582dacd220ba72329bac8e710ea6d90899824c07","1b669c54c9af2486bfbf71724e4ef7aea3ca2f8833217f819a57e44fea011bac"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":1,"u2":7,"len":3,"rows":8,"Q":["b6de4c4cb1d5651b7407d289b4a46a25b46b364df2849b2883fcb754687f9dfc","3fddb4cbd25250481555967cfb2bb038f9306a6dfa4fdc694defacf4c9e6d2e3"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":8,"len":4,"rows":8,"Q":["01cad67b2996cd2af88cb33898fe3d8a5e96ce802298f1bc24830c6cb0b77c07","6685d1efdc1ab749d3ba71bd7118c31061c44a2424f5d616bf951353671143c9"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":1,"u2":9,"len":4,"rows":8,"Q":["975f67cac8f74babfe0e38b4470120e72738709778197e2d47bcf802765350fa","179e4cc1545c6bd83a0d18e537cc3c4b66b2d6c07d6abc32560b1e83f1392123"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":10,"len":4,"rows":9,"Q":["36d9a94f48c5d7e8d98aaad50664c2168bd6f93a5344669a3657c08d8e3df748","9fffd06c246418a22073e25c11dc5d46421448d178d58e550b4348cc59b4d5ee"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":1,"u2":11,"len":4,"rows":9,"Q":["5977b43e4df221e7876fe9a4c93fad96607e57b0dc76ac0260ef8d391ca339c5","0c3f34e310cb880ce250b83d5bad257c3e2be97a2f6c6388aa1e82c2f2726ebb"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":12,"len":4,"rows":9,"Q":["83d06a6ff68c2763f2763a5b86bcbc2bee5552fcebc9887ffb5a9c2046bb4e95","dea7855642ec08426fa13f4615fd9a62feba71cd64b57610dd4720f52f26f24b"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":1,"u2":13,"len":4,"rows":9,"Q":["aef9fa77097433445645c71053fcb2a4a52fb4f08c24072ca4f23d9e56cd6610","34745f39f1b4d44feac90cff60f650d21c1115b297d94f333219b1174ae952ed"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":14,"len":4,"rows":10,"Q":["c1628ba34b91655dd4f92ac516dfe630ed6f0fb0113b36f431a943b5957aa229","d4bec45b4c18d367ba972b6e1cb7cdb71a41e18154b699e4dcb0e3d4738035ff"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":1,"u2":15,"len":4,"rows":10,"Q":["78a62ba4277647eca5442315ad86ce0792510f801e7f7781ba5bc98ef9760a9a","6b9142304942dc637b6f5eed63760f6bd9abde7cae76d4981148d837bc250195"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":1,"u2":16,"len":5,"rows":9,"Q":["a8de1b738715d722e41877106fcb05c5104fe02dac4248aa438a99ef79767adf","6c09254f44bab7a8183d476a88a6cf6eb88f7d2ddf20bd9e9cb5c96d97138f49"],"shape":"Precompute,Double,AddP2,Double,Double,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":2,"u2":1,"len":2,"rows":6,"Q":["54b1d284e5e45ead437d866a61eb2f43913c2416588bfabef949a6b602dbf651","2805f09cabd7972e1d8310262fd5edd8a0a1958ac016ad055ee1ee5c989fadcf"],"shape":"Precompute,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":2,"len":2,"rows":5,"Q":["02ea90f0ef85a949df5374f354a3a9203965939115e158de3eefa698439ec3cd","529b9fde6e88176e58bef24ec980b7538029e27d82761bff838ca7cf61d0a87d"],"shape":"Precompute,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":2,"u2":3,"len":2,"rows":6,"Q":["3957855ee5eebc190e22f880e9c064d279355770f5090ecfcc56e69b0ca792fd","1c1c46257ad00964ca92a0d0d38d54453167763538c42083c9430b500d8e38a3"],"shape":"Precompute,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":4,"len":3,"rows":7,"Q":["3435a65a6e015027a6c98fbe582681ac79a2f2706f016e07e8b1d509f54e1e3c","9b445f40f561957b5ede5a71d247df6d97444e98e2f9f6a68399a8bda697b2ce"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":2,"u2":5,"len":3,"rows":8,"Q":["b32058be0859a90d5aee79f826f2ed5b00bb4fecb41b0d0ae9352e68dee3aa43","1456b0eb72a6b0c1e2db8741f75be5ff7d4f181d10c03543650175398a0873ee"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":6,"len":3,"rows":7,"Q":["03f6c6077e2f6a906f92e619ce929121af674cd8eabc4e29ac1d68c9578fcc0f","b978502cef26e82622e8b1d397efd5a5fe0425a4baece567f6d18695ce404741"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":2,"u2":7,"len":3,"rows":8,"Q":["fcf0e7c2782ff8be3037ad26108a8419e52321bebef6734ffb6cda3b155a6545","da6da9e00253a5a8279f391badf6b1a33f9aff3895e054ce6fb5e49f7c5571ce"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":8,"len":4,"rows":8,"Q":["c60dc59706b71457bc542a574745a70a6877c7100f61d8de086f7eb7bf15e75d","0608fc501097ec00d89d56407a9575c0f6c65faf2e92f30c36d36eed970833fc"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":2,"u2":9,"len":4,"rows":9,"Q":["02ca9964a3be80f994c291ed1272593ed90427871a56174ef8f8effc3eab76a9","7662683c1cc04a01be038e94127f7a46b93ed3af7176fe872fc789592b77c6f5"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":10,"len":4,"rows":8,"Q":["77efa2c907678be4ee7e9f88f69d5bf2c9b7b855a6c73ee3b210bf0defce3cfb","3e46d7c6e1f21eeca69c1a8890f767303f450ba257d44a16761872033d21708b"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":2,"u2":11,"len":4,"rows":9,"Q":["5c0d54e769104db98643949836fabad93057e7362ca7f117c5137ba06ed55027","9e2a8f4374471344f527d62d9301ec6d0dd9ad7151dfce9b2371012fda081648"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":12,"len":4,"rows":9,"Q":["4e8abd152206a8d87c293d5ef42e68a6792d77691bb88749458c35d8acc6868e","a547d42758796f853f0fa06d4489de7e91ddb94b41a90d086019104b3827e766"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":2,"u2":13,"len":4,"rows":10,"Q":["cc2f261f21a1b7b096c75d1c9e60021012aca656e0ae8efea2a2bb0ee365498e","0bd1f85f2ac2879a772e7d66ede3ebe302e94883733a3ebba9ea02c7d5e7fc5b"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":14,"len":4,"rows":9,"Q":["b490cf6e94c7324a42fe67548e0241db1b925246dc5d210e5e1513faecda936e","72fc2c984f21a6c7a7ce20b38adc5c86c29a0075a1f84c99d2ed2a1dd5ed614a"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":2,"u2":15,"len":4,"rows":10,"Q":["ffc9aa6e458f9eecfc3da22cdf9f80ee2a9983b529512f75414e7ecb8a299c97","3a3bdc53139dfa752393aa617169dc6ebc0c4276cde409f50a6198f1c7e16af8"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":2,"u2":16,"len":5,"rows":9,"Q":["c7155fd64f04daa6d37cc549219f563eaf2021a3aa1ed60f3c8b6c4a56520a38","fb39514dd30a228e94eb4a87c63092a60429fcd4a79405683dcb8923d402447c"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":3,"u2":1,"len":2,"rows":6,"Q":["cc5a60d33d5dbd084438d6fe67e95c3aa0a01565af3ce2a221f3aca6ffbbcfa0","ed98af40a7484179694f103edaeb709b90c20c986636245c353cd5cfa0573ce5"],"shape":"Precompute,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":2,"len":2,"rows":6,"Q":["14eee109dbb08cb8cc58a354ab14ce6cebcc0c0a46c710cc41cf7783d577b567","cdca16eb58cacf6ba45781e333d1c53e5f3984d7fc1406b482b8940bc87e1e5e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":3,"u2":3,"len":2,"rows":6,"Q":["ab2a06be2c8c57a3d4b48be662414c3ed1905e188bfecc9b1b110ed8027015da","44fa33e40f0efdccf805757d19cad43673cef17e81833061fabdae899b9122d5"],"shape":"Precompute,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":4,"len":3,"rows":8,"Q":["df46de94d7eb82dbffb60dc41e843a8396a042fb76ce39d103f0d7092fa44f95","793af9b566af166e0096bb98fb7bdf4f30fe2d79fd4cb069b5995f640e5c5b40"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":3,"u2":5,"len":3,"rows":8,"Q":["34190b23cafc059d7e8a03b9644e249e65ba9eb5044b26cf3e437f5c3ce87c24","efac6646e82ed293594af2d408ed0035035bf8d12d114881e66e742c6e9e6789"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":6,"len":3,"rows":8,"Q":["86c489b029676d9ed367f11823ef263446f12572e539d7aaab4535b4db523db9","946875d1e96e8e418815c815e2896713b2658ef8d75b58a4754e5de4e6c52395"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":3,"u2":7,"len":3,"rows":8,"Q":["c82283a0e2ef63d4e69350a60b6e48840d93a8353d73ac79d0eeff2a0607f5f8","98e3778a9ea6cf99ad58df1c823db656e173aa1ee1fdb6dff5f13ffde79c3993"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":8,"len":4,"rows":9,"Q":["8d5f1adc0346f71ffdc312732860a7b942490b2383b5d7005cae2dcebfc6fce4","07841b2bf7d18dc16b42ba227c991deafdf7de2c97e6f850188e344e49acec70"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":3,"u2":9,"len":4,"rows":9,"Q":["bf89fae38e02ee034c0ecb992af4535f4eeaf49b92f1690aede58c5df4d4b688","31e538b81444f85b0bf49ea717fb0180cdbd714a5a0f84b76e49d7c985ae6a86"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":10,"len":4,"rows":9,"Q":["03673d5563aa551a67792785ee3e62108d1ab5cd0d1629b332d9102ca7ebdae5","3d7e50506900ce0d9899a2ff6ab6fb7bd8f82c434553ae376a9cedb0db740e4c"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":3,"u2":11,"len":4,"rows":9,"Q":["b0b87557ae170bab63933567809e16d8042033a5657ac890303bd4dc2eef7258","c1b6fca1ed8739b8e8cedff3c4d40ce29b34210d03d397cce775449efa0d9312"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":12,"len":4,"rows":10,"Q":["34a8b96bedc7597b2cc7a66fddf461927bb856a01ff501a8762a1b4d57dc17bd","1ee0ac3dd2c125db4e9885ff8841460cce67b62dea7ed0a6a266252ec605ae92"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":3,"u2":13,"len":4,"rows":10,"Q":["4a9807d5743cb17f4a6a99cbd45649f00844dcffbf126143a7c64b107d7177db","7ef803ef464859f913d3055cc7e5fc059980464f09c0f54cbce588e736338ba5"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":14,"len":4,"rows":10,"Q":["a1eedc2da395a76c61827b2110dde0f066a936ebf1f013226e105b1ab2b5b01c","5581e4350c781660b61fcf1cede6a950875e3cc698446c90e90d8612a45560e6"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":3,"u2":15,"len":4,"rows":10,"Q":["2caacc7f0e4c56e1d3ba9ae511092adddf82fd2a8f67621fbdd93d79c7890399","418fe494ac225bb589153e961a347a16c0248f677c1e443dbe52cd3082ba2bd8"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":3,"u2":16,"len":5,"rows":10,"Q":["906fd157cd2766032a341333f524a414a35143d16ff0ff5ff706ac9433abdee1","619f69a3323e23b3236a339046c3830379aab458512d8c668a4a06ab3ffe0fe8"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":4,"u2":1,"len":3,"rows":7,"Q":["29eddd1f1e841d77dbc27c907990d6d940e509fcb6c18e4dcf0010b93f3d4412","10d26f8bfe4d9ebe40b79c6b8c3b11ef51d16f64b2f79b392722343ed30a22c4"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":2,"len":3,"rows":7,"Q":["1a231ae03b30f60f41ef84ab613b3c257e4b8ca3fb9c7884619804048d72de13","285e1374b57bdf76a203870fdf8e079cb9dce1b365014cc06fba8932eb465a8b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":4,"u2":3,"len":3,"rows":8,"Q":["9e281be9033cb486fd73555ce71903e8d108159733c1b8c6d861bb56bf4051bd","a6e29decc49e02644ce392b24933f8fa670da2b69b10b9084ff3fdbdb7cba174"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":4,"len":3,"rows":6,"Q":["2d433cfa59e113dda1c9e8bef365f091774b2c12686a0e2fe97931d494bfe3f5","9408d5d3f0f2eecef9d78914526d1d768aef140ddf05387677bc1ff38303ff0b"],"shape":"Precompute,Double,AddP12,Double,Double,Correction"},{"pair":"G,R1","u1":4,"u2":5,"len":3,"rows":7,"Q":["f93294091fd490e2d052c38965ed3e2b893375adae889b529f02b7089398c1a3","49d797f993fe60643b21ac18493b7b092b14b80292c0d785b35cf8b3b4dcc4b9"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":6,"len":3,"rows":7,"Q":["09aeca783c7e3fe385e56461b3c1e36912ba8fd95cf54f2fa4050eb8327e000f","69d5d8d53ebd85204a343a19c712ea2bc2d47505848ad7f7c80250536e07ba5c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":4,"u2":7,"len":3,"rows":8,"Q":["5fd5443bea56423847e3661526c75cc89ac1cd4d29d7175cc74336d948a7ffcc","8068e18635604305934378d0408850268ecdb2c5546f2969d9c2c0543f415230"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":8,"len":4,"rows":8,"Q":["24fd52baee48d8c44ed656e44e1df137d8f5cf0835972b7b79311479985d65a9","ecd58424bcb9ad0d22fb378255d8ce144bde9e68504f75b3405f0602de2c19ed"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Correction"},{"pair":"G,R1","u1":4,"u2":9,"len":4,"rows":9,"Q":["051686bd57a5671a9e923d58c15c7edce241c23b490bc483ecc945544bcf16a2","82f3dc77d6de105cc1d906b0f39b4ab18b67b9b2a0eda32b8f931e7dbce1a409"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":10,"len":4,"rows":9,"Q":["006aa1574084317dec1bcd2d24c88a189ba410ee9814de53f88b59822259c02f","3118e958e7c5216d98b9ac17e2b5a8240a8d74b97bfddeba450e832e4303d68d"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":4,"u2":11,"len":4,"rows":10,"Q":["a249b723d0ef091d067de3132b3f14c513cf4df908e0d202491712c339b9211e","2437a734caa4c5c3e1a35cc6ebf3c866df7f7638c391417399ed931a5e4a3c53"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":12,"len":4,"rows":8,"Q":["f8408e8108959bf49a1cc31e372476b3ab69581ce7acc10af3eb93ef3daffe14","f44b6244c1b810323f2dcaa954ff9741f7ed6d265065801209fccd4c83f1cb7a"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,Correction"},{"pair":"G,R1","u1":4,"u2":13,"len":4,"rows":9,"Q":["d3d4c4ae0ccf8394de017f29ae00106e4cd38ea6e0c74da7daae6845c86eec81","9355265a63cecac2846f7687345a17d20a1feb8a1ce487b3dd2a3784a3d6dc80"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":14,"len":4,"rows":9,"Q":["cb98a1e226da7064b2527f4100f43f3106e9b74716accb171c7965acfaa2a636","2b3e28334eec7b3f5f62733f3f56a6187227e0c97b91c819c4f954db2c354c64"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":4,"u2":15,"len":4,"rows":10,"Q":["ecfd42159af41a94d7bfcea3d79c2bbd6c1a8ae3e22cb9f425f71ae6e334932e","ede02c4e9cdb71fba45e2f511ad9913c75955bb9969b0d77c10726919829f7ab"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":4,"u2":16,"len":5,"rows":9,"Q":["60535a0a76100a8c23f595f73d9890342129c779243c5394969685455eba9abe","af7067a60022dc187a4a03148c82f5557734197a0605273d6f77aef229fec6f9"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,Correction"},{"pair":"G,R1","u1":5,"u2":1,"len":3,"rows":7,"Q":["6ec0b02099baff3f04bdd60c9b0910b690e1d9a9badab607dafa80f148e64db4","6f9cc20aad17203c0735afe8d83e8eb1962d8ea52c972da23289f03d0c848438"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":2,"len":3,"rows":8,"Q":["a29514109550311b687dcef2a0dbeb84a740e78e1442aa2a12a25f11b952828d","909460c421d1f16eb13c86b34fbe7e9f94345ffd2595c392e91a1ecb37ae2f10"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":5,"u2":3,"len":3,"rows":8,"Q":["213974cfc284d80ba5e3eb158bcb4c4830c0f652c442ce9c40e904f8433b1f5d","6c06c441bc125b2322b1c1553b49fb7565cada0699057b0fa8cc03b26ddcd28d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":4,"len":3,"rows":7,"Q":["1847563ef36912d985045a7d563c3df59f4de318008a6b0ff46625b4b38d6710","4239f0fdbab3c627b8f67ef946c78054125bcbf0cec02983a622eac726d41a34"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":5,"u2":5,"len":3,"rows":7,"Q":["b8f138cf3b11db4666ac88abeb631d7ff8cb706012a02398898b3513abd34a10","ebb016b7d51bfe059d2be344b1ab784dd26b2d828133d200fc6328ca6cd7decf"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":6,"len":3,"rows":8,"Q":["46ba40ef5372b482864249913276548573ccbb5595d7b271da9c4c4d43f3bea6","b6aeb687197d3a546e41b6e3df9f8d9f6d42cf56a06342887587ea23b0cacdb5"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":5,"u2":7,"len":3,"rows":8,"Q":["b884f29a7163044e5179bb03d9778fc707f7256dc0c7466600c86a3af03b0f59","6462065cd04610a50bdbea192c4e5304cfd13102a4ac7d1ee7a9ef70649fcbad"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":8,"len":4,"rows":9,"Q":["1d7ef58925bd5fd0f1ae47323d28110e37b5d1bd6b17610983bb45a96d41b334","d4d366b1bcb76fd4b8b29e595ede869224dd0628abbe1eaa69539e00bf9ed9db"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":5,"u2":9,"len":4,"rows":9,"Q":["e02eb34d13baff0569ab934401227f48b7763d42edd8bc377b655ae06bd9a6db","caf19fd40f55b15f8e4ac0e0c1bdfeb2ecfa5d678c7caec388cfe4642284fd79"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":10,"len":4,"rows":10,"Q":["7233193458747c991027f3f7842b98db32f8e244560ad679cc430142a667c591","a36c07ce0261a093540a6e4c326398bbc15904841f56a1990595050dba50539c"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":5,"u2":11,"len":4,"rows":10,"Q":["195120396631fc30679a9f02cbfdfc3e5246efbcab49f0045a73e83df2353f22","f9f637abafcc4a82529fe8ed2938ab77b7f9816ace1f9af30427d3c6f2977043"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":12,"len":4,"rows":9,"Q":["b345d31686d16e6d4c909d227089177f3884545e808b3768ca067bd885185bd7","172cb3a0cb05d3d5f8267b5aeb7628c1b1804d87776de8ce894b46c85d92abdb"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":5,"u2":13,"len":4,"rows":9,"Q":["d6dc290ddeb3599558607d824382ea7e0abdddb2b8dab873dcb009ad90dfe625","4cdd1ad844263df3168eb94472154ba2fd23ff55eef4c051641aba3aa2cfe2da"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":14,"len":4,"rows":10,"Q":["059a5268cfef6acefa27c898163cd1942788635a51e2ed7143c93bfab5ee05eb","a2a903f28e31027432f3519c220cb2d76cf27203460b7235dc96249a8c4e3246"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":5,"u2":15,"len":4,"rows":10,"Q":["653b45d254e554958fdae441c3c9292bdff43dc72e4457e5dbfa8ecd58f83635","e3efd3893f2ddc954d76142cdfc489922315e2a0299bc4d6ee8b7b7e9fd174c9"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":5,"u2":16,"len":5,"rows":10,"Q":["e9c955d73281887c527c2e0291c1a4a8ff167772138eb0044cd2fafb0946771a","eb2e0e6d660f4707b8e622a36eca58e3df1f5a69e5c35be13e6685f492c48f16"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":6,"u2":1,"len":3,"rows":8,"Q":["4f6675f1c31c33e45cfb574e0b9a199f846d2e5fe96a1a3479a2693d535e9eaf","35817b8c221650a1e4ceda2c45682d2084d37af1b519a50e560f44b6a4d18d37"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":2,"len":3,"rows":7,"Q":["d1f5481c7fd0c6edc9ba7c31e2b46ee636accc0981e9ffe5d97938130fc978ca","12e2f23ab6a9a8e58c8577d73a861ad9be49de4d61a634678c7270f704ecf502"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":6,"u2":3,"len":3,"rows":8,"Q":["fea00e51a3a55e0367436c380f9ec6a7b4ed460b2ee23dcd8c6607232c029f37","6f08f68055a5362516bb251f3793ce1e6f3927f190b376e17363211c1d297827"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":4,"len":3,"rows":7,"Q":["54a0322b1fc3f457d79200075e449678af01a6b0211d0e4e9104eabf6b783578","9f0c690ef4ece9d39670f33321f038116d0a2c9cb4fd3b2f390fa49b72323be0"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":6,"u2":5,"len":3,"rows":8,"Q":["da9ac45c6a9c4a37375afbda058d82d23fc9b877d9c4ec3a7c5c7fc05e90f4b4","9def863acf3bfc2055e1f5dac30260a3e284b8546e876c57ec017ce7aa9b1f1a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":6,"len":3,"rows":7,"Q":["b00441663e2c29f10fd86e2b71569042586e3cb966edd85535328b104374f8fd","dd1c0b45d3cf743d3d70b2d4ef24c123e65a1fc89de82698e311f43baebdadbb"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":6,"u2":7,"len":3,"rows":8,"Q":["0a8c19e06e5601cfe52717886bfc11f785f02cfbc71f41b22bc134cdb85a22bd","cbb2f7740af6618e53b0a2ef6920cfa8dd4e5b0536cda5c9a0400512ddea03c8"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":8,"len":4,"rows":9,"Q":["1c7e8decdb5aea135c99b0b57e7ade3d246da5e3e7fa2986e79a28674fae9d88","367c0e3fe97797a646e280009ea002358461f9db2e6f9899c46526be9f775f70"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":6,"u2":9,"len":4,"rows":10,"Q":["c44c43304e92229332859f1bcd97b25ff2b17e930e986496bd2c327dcf7815d2","32bfb6d37dd751232f86bb2173ac6480f30a2b8ee6da0f171c2040d6b4dc3028"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":10,"len":4,"rows":9,"Q":["250f843c0cf8e14f440720f093cb90d86df18393e5bf6d3461f5e10544753a30","01ae5ab9fe844fa6bb99a971f209a43c776baba81ba1d1a0d14f4f80fc17534f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":6,"u2":11,"len":4,"rows":10,"Q":["3668df46309162a8f25c4dfdd121fe3ebbde71bcb8022f5fcede2c3d9989cc94","4bb5afcffa82b29ce3c80253b41c21543859c1b0e0cb3ede461660f28168de68"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":12,"len":4,"rows":9,"Q":["0652208aff897ecf191a909bb9db6d545d68d3810e14d940d22f64b6e617e327","569372f0d31c343c7863715930bb2792f9b887b08fd5920abe64d8a01d26531b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":6,"u2":13,"len":4,"rows":10,"Q":["5559ef154a0938a9269dcd99db8293e9fa630e3fe361b9e5c85d110fa2464cd3","1a510aa318c5d0032363516269385ffd3fa2287874d9c3b7e040ce4de9fccbb2"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":14,"len":4,"rows":9,"Q":["a563dd14e43849e45a439d9a2f27e684393290dfa09960a18f1427494236adf6","8341547ca562601a0b4a168c95e882ed0206372e90f3ba5c5e01ed5c4402d206"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":6,"u2":15,"len":4,"rows":10,"Q":["8dc217eeb5fa9dd633852d53cb0b5fabbd8e47e14a85b655cf5a5229819b0397","a42ccd7ae1371917086e2d2e63ce1fdf2bf9cced29f661227043c9cc2fc0e04b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":6,"u2":16,"len":5,"rows":10,"Q":["ff798dc247b4f7d00754d263e866888233647e18dee48cdb326090e5597342fe","1de6826fff0987743b19a6e1995860e668186b6e822f36eac22a7f7335770686"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":7,"u2":1,"len":3,"rows":8,"Q":["5e9ddd181713de8d8402b5019d9d26a7e7455d1ad23d5215fab39c7db713dd12","50b1c0af0d75121a982a8260d49aa17352419b48a9f56a3a6907634e8e4aa8f2"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":2,"len":3,"rows":8,"Q":["34db4ba879b7dc57af67d8cae47745b71ffca7353fee9b0da6801f90cf697006","e8327d5a2d7e7f43e2d4e953dd787b79a8ce818078bbcc386f0b565f67ac3d7e"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":7,"u2":3,"len":3,"rows":8,"Q":["1da70ee87710b6bb186cdcd537be17b30702e6023c725fd0f42dee3b3bec4569","129093c5f3cce841180916a1dbfb4c050a52f44e4eba810385d42753e0e1588f"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":4,"len":3,"rows":8,"Q":["04ce6c73006aa597807f34ca119d869198284df6c88d969597f04b6e72e9ecc9","aad4655924a4e77acfe1594450d5dea03667031f007920cfa82b2b6845e1e658"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":7,"u2":5,"len":3,"rows":8,"Q":["781c4371e283db5f4d06f4ca1df80d731472ca302e8facd900843628386ae4a7","ada9a023dc97b1d3822334da60f942a351b1b6ce601f5e089b211507b2203ab1"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":6,"len":3,"rows":8,"Q":["e56807135d64dd6b3098a8e6f076394f4dc1fa56138b1931389259e9cf6be7fd","84ed212f0239dacdec02495e921fac0c7307f80ed7e40669c6451eeb51c6cb3f"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":7,"u2":7,"len":3,"rows":8,"Q":["e7ade36f9508cea51e007d9f4a5b0cf2a5df775045f869a89a9a96957974df99","f6582e1f8322f4bc3947a9fa903665ab32c5257d1f30a4d7d4c2e04545ad6961"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":8,"len":4,"rows":10,"Q":["4099292f22b24f958f442e63b2e3cedd32ea285307486cb2c202c64e609b2aac","c27ce72d44d215d4aad342e14b411f06e545bc946a718e087311aa781db3c8d3"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":7,"u2":9,"len":4,"rows":10,"Q":["8573a99a0ed3d981646d7a71e9a2af50e479f4fa9c79bfade50012cc3eb5aa90","a798ce1b3d6184072f3fb409ac6d5cd99dc79d82c69ffc85aabcdd0f057c6ffa"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":10,"len":4,"rows":10,"Q":["4623e65f5f353ffe14064c5a4dea895063e8455ea84bbb78ad3236c8fc88d172","1a07ef97323a05285434ae7103db974231cd0eede8f649648c988894ae5d8072"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":7,"u2":11,"len":4,"rows":10,"Q":["56ab2e24f00226b864af91126f4980b7c3f3010832650bb182453e1dca488e32","a99763013d8d9c7d6ccb5334a74cdad312a0153cdf05ad3d291fce86b549509f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":12,"len":4,"rows":10,"Q":["8a277f1585bed3ba3c854a4fd27ec7ebcc95bc1d021b543c5b36d1898ac6b8cd","034f420d7d900740fbb2606fee4d092402744e1b59c22e54b36241cd4f74c1e6"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":7,"u2":13,"len":4,"rows":10,"Q":["a4e97af086b9221ddfe48b0fc818d86372f70c180c9c30e88433083652465167","aa2bb357c58b505261e6162f60279ad4ce4a6c500e4cecbb85a555d3dc36d447"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":14,"len":4,"rows":10,"Q":["739f215bc8b68bba3ab89692ff3e2363afa5f73c9a5a8a2cb31ccc08df0d5888","19cad2f9f1ee0996660008586b63249deadc64f6a4499ed6903a5d9a464aab29"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":7,"u2":15,"len":4,"rows":10,"Q":["74edacbf62c4adb6173da588c4b96b97582e9d451ca4d43821829393cca1e13d","92caf6a1ff27e897701ceb8655e21381ec9b55d1e5f8dfb7558f99f239432663"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":7,"u2":16,"len":5,"rows":11,"Q":["d9887f209966bae4c08008d1e430bddec27cde2060c799f13bf24add35466795","2f40e450c771a6b248452827d26ea1e67ac3df23f20b31e2658b70844701fbc7"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":8,"u2":1,"len":4,"rows":8,"Q":["35af250c1598486f325b1b764c824f302734927394097eb22a52ac4c23b7039e","22a29663f588790a91b37e9444c773e6e56069bb98c5f917870a55a6d7c2ccfd"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":2,"len":4,"rows":8,"Q":["415e49faaf6655d93ee379bfea556a1b60b87a03f129d2dd8464db125c2e9f7f","6b28957c7f768be9f1bccff8d108e47bf40e46ea3e3a43492c2fd88de0040e50"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":8,"u2":3,"len":4,"rows":9,"Q":["d261b81a020ca72fa56162862810507ae37562a88d3bd3417289b865fdad8cca","077e9bbf303afaaf056517bb38deac72b6d90ed6c7f4bfcd6a74f9345068458c"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":4,"len":4,"rows":8,"Q":["121283286e726a406fd0d7e5dbb376ceb7e541b2e4d8d2760fd71e03ba8d943a","8ef508c9303a4ffa7b4ce1e95df82acf8fda261e5035621b9aa28da030cf4bdd"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Correction"},{"pair":"G,R1","u1":8,"u2":5,"len":4,"rows":9,"Q":["0f860f3950cb9a00daf9dfa79dffbf2c645d11a63fc5118f910b80b451db2b09","db2e05dc3e02afc3d1701f78bf0013e58813a9a719232575757f6fdc2b211fba"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":6,"len":4,"rows":9,"Q":["7689e3e0af19c81991050aad15bc4ecd401703e6a167faee030c750897386063","d08d4de81d2850049ff2e3209cb898f5233dad32350ff60ea30e7ec2328cf45b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":8,"u2":7,"len":4,"rows":10,"Q":["210aafb4c0d1d7bb9f27a12dc1d0ce28762a89bb33ea4e6084b58235dafe9560","4dc28c3609feeee96981d76fb5f296d400ed046651a8c2760ef3c166a55f46c6"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":8,"len":4,"rows":7,"Q":["16494eea53a475c1607e46e683481e8c801bc701392a843426d0b85acbf07955","04ba280c148058fe5b01f35b5658dc28a3a2eaab4390d683ecc06106a266e542"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Correction"},{"pair":"G,R1","u1":8,"u2":9,"len":4,"rows":8,"Q":["5b38d679dd60a26bf27688d4ed451e45d780fee2077f6829c883e0c248cd2657","bd700be2830d10401c67b93b45798e2c4709b8a3dd5ffa31670c49de077e7ca6"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":10,"len":4,"rows":8,"Q":["9806d874cccb267851a7746ba14e8ce0e02d839961384e53101ecaeb34f7aa9b","6ff5cfd8f868ac916a886f6446f2699142d9388f05827b3073e35a85026e2843"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":8,"u2":11,"len":4,"rows":9,"Q":["494c9fdac2dc6631b567c10983ed9d2fa895136262ff55940a01b69f0aa440fe","ec1aa8585912e0055a718123cf0abe1f5b9b440f53cde1e52f94acd73ef1a390"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":12,"len":4,"rows":8,"Q":["be6a65403a91b81c802a23f685690d5a4ede4c1e41bbbb6554a4bc774cb11ee9","caabd0fcd18937f9f5b5dfdd009a494cee3684119119adf93a68123710dd2bec"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,Correction"},{"pair":"G,R1","u1":8,"u2":13,"len":4,"rows":9,"Q":["fd9695110523473b4610975bd3432df4085f05e240a8e4f3a634c18dea13bf51","58d711e17d0ca79b31f8f8a1d63402c1ca40c22558ec9f2c7be9af594c1c7e8a"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":14,"len":4,"rows":9,"Q":["df82c13a55b790e379d0312b44426e8269ca1e50c574a2286d6d808d02e1a69a","84b151fa06acd744da223d56a763a38e3612f09e8b84de155ec0ea926bcf2e0c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":8,"u2":15,"len":4,"rows":10,"Q":["95b1a4e5dd55110190553efdf4dfd82698fa106db5b8f3920c1cfe0a3e7fd381","6995ae5515e6b5fab756dbc999d2918c1a8b52c8d0f9876c6ead05e74da265ce"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":8,"u2":16,"len":5,"rows":9,"Q":["0c788860b9f7f5987845c8780f2bff675db74611b25cbb0563fdd58566ecdb45","6383e6dea1ccdf07ae5d623047bfd76e271e6a06328ccfad10baa0946e0aab1c"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,Correction"},{"pair":"G,R1","u1":9,"u2":1,"len":4,"rows":8,"Q":["0c67e38f9fc94c0037f823deba910abfd3996cf553850594cb9c33f8a467c353","8752377d0eb781fb444e66595c805e464ec4d7c2f861c07a197c289e4c794850"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":2,"len":4,"rows":9,"Q":["10b927cab276e6e5335ae682a030f58cd6b3c8eaa23b1c465403b060b8073b6e","4f264362b44e539da1208a10da47d819a5dea29a8c38c6d72e37ff04d4cd6b34"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":9,"u2":3,"len":4,"rows":9,"Q":["45af4c5e9ff98d0f20db8a7716d9c9db9c784a9b78fcba54eda09e299d56c099","9294b59c048b76dc10d24fd578d99ee13fdf33a690a181f5aec4e526ed7d85e3"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":4,"len":4,"rows":9,"Q":["960c79747052dfeb890c5885adef0e43c0d9346502f786d2de8cba0f5efa2838","cb266f91f117bef8524320cb211cc6b9086f039988d5a885b90acfbbd8a345d1"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":9,"u2":5,"len":4,"rows":9,"Q":["bcae46323d0ed2f94fb17e5b5e70cc1b50220fe5c05272a71b35605b309d8550","2de369ea764055734f4ebc92e308315f60c030831ebe77aee232e412ac94d34e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":6,"len":4,"rows":10,"Q":["42eab3137442df517216019c1287b1ba54842a1b9d7ecf137e028b938ae6f1f2","baf0c8645a71b7beccb2f334290c4f90049cb6ea1f86f7d58637d243f67d073d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":9,"u2":7,"len":4,"rows":10,"Q":["e3965effd28bdd2a09648261ec8fab02bd0d85cbf8ecabbc50abab2085b5e2be","5a6cf4002a566c3dcccb63230ff873aa27fc123d5ced798fc25ba3b50276a523"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":8,"len":4,"rows":8,"Q":["b4f79da94ffba1ab39f0eec962ba49795c36fb100526c8879392f870666975fa","43828507a1b695c01a56adf8e1b7abb597ac22d86c23c8b401a7b9f917da78a0"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":9,"u2":9,"len":4,"rows":8,"Q":["433a8dc2eebe940e70a5904ec74081750edd414ee1032181a1812f2d7fb725a9","c6b5ebed2506c3bb026ac45097f8be495235a9bd35f9383887a13d3cb3c92170"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":10,"len":4,"rows":9,"Q":["e3e95e271420dffd970ce59ec8a433689da3cc0d0d6c4964e6ab3147ca7592eb","24b515053d3a332a056c290e38c5530861e18993840fa6292293b453322edf2b"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":9,"u2":11,"len":4,"rows":9,"Q":["5dff16eee834ba671054f71c221ac71f893b950c738be7c5da7c1f2eadc1d331","858faed00d5f767908e838be43c2e7a4c7e5f2e2b8d892d006d720cd80292e66"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":12,"len":4,"rows":9,"Q":["5b4a479873c9b4d1ac096f4839336da135782aa12edbd63c0a52da8d1ea8774c","2347d50d1faef55699e49e66915c625ac5b9bf322fc95b8b664d928d285ba339"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":9,"u2":13,"len":4,"rows":9,"Q":["db6be3fc694db80948918fdc6fe7b060acc1314a4b0cbaf396b7d015d283c474","969ee75e95fcf42a81b6612c43134f5b84f5b1570e4682a320ea03ac42c0e26b"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":14,"len":4,"rows":10,"Q":["f2219b3ebaad51f0a1e53443f19a430240a8db306baec871d9d85c4a45b441d9","205f484d06360553bd0fc0a1fa2cfefba6f04eb2e7591389c2b873a4891d70a6"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":9,"u2":15,"len":4,"rows":10,"Q":["eee4ad2004f4527259e31e3914c5b3a87683c45bb2e42d7c608f55db63862ede","578905d34fa42d05df229d555dc757ea5131c03ef3485c17a4dbcf1d1ebcebe5"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":9,"u2":16,"len":5,"rows":10,"Q":["3b3b142d3539b418e584df55b62ebe8764cfa85961f007d5b9abdd2a8f45f8a5","0b687623966d87b28dcdaab0d27e5ce86feb4293ffc4de9a4b138f1ed53f52b4"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":10,"u2":1,"len":4,"rows":9,"Q":["9ebcf3931d761b032b4f291f74b9973b911cea356733437200011b09855dfda4","ca4866f83cc28ad14864451b0de3bfe5651f52d78ad32b7f111cd8dc88bd5277"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":2,"len":4,"rows":8,"Q":["6d1f59ee857e516c5c2824de89d0e9dc0115799cd700883c2c325e1149f8a1bf","938a6b196733c256b33ce328160e642b6e42e0b286f4d0a0aa71cf830e0515cc"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":10,"u2":3,"len":4,"rows":9,"Q":["d2b95d666332624dad9009af6aeb2d2a647e5e2a1ce434e265981c8e2f940eab","2d683324b358b66f98cfb064c25ebac42086ceb942edfb8fcebeb1a876fba857"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":4,"len":4,"rows":9,"Q":["52cfd3c69298e880767fa5cdb4022670b26dd45905dec62dfaa47dc9165080d8","e0a1078b21d176e13fa3c71b3e5d863a61f9c031e1a222b9b4821b51479a1033"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":10,"u2":5,"len":4,"rows":10,"Q":["b1485b3770f225f634e4d74aef90f3f4885144f4fea0af39720f47c4c768e2e2","c59526e84d2fc093caba96dd359bd0d2e9be040bc6dc135ea5d46cd18b40dd91"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":6,"len":4,"rows":9,"Q":["1352e898d3875807fb1bcf4d43ee0fef64be23561d22b8c5a9297694bfebfafd","450789f297cb019bed9770571038e7b6ba640c7b15da7dbb50dd9c2ada994949"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":10,"u2":7,"len":4,"rows":10,"Q":["c3d3b895419b9035e1db351016451760d0850ce24d16d679a1d5168ab22f56d4","b73918b990fcc451c2eef9a8e34ab609ec00b6294c5285f2ee8805021ec6ce4c"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":8,"len":4,"rows":8,"Q":["b74b560e44d0b0a346247bd9c8e5836592f3d5abb42015088b0abb8e16e070a7","2f9266f31efd3c4550407af8ebeee3316bfa07e14da97b98a1d92b5f061df68c"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":10,"u2":9,"len":4,"rows":9,"Q":["5cce06d06e2dca8785a49a54c4d14cac28cb6b7a7086e17ae00c1b47cd557af7","ddb300c0db0d8617cbd40a2eef84f5964d50b987ad9dd4be99c9694db2852121"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":10,"len":4,"rows":8,"Q":["37d49b8f45d17397a47442629b36cb0ae7ce5b85da9db59bfc15a2f6c2319f5f","1a1d0e52fc393bfe751ef71a714bd43111726f0a80dfcf7823e743e2724d3d72"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":10,"u2":11,"len":4,"rows":9,"Q":["175d212346497c1af650680602a61046318dd91aa4acebff431c32d7d9b5c2ad","3b1c7f274045928700544a70a00716d21b8a4ee4ebf2ee3d7456e8dd2f253c16"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":12,"len":4,"rows":9,"Q":["ff55cb430b3069f5a44f5d045614f2f9477cb02e3cb526336b62cbc4e246e16b","2f6c86553cb732657fde9a98373fe4deeb65b41c343837089966fcbbeffa7d67"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":10,"u2":13,"len":4,"rows":10,"Q":["a706f998a99bcea8d3b1cf009b1eee09ac071592e64e53e6cab2a3c5ec1de10c","e82773cd51babf2261c6dbef4c6f1528eacaf1d8065cd94c373118beac8884d7"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":14,"len":4,"rows":9,"Q":["37415f1097ce41af9343266861f7c2da82ead0100f8a05a6de92334b26963b7b","8bc05a94218a6d77419327023a48407bc95cc9539da56a99ee61813e2fc5c66c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":10,"u2":15,"len":4,"rows":10,"Q":["ba936f7409d312b5aa1668465f8db8f75bf30765a2a23e4956aa14c7d091e92c","d8e384ebf7a3a3e9811a34e6ea7e40bc5a6f8970aced029bcd52e26ada31bffc"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":10,"u2":16,"len":5,"rows":10,"Q":["c946db28390aff0f6e95c24d212891321b746f948455335598e83ea26c064a1d","28361da1a3c9d4103806d246767ff6319d3dc563128a71075a0c174c020e602f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":11,"u2":1,"len":4,"rows":9,"Q":["ed950532b7160daca6fc7b08856cdede87097e968641beacdc331d276068567c","357a12399fa6f50f017918aeaa86c4555edcbd3d66a922df3cddd46e8bbc28a8"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":2,"len":4,"rows":9,"Q":["c0374383409e0381d64f50508df731095ea41a0171c485d80c48b2db66639556","2fb99e1ec2713f4b6f53d7aadbb428f43cc3bed9a902b25c66c749dfc1b777fa"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":11,"u2":3,"len":4,"rows":9,"Q":["f4515fe3557fbc36ad6d7afb31e8b967b994da19f4cff705cff8156c2b4a4188","6996f160b48fcb75b5e78603f4e9f77912cdc66d7e9f6f775ebff73db50df54e"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":4,"len":4,"rows":10,"Q":["5ea2cae6c0ee4366256b8c93c738fa4768f129ce5c9dcfed10a3ed3fbb7cf23d","aacd8ab9afe8e5dd7cb74bf9007b57f31058d360398badc7037e6ea5e1a544a5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":11,"u2":5,"len":4,"rows":10,"Q":["78babd3ba98a6628db77779e646b40f08dbcd9c0b4ae9f34381344977ee16b31","37176ee666ce2e90e4acd8c889b329d958c5bd56b11487b85ab2d1fb72b91fe4"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":6,"len":4,"rows":10,"Q":["bcba21d61e57ef91982c95c15afbd102de21afc4fc3def7259fd8359ef41e15a","96f771b99745db55b2d1e4b92597f0ca6664d7f7ba95bc70d6a60ae40af6cb95"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":11,"u2":7,"len":4,"rows":10,"Q":["1d9027f4a34acfe8074d8ac35ec01883fec9004ab553189588f5298b385912d1","a630890c03311a39550d85ad82cc3c2e8c82f244e9bcf9e513af3f60b6fe462a"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":8,"len":4,"rows":9,"Q":["caad664e9b0ff5f2716f8d3320aba27eb0a48aef715324b4fb13cb8d76dd3b0c","4dc270ae54fed5ae5653e2d922ba15424bfd708548927a97b5226a28884f9420"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":11,"u2":9,"len":4,"rows":9,"Q":["2da4877ef612c878822c56f5d219e4f62154c6d52a67beeb34a463988acc6bdf","226c0c7a80f9d6dbb338314f52846ee8afbaa7ae306aeee49431196c1a5f7690"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":10,"len":4,"rows":9,"Q":["2b6372196296b8fefe8697c214bd66757a508fda1144f48ef309fd6f425d40f9","6d7a7fc9658e01e58a07e1da9e69dcce229e0e17d774801406282c9675687896"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":11,"u2":11,"len":4,"rows":9,"Q":["58ffb8e2a59d3e5e4f3137f55e6483b2b7292639ea643dfcb9d7b5fe5036c322","23f6467c95aa86ed5275b512a8e5c63e2da1e6853284f2a691c18e951de637be"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":12,"len":4,"rows":10,"Q":["c9b395dd11e4de8a0a6505d31391a92b6b19e35e43a041c64114b489ce4d8428","f31649b13ab48a7eb035b3ae4fd30328d4f9116fa267c2172d3f271e94830acc"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":11,"u2":13,"len":4,"rows":10,"Q":["1aa8474374595f01670d5851176f82f73a30dc797d77933c23ad1b313c662e2a","cc14278d5b9abf3ddf5fafe423facd3bd92a3ffb122794434e85acc3cc320838"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":14,"len":4,"rows":10,"Q":["a6a68cfdd4ce5de93164ca1a81563d93c8428ad624e1ca7b84ece98469de1483","dd4348e529d0d45deabc523a1862f140ea61a4cf04c42385b3774196cbe02de0"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":11,"u2":15,"len":4,"rows":10,"Q":["bdf285d6bce7e7f791153f9bd8172cfb5edbb7d0177afbc551ae37783613dbae","3b69c66539a81dbf0ac28690462c5d391b3ac4df3854dd0c75d00c10c6d2f951"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":11,"u2":16,"len":5,"rows":11,"Q":["782ed5fe928f4d1138689b323e72bfadf705ee2d37dd3b17fdddb57077c7efdb","64f58f240e9d91d3c6ab60076d7c2a4b0162af8a8bff401cb1c093427e8708a6"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":12,"u2":1,"len":4,"rows":9,"Q":["a0a66f5cb09823b0680da57646201a1638ccdbf92516ff3095a8fcb01bee45c5","249565a0941444d5ba52e4fe8e7aabb0fa7d5e7f0faf6efdc14c3ef930c2bf1c"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":2,"len":4,"rows":9,"Q":["cbfc65bc0e71f7ebc7f2127589790f0d97a7126d9d24c1c7ff3cf1d704696abd","9232414abf85f5ba321c12c8c98c582fa8ae98531759155e7ab70a0d6fda83c4"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":12,"u2":3,"len":4,"rows":10,"Q":["4879a2e2d9b23b3f1b2e4088b853a76766525e577461be0edc38545951eea199","5b634adead131d2d3edf87253360fb721ce2528c88257af6562e85251ce67254"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":4,"len":4,"rows":8,"Q":["43cca5f2d4a0124e2cfd57acbdba80ab8a282c1abe406876300156661ab598a8","56452931887c965bd6b18458d08f8b181c47388dde6a6088de5757993cd1f6e0"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,Correction"},{"pair":"G,R1","u1":12,"u2":5,"len":4,"rows":9,"Q":["0039f33c74e4266ee024e5e603dc1badf0185d04a6f09ba056176e3376c87332","c4841e122d357903e5d86912df120c290c30004b2b826d4ef7896545c23085ee"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":6,"len":4,"rows":9,"Q":["14a5cfc435298a4acdcf519d497e6a7629d69ab98f21e4b8eba7e8f6a1742133","b2b7a7a7f7a85ca71f5e9ee3ea4b63922840b32283ec77586713e852a578faf1"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":12,"u2":7,"len":4,"rows":10,"Q":["e3f3d4ca14c22ef447a64b6546e314cb3a1c0c95d1dc1ce4d84ac033dc0de229","51d6ee8edd81dc4c9f78322a6772ee61edb183b653855503a28669638f7eaaa4"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":8,"len":4,"rows":8,"Q":["309763ac1b73fa8ceaedc7dd957014ae5741d5a27e1a8cfd6c3ca4f99b876b78","7c4fc7848aea44fa6b8fdb3c1f9e2ad796cd7fd784d632f11088a7272256181d"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,Correction"},{"pair":"G,R1","u1":12,"u2":9,"len":4,"rows":9,"Q":["f82f42a563c34b909ba9e4b61b74733563fbaa2153aa8688555a5e44582457e5","d854e95fef3f16ee6046dd2b2fe880130ce962825463e0dfe07ea172e3549de4"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":10,"len":4,"rows":9,"Q":["5ffe78a3c2572fa8d2f071d35607680e32d0029ec6ed9b9520ccb10c4f4bd226","d13301da3b433de3fc2f9362e3ceebe8ff5bbb9e7ee12b4ae671606ba3a257ca"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":12,"u2":11,"len":4,"rows":10,"Q":["7708b5719e4801f4cd602f6c026ab3ccb7b9de03672b8a6293b7f85b5f7b80ae","71d71404a6fbd848d4784d4f41d853ad9131059f0a7b76af64c0bd51a349304b"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":12,"len":4,"rows":8,"Q":["19412b02674efe65ebe8d74fd74b781b7e54bb1581c049ca57bd27de18b4714b","d3c7a1ab38c1e4804d010bf53a5baffffec12a27b9b2bd16dfc8d3efa0ba267a"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,Correction"},{"pair":"G,R1","u1":12,"u2":13,"len":4,"rows":9,"Q":["03d9dff90538a2e1599fe1f38572bb68aa9e5e01956c11facf27e75701969ff3","48032c5a40d9dae6283eda58030cde41ea9a1590e477f77712e4e6263d3511ee"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":14,"len":4,"rows":9,"Q":["f502860f055f6575558fc97e536da2b6f98ef6a531ff0f0406dbb4df814ba012","7263688a86b719408dc41563bf2fee6da0c7cd2f02cfc79fd64d4058c53f41d1"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":12,"u2":15,"len":4,"rows":10,"Q":["a54c36035966ce4f2c41bd3836d9097cd1d674435c33684254b16517e80310e2","47372217a09b96b2a2b342d294f7ef30cabc60d39d15c13c8e2543f5760d3a4f"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":12,"u2":16,"len":5,"rows":10,"Q":["72af70770187e001ce1478f449891b8faa0b5aed55a1d205889a7eede50654e3","ebfeb1982dfce146d275a59f0a7b01ed65f53a518ff0a704bfbd705dbbdf2fec"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,Correction"},{"pair":"G,R1","u1":13,"u2":1,"len":4,"rows":9,"Q":["71d30c48f7cee5627a91a34f169f8131747807362b1a02d2a19437b5a3095b55","75fcb013d16e0e01b0ceb365259d4ee72821e0c459b575c71d86137ad69be342"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":2,"len":4,"rows":10,"Q":["a50eb37d32d9fa7e14dad12cd64e0c9661d4d3b97a4db8764505dd1104f9dd9c","83fef81674a223840e8f41a19ba7e51e74409bcbb25bf8558bc0fe675047e3bc"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":13,"u2":3,"len":4,"rows":10,"Q":["092ead09e61d7740d9eb6f0449bffc9ddbb8cbaf59105ed69815e233b081cfd1","f15d53617d4617b01b02b8469f8d6516dedc7a18e04b34638dda4d25e92d35a6"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":4,"len":4,"rows":9,"Q":["21ed5db7b66330d350675ea55a51d00c009a86d19183dc0da3c06acc40514fb8","15170774cce0101c651e99990bd5d5662e39f0791fbdde6ac32ff5986813819b"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":13,"u2":5,"len":4,"rows":9,"Q":["52eb7f091bd4e289e51ba04db4a2e40e6c70d503ffdee2d1c68babd545c945d3","a856848f15959b64cbad526a01edfa30f9436a89262542e9ef04b6c0838a6057"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":6,"len":4,"rows":10,"Q":["80716d66ef06c75fce757151e6bede7827feaacd6f54ae65e021feae16c38674","059ea9f7d46381d6266996e9e2c0e8dab5db45c454573a1794ad5d2db04d3080"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":13,"u2":7,"len":4,"rows":10,"Q":["83fb09dd284fc758da5e1d4945119831a7d21c7bc7dce6940f0d7feea52eb7e1","405822937d9a1d72a8270a07a0a716e20e6cbe312b0f329ab673e938072217f3"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":8,"len":4,"rows":9,"Q":["874101e7cb28d07e996e93e73a05a197acd3bb3b95019f423a7776ac78969b1d","4d1175bf6d89b58486b2b651e1c27006afb0658f851ef822e957b46fbcdf3383"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":13,"u2":9,"len":4,"rows":9,"Q":["fd260edb69c42fcc774b13f268fde8808a401f81598c2a0bcb7b2ed195c388a1","264dad7b08e82125f58649eb649acb1b3955b41fa7f577d5abc894b637aae0a6"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":10,"len":4,"rows":10,"Q":["ba626383ca423ca0b25ffdf25cd27e21c597b804b4e7ca957e4752eed54a588e","55c845e29d85812aeedcb2bae2dd98b82c8c37b16c1b520fd5b94cf25b7b3e51"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":13,"u2":11,"len":4,"rows":10,"Q":["7ecedae6d3ee8f56a2ba05f5cfff1f8d1a70a0591671ea4d5f216778826b29e1","87de61198b316becbd7ea6b376ff7b3c631da2b1db50ffbb4ed7b0d356319271"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":12,"len":4,"rows":9,"Q":["ed8670d1d1c0396a61a603e93bfbbbd566f8495ea512477054c7ea6c8854d18e","af93f1f0aab15b7ceeee310435b27233110ed5f1047565d7f73e6c4b0497b16c"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":13,"u2":13,"len":4,"rows":9,"Q":["feead679b552900ef869cbb6326471b26b204d4dc7001d11e32c4c90058f9120","8a884569669629a87e9fd277757b669e37863afadd54994ef65ea3b36ce0009c"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":14,"len":4,"rows":10,"Q":["4691f87a12f74bad8687f652d75372da8b17b6b0ee053327bcc62c987f6072e5","6b93dd5ab9d2c4fbf1a8514ed9476a3c484cb27cd6e750e82ea270d22abd0e0f"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R1","u1":13,"u2":15,"len":4,"rows":10,"Q":["006874337c3c50ea5545607677e1d1ff12b770bb959768bf523a00b0cc3483f5","277ab0a48940347ec09d8e0d4a90174274342c3dbe7d0d24c6a37fdfaea489b4"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R1","u1":13,"u2":16,"len":5,"rows":11,"Q":["3c311c6f6554d3bac79b3026a48f0711ff8dd8ab38cdc05ea66b2b43b0ed2c26","a0ca60dc84f5bf374b13c608e52d83bbd66ab1a95546e1b3ebad0fa3d45613b1"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R1","u1":14,"u2":1,"len":4,"rows":10,"Q":["bece64db19978581fb443d81fbbeff3afda4ead45a2b183fbba030691f481c48","d1b9eb1dabeb14b6df6644b9797ebd5909fefc9d153c4ca7521bde0a3660a77f"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":2,"len":4,"rows":9,"Q":["fb82b3c3cc1818288f8434b51218472bf8164a1d0e49228ba171092c32c3839a","a182d16dd6cea953f51b1a374395a3f86c2b3fbedc8eda8faf7a23fe6f6c829d"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":14,"u2":3,"len":4,"rows":10,"Q":["cca1ef59ba69782d6a86bc2f3209f1101e1173020f2be832debd5af7951ecee5","a203ee49193b994be0077b97b37180fac76b5e5c0372c916d3cec789d4683da7"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":4,"len":4,"rows":9,"Q":["a33c47e1c7d6dc9448c51c141dadf45e31070d68d490cb9f9896ca641ec75424","e2461c2cbf330fb70e9e74e57e562eb882d92d4a96e9fcedff3ab97cb342942e"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":14,"u2":5,"len":4,"rows":10,"Q":["89f793bee050b6d52676831b2a775adfbebf6a775131c25041c07ccb73ff41e6","9c950e71721c367df422c9975d94df3ba59e89f4791480fbd667696e906b206d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":6,"len":4,"rows":9,"Q":["df4b6b3183a3c3e23152a5be9c96692286b2da814835c9ec2831665788e3dd49","651c7707402dd891273820c8a8aa6be17f5e35cc0ca356aaae395cf0a1d0d1f4"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":14,"u2":7,"len":4,"rows":10,"Q":["e0cbbb56e61775a497dff632ddbdcf9f1781f7964b2272c414c1cbafcd220af5","a06fc7a39a338cfe60dde64cd7116b31fab11df917fba2774051e9125f79919f"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":8,"len":4,"rows":9,"Q":["eaa69083dea54f2dcc89f9d22d1f66031af59ba28456c3fe316beb663d8b0644","427e4281e1370ec6a875ad5fc6087a8e85b32333224baeef88b4a3fa4ac7e7ad"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":14,"u2":9,"len":4,"rows":10,"Q":["82ecb1d5c5eca3348453fb289432d8c9381dd3090e56144abe836c8c21c79189","8efffed88f9b42f32085907859ea371da20c531bd9ddfc3bdbb3a34ef46de3ea"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":10,"len":4,"rows":9,"Q":["90b45c45a6d7b2be107d3e61ade4d424dcb9c38246dbbbe12ac74deb4a450514","33b9dfc1c164146e7cd3fc7e2c2fbda3ffd8fde532787045883010e01958f4a0"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":14,"u2":11,"len":4,"rows":10,"Q":["e0982053fc208164395c796b0faecebbd1cd5de1f9241dbe5bfea3187edc9e1b","06b7c5ab2d65518a4839c24aed12716961f8d8331d4a678e61787b6ccd3515ba"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":12,"len":4,"rows":9,"Q":["4cc3895e9a6395fb473d45c6000d15a006739b891959eeb121728935491d1627","cfeaf7336a07e7d3dfd0e361b4ae6728abaa04d0e3dfbf9a820283c2cab567c2"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":14,"u2":13,"len":4,"rows":10,"Q":["6b633decd1fc38760d4b726fa06732b23dfdff20c4077bd1843316535bd5d8eb","e9dd10c4d7a4f6b443517eea1ff97ea5eecaf49accaa1815d7bd64202030e557"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":14,"len":4,"rows":9,"Q":["dea7a76c4255a89975e3ff401c32ac3840cc9a613961b2327dd857229f012c81","e4a736d8975d82949f5d107f9eabd97e45d28184ff8ebe19382def5fd564e074"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R1","u1":14,"u2":15,"len":4,"rows":10,"Q":["ca9f84ee9fe8dc20b1c3fafa84665a61663bab0e9f61808cef563bc2ff6ea238","60984f2d111de7636030a0fd82a5a91ba911359114d14dd979365f66e6974ca8"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R1","u1":14,"u2":16,"len":5,"rows":11,"Q":["91b4a41c90477c86551be367db495a3e1607cb35a4240d5bbe9975f07387a996","2b9059535ab39ad98bb218b056a13d036ded82705c39450f3fb2908da7ad5aeb"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R1","u1":15,"u2":1,"len":4,"rows":10,"Q":["5f9fadeaf79ebcc546501a329725cb47fcc35b512a0090c1ff601dfb799fa2af","d03d9871365451ec517ef89860f120ed4c630dbc213b3dfac0307090431831f1"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":2,"len":4,"rows":10,"Q":["56499a82b161bca1e51ac6c554d65b6c0aca2652d8b5f667e78988fd449cb119","6c479b470d4acae6b37b2ba3dbf65f8d89df5e934d14cd4954270b29a83e6d70"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":15,"u2":3,"len":4,"rows":10,"Q":["165bd82fd20373c6f3d4e801f951cf561cf9f1de13e94683c02791ccb5ddbe09","f31a684935faa5b5569861b2be1aba38fa2b00b752e79f0b5b96fefbee80173b"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":4,"len":4,"rows":10,"Q":["588382dfdb2c506f31039040902f4a77dac891a9e0c4a6e93dd46f1ebf47df82","96cad3b622943ac47c56f65300d6e2e1fab8f9feba03f23b4a8352ddf5de2552"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":15,"u2":5,"len":4,"rows":10,"Q":["845d5f1a09dbc6ab4889f39d796831a1afaabce0a308f5d67e74e02e4d0a9846","f9edd27ff6440d31b500a4e7c682193530cfef1ebdf0c2d1b699b5af2eecd603"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":6,"len":4,"rows":10,"Q":["fe4f43bdcdd0c872eb89dc1a35c8da5a90869bc01e2c450885595f7efb526875","3e09290fde8820981d7c99dbd093a18938a975b9b55998cc957bf5ac262d1d6d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":15,"u2":7,"len":4,"rows":10,"Q":["b8e069e435d865dad820275986f2e3fba1e87f0e2389131441daa2d6ab7059e9","a9640f0e7570b42ec625c6ce1cf8cd574b538e4cffe850753143a1cdd0a31227"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":8,"len":4,"rows":10,"Q":["67a2c614c615a90ff483aef720c8a7f1d1fe0f5524542dc4ecde9bd52078133e","218a24fdd36332ba3219c1cc96f5fd0e15c6fdb96d23e6fcb30b9a12eea7ccf7"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":15,"u2":9,"len":4,"rows":10,"Q":["39cab3bd5ddb08c80cad6b50afcb305414b052d7317f2d3053649ebc98c3822b","14bb0098bf12401eeda4c1194e06f02f5428f52b0078f1c6b68ece91fc4cc798"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":10,"len":4,"rows":10,"Q":["0af3b8ffb76b6690131d83757550c373a85bccb5493c1ed07f418061c2f75b8d","22ba0a92deadcf0d3d5e26fc1cc6afc4506dba0f53a897a480fbb822a1fd8559"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":15,"u2":11,"len":4,"rows":10,"Q":["2362f9e1d4a1cb9c5a3508c78eea3d939ebdd69d8d84bc89f2769b1465b2844b","05ffcf162a1d86ebabd144b5f75bc24b520bdc86dfb93253d24c60b9caf706b8"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":12,"len":4,"rows":10,"Q":["7446026f84bb5b79f9d455e311cb1836f86ad9ac53dd0ad8feeaab2ef539af3d","fe3e4dba681756cea0468120d74566e9760e9672fbe19c7258c1327726971ba2"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":15,"u2":13,"len":4,"rows":10,"Q":["2ce08d6e8109e8eb4d1b576a8f3a6ff73446307f85a38c2d7fd27f88a5e7c503","48bba6127fd9125b54922ad201cec25c46097a8f57a53156a92b038d561c5667"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":14,"len":4,"rows":10,"Q":["dfcb99283b6184124fb670a09d1cd834008bb0caf0f17745e9df2183dbc29d13","1364d23847a4b1a5083eba66c0e06b5bddebca46cc8af376ce589af0fa23a1c7"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R1","u1":15,"u2":15,"len":4,"rows":10,"Q":["950b88595b4eb68f3103871473cc9ec61ac3146b2f0bc6d7f03f995e807b00e2","e1e73f8df227e5dd49d7326091249a88604e6fc8dac5a3a58b7af4ee942408f6"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R1","u1":15,"u2":16,"len":5,"rows":12,"Q":["e2e1ea91aad91192a06d5b0bca7566be0168c89ebcb282bd945313ba3dffe9ce","4d270ab56d7e53f31dae05e11e15088f509fec732c8abbb746778794f5d0daf6"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R1","u1":16,"u2":1,"len":5,"rows":9,"Q":["dd437ea753b238fd1e68077f0118365b71be24b366bd9c74a23e63c4823de1fc","2a7524bd18d322f44681e670fcd1927140264112eda319c2e7c60c01f92d7ed9"],"shape":"Precompute,Double,AddP1,Double,Double,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":2,"len":5,"rows":9,"Q":["a5991d87fa64b712d8d872d618988fe29b208876447f05a4a27e881674e7187c","3f84a1595e84a8a829f96f608846a2aa90262d8e6c8631ee7069506fc05d74c5"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":16,"u2":3,"len":5,"rows":10,"Q":["b1061ecce29ed6f722167154cfffcb416528a2cd419ab5fe202c5b076feaea80","9c89df46d7218e92014101f06209a78b3cc97a4f5d68219005d555c3490cf291"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":4,"len":5,"rows":9,"Q":["801a2d421b400660e3e9e8b4bbf085b84f7365a16abbc92c5a549784690e1929","4f2c80db3c068b293895610a562f765d1e1c5a61b86bba963ea16566cf0c176e"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,Correction"},{"pair":"G,R1","u1":16,"u2":5,"len":5,"rows":10,"Q":["5c0cfb06610fde55b91d68e43f555db0a4ab3f1bb31663071edbfdc3a0be8a5f","31ffed4e868c47b97448c81b3538136fdcb4fa937e2a0af00abff82db57f9dfb"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":6,"len":5,"rows":10,"Q":["48202980164060b0e0739641320d9cd6d92fcfb578acb585ec219d4c5b689c63","1dc05239efbd7ca97098018731f0c66a40bad3267020e73c066516918e25510a"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":16,"u2":7,"len":5,"rows":11,"Q":["2344d67a16f45d9d543c7d931b2b4dd6e7e82e69703ff51bbc8cbf8362c1bb32","6f50340db4b18f47d0b6ec61e19845bb1838d14769ea11f5ac37fcb93903bdcf"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":8,"len":5,"rows":9,"Q":["a5b914a3622396904b4e457b4d84400c7d5bfd0f102108a423347d06c0a79f3c","7b078a00fac2cbae57a0f6b6bc9fa015b5d13bb57ce38f5faf507b0901d4b8c2"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,Correction"},{"pair":"G,R1","u1":16,"u2":9,"len":5,"rows":10,"Q":["182717e1caa3af200b3ed4e0a99ce9af0b3fce257419d936c624aa49046b4810","bd70f6520c39205d1f9073271f45aa803a31d5d8b6bfb278ca5a64d315aada33"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":10,"len":5,"rows":10,"Q":["6c86901d6fafd31509aaab2f0cf147a3b6576f4ef58782c1152dbc79cc6faa2e","37bc10d11d8f40073354a9ee6f8dd9369018ff46ec507388a84d7e4c13716295"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":16,"u2":11,"len":5,"rows":11,"Q":["78bb5e5bb17b3ba8695db1e938232807aeca5ddf8b38b5c974b14a2dc18342cc","3517507bc9d6f5dd3f4704386681f02e72f1941443c96e4585ba0f424ae32bfd"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":12,"len":5,"rows":10,"Q":["7be92184589837d1d82090fa1244bce37f6399d2927a4f2f7a0d8537c29a742b","0f7b3571c50863c30b5b6416893442691ba82beb94d0adceac4ad6f7ba37b2ea"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,Correction"},{"pair":"G,R1","u1":16,"u2":13,"len":5,"rows":11,"Q":["3672484a5a44b8fa57aa625b4c7aab47b72ae30936b357b0ce3983b0df38bd0f","a185b27499dca285ef7baf888e30b447744d20aa446f8ed2db03ce83c1ba717c"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":14,"len":5,"rows":11,"Q":["1696d12cf721517eecdd9f923b4ff6b314ff08034b8f87d00d549509905f430d","03350ef6a2fa9b8680957c5a0e860341869632b78a168c492c06168a733a917e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R1","u1":16,"u2":15,"len":5,"rows":12,"Q":["e884f1d184e204c281952cc9ec1a0c891317700eab368db3c18787550704606f","f4554fb330fcd919b29748bb33aa6c51a306bf01511a0b33115072d96dc1cebb"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R1","u1":16,"u2":16,"len":5,"rows":8,"Q":["2fe0ba3aac058fb7076371ec90207ae9d0d3880ae1a67f0866b27d61b9ce8dbb","8ad1eee2eeac4e433fb17310b8df52671ea9e3e49cd63620aee77593bfc37f7a"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Double,Correction"},{"pair":"G,R2","u1":1,"u2":1,"len":1,"rows":4,"Q":["c9c30228c5ba1f42a58856fb12ee8887a0622b3a0605aedec4e42564c1b94057","5964826d642f7e6dc21b29e8bbefae2ff2ad980a10c6771c550c8bdbb4d0f7ed"],"shape":"Precompute,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":2,"len":2,"rows":6,"Q":["5c40f1050ad3496efd1b82fbee6ce032d56bd195603dee292070378f2f0b0b9c","a73a34d1ffa1ad88bbae4000f37c4cf8fe79cf6d2f232963806fe20ee12c9b80"],"shape":"Precompute,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":1,"u2":3,"len":2,"rows":6,"Q":["269a9508f37e849c85fd21cc98dfbd948743d477c08b01eea8550194fd049047","9eb415dc46d4180b91bd4f696667719baf0b841b9c1b246c4d1390dde8550689"],"shape":"Precompute,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":4,"len":3,"rows":7,"Q":["713eda6fd82b1e0e1eb33bf5c3553572a4c393927facfdc30b158a46ccf34e96","653058f6b4ccc146679b551b65b24b6e0f10946d2969fa80b1f481723fad551f"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":1,"u2":5,"len":3,"rows":7,"Q":["2b0e341152b8f57037fb2d5d00c987a9acf68ba5deec0132d3742b697584cb91","c2911a24f25f31f6504237dd4520960ade954cbf4982327c0706c7d576ba125e"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":6,"len":3,"rows":8,"Q":["6fc40b3f742bfff1b5cd6976e64fc4d7644ff350456e1b4c030bd02f955f748e","b1f769a930ea999074c979f0c479148ef6abd133ad953a2ad389f4ec19f3f3d1"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":1,"u2":7,"len":3,"rows":8,"Q":["917187e47f145111fe0c4b2807ad9191569ffe1529f15a7d31fdcc02bc54bbe8","3c8b3d93ff0a0655fcb5e5b9618ed3dd7ff05a1be604324f4170bd1454568e05"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":8,"len":4,"rows":8,"Q":["224058d33bb00144fd5b5e99b619fe2952e486d4be2ba19111529454794d3bf7","0bc5e217ce1f76d08418529654cd7cc443425ae8110e253c39777d09246c4125"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":1,"u2":9,"len":4,"rows":8,"Q":["259fba5db281a687a7a8fc67d68d3652114a647d118ad39aec244c6f322406a5","268c44dc140e07f81eace13c32922459b62173048493a14a154009079e46a09d"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":10,"len":4,"rows":9,"Q":["0ff2a118c7d30dfd318dc16b7fd71275f6f438707880925f9494a8f5d27fdf8f","6c56a52c40da61128152a8fe180662735cf14adde996f431f3d8c231f0eec54e"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":1,"u2":11,"len":4,"rows":9,"Q":["21eee836b74a5d41fabc133d895906d4ce538a69ededd3c4b9356f73628c6f4f","156a31154cc1f2c69b80c6233c36fc612d0794c1261f9a654374346272611311"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":12,"len":4,"rows":9,"Q":["8aeafd494f5a29edc8af460a3fbb6897db074591ac7e3e98d792ff5be2c826e3","ef0c7e70fa7cc73c4406b7551b218a75781ae5f7a96c5a7a5e9cf4339da40956"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":1,"u2":13,"len":4,"rows":9,"Q":["5a70a96a28f4e7886d1705bfa7eb7a35f15a823566106db582012dffa83ccf38","a897ba09a69a5ab02a08e385b9fff0862e44e16d0e79dd7a7d195b55694543a4"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":14,"len":4,"rows":10,"Q":["cc4887a9ebe1ea51f02af1565def812a7c674fbd1be9d226bfc81af85d12d8e9","4d876784eb8f98378facefb888b012db87450d08e5d828db7503d6c7176f6dc7"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":1,"u2":15,"len":4,"rows":10,"Q":["19208fc28561e00aab29c7ada36cef3d6317bff606c4f0b8a82a1ea67e6067d1","e910b9f144f95a99c05047b13563deaf55829e808856a33bcf1d12d94ce21aa2"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":1,"u2":16,"len":5,"rows":9,"Q":["2e5fc9eb8c55a9228d05f8d768e72fb4295af160f113daba2acc9185a1241832","c29c32d0c6a90c35c43d2cdad37a57d74267e2dd2f0235f6a7e60fe8966ea2ad"],"shape":"Precompute,Double,AddP2,Double,Double,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":2,"u2":1,"len":2,"rows":6,"Q":["6f64b0e18275fdb11e032923188fbb438b3fd1480ad34eb1022d084f880d1843","0d427a360a3e0f0843286eb1f596973d410e1f05223a24a69d95a23e919ee28f"],"shape":"Precompute,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":2,"len":2,"rows":5,"Q":["9c4db4699acc71a94173c2c4af929b2d0cbd7de34e20a6921147a1ce50a61da4","9496b23eb553d8e48771d4df3a8d1445d51d3a3ad06da95c4684e49c17bc687c"],"shape":"Precompute,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":2,"u2":3,"len":2,"rows":6,"Q":["ac1b7777869eb63c8d0bc8b7fe31c5214709141b3440da8301c9b2ad778f0493","0144dbbdd863e38e12fa0e5392895fe00f693a42b4dee539dad266a8d2b8bf02"],"shape":"Precompute,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":4,"len":3,"rows":7,"Q":["4614d048e66aa71e3193ca96164c102398503248492452775e45e539afcdeddc","72c67e2efdc6eaa440f0a2a574b68275fb16452a8694a48e1fdfd5eb1ba40b96"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":2,"u2":5,"len":3,"rows":8,"Q":["e84c4c7da45da0ae074db48af741e16f5d6efe7379a98d054c1b1d479bb4d1cc","96ff49ac75d8677747839772d602822eedb0274dcb645536badcfc66a7a2920b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":6,"len":3,"rows":7,"Q":["79ec49dfb8eb93650a5a89f5402d41fe1e9698716b3518e84e2d8be15399be7a","301fa40de691e6b62ff6fcc0fa2bc50902faca4f20cd401377e3c598f50424bf"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":2,"u2":7,"len":3,"rows":8,"Q":["5aca12b8750c33b126a40d9d67df65097a2515db19ca13529dc1c66cecd690c1","0146c2c326777851a11ac553b48c00d769d8d3cc4c369542f967e7810e6650f1"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":8,"len":4,"rows":8,"Q":["9e15787e8f6bb1214e19556c55e70bc1c2d5c5265cdcb4be0463cc03372579ef","aafba4b6b08fa64f461f31e658bc82b9641337f7b384a8ab7216524adf1c43df"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":2,"u2":9,"len":4,"rows":9,"Q":["8b73447e643ce9e5bba53da7f9efab902870c16ba388f3543c8cfed858a8793c","4af00b6c80ae7059ffd31c8792f9010bff303e37578b3e2c48c76c5d147f59af"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":10,"len":4,"rows":8,"Q":["35c58b28e1b7967628c70874ce780cd2504e35ee4f6fd8cc1aa5841f773abfea","caf1d7b25a0df3b8a5a4a39f1903861898f214badaec34c9a5b1092f71ad7f7d"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":2,"u2":11,"len":4,"rows":9,"Q":["d3f4e692b1df0245adb183fafaf5b170cfefed4e5c33eb58ddb6dc77d9a9732a","de2598bdc485a4ec2c7bdfadd60506049b6965560703dd729dd528b2e32ae6ce"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":12,"len":4,"rows":9,"Q":["2b7245bf7bcdf75bea35b239cae2ae5d46669b0ac0438c49d12953e462294a7a","de7876b00672e25657befdb163c1bc676efb2f5c958058736d166b03e8ef54c0"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":2,"u2":13,"len":4,"rows":10,"Q":["0237c45faada0aa00281e180f29d8391b40c3009b17a0e28ddb87501bc693696","b49c3d1cb5527a1f25e30dc772d208055061c42ec07d24f7daef8bdb315b9ae1"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":14,"len":4,"rows":9,"Q":["c555353050d769ad30b86e739aff4baf146036e21d12c06e2ce3f72887673052","c67e703deb149a238e5104df3037e135a65266448cd13ffbfbe68e684f1003d4"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":2,"u2":15,"len":4,"rows":10,"Q":["dab2f23e838d51a733b1627a05971a881d856123a7ae03147c35cfa3c002a262","0a29f857aa43fb48981e175e54293541cf59267085991e496a4d4a373124bc5a"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":2,"u2":16,"len":5,"rows":9,"Q":["21f6344b78205b2a713c62934be1caf1800d5af19ec1c445e96e247beab74bae","30db8c0d96ef630dfe3df6459370d1ba067e61ede275e9d7e70286f3ba3d6eb2"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":3,"u2":1,"len":2,"rows":6,"Q":["5e1bea30c62ef82559d78feb0ad3c645cb32773366b66c3974f69b70e9f20e55","aeace61e4548528c87bdb7850843a3ba562c93186db0d379c5930229d85dbd2d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":2,"len":2,"rows":6,"Q":["aa09ba7c7f3270dbaa54059fd97fe8272d4bc8543552953270ebedbd548c42de","f86650178a2f2b7f45bcb82d8a7c9e0bc933dcc360bf5a7741c0588f8b2b53d1"],"shape":"Precompute,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":3,"u2":3,"len":2,"rows":6,"Q":["94eca46e34747503429cc4a58c4e37afb6193890c54cff6c0c434da7e77970bb","34d2962ac921cb6ef5e88e39a5e0b9efc496526e39eadbd1b1fd6422971abef6"],"shape":"Precompute,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":4,"len":3,"rows":8,"Q":["a68447f2df862791b4303aae41deb6b81fec3b889b0cd43e84f6540fc80ebf97","8942721868c047b0155829e0bab2bc1c056531258b5a4fffbc51337d16b34e57"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":3,"u2":5,"len":3,"rows":8,"Q":["e15a493b8cab430c4ce43b5bbff6bf8ac0c1088df902d46d5e884c28920e4e7f","c347a635fc9149e8fd0c11cc48ccba9fd398f9009e931c6efa6c8c8272fa63e9"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":6,"len":3,"rows":8,"Q":["9f767028f2d8f5d80fc9c560377b466399dc768a67b430eb3894772be1b4b38a","d31c845bd0c2e15288b17940a01e4ad47c8b6676d3e376accb15c7dca394f46e"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":3,"u2":7,"len":3,"rows":8,"Q":["6be36be675b32618cfd4a7a152479e09c8ffa7bae16e9c7e46767a2b1416b7e2","b3fcf6c699e5c8c0928dac942f9a5353e7d790b04c1fe0c6d6f563275b47b1e8"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":8,"len":4,"rows":9,"Q":["7620efaa4937a038352857be963a3ce5f580fe3c8946741bfcc1241a16d3de47","80558162c49c0369939d8d45e0f51959a555b2bcfbbc3d3cba85188c632909d1"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":3,"u2":9,"len":4,"rows":9,"Q":["c213db68d0108fa94e576ded7984189d78b9f3a2e3dd19aa6c51a2f5ab908547","ba13ed0af352fa69012f286bde4e16c2a613ac84814e2564745bf9d2f48084b6"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":10,"len":4,"rows":9,"Q":["014458424aff79b6bbb38a1953ce8c6ab9159d80444bbc6f5090844901e01a72","0a8edb78dc9fd47def4a248d824335ade92441b90633a384ac977107ab4e0b79"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":3,"u2":11,"len":4,"rows":9,"Q":["fd8faec51cae92f1e26fb6038c0fcacd473371c7936204a18e1332a15b48f993","3417cdbbe43bda66d263de077e4985c8d8ad3c3f086a7f2e4c7a8df438aa40ac"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":12,"len":4,"rows":10,"Q":["f67c931e5860aef88154c23a4a514f2c1fadfb3b28b7f4b777db2f466bd61c8d","c22df250bce4bfcc533201f645b23b382bcf1114559204d74fce81350f668322"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":3,"u2":13,"len":4,"rows":10,"Q":["83eb99a864691aaed2cb200889e3400dc5301bbc9c8e6ef6d7b6553de2734b4a","07793333592a15aaf67f32d5d0a034d8e1dcf9c7c57341a24354f063c27e93b5"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":14,"len":4,"rows":10,"Q":["4b1d0293d6537854126760a4581174d274223bc5001b94f8b4f615b34b851eee","19f97e6151f4b41ff60b6c008a40ffc089ecd9b1e16df7665a3abb9d0c7b5ad7"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":3,"u2":15,"len":4,"rows":10,"Q":["53ce1f69b6b799cf59613db12c8fc3b0144e33661ab3a2697eca0a99e0b395bc","d15ba064bf07454f96defdab845754a65c6c469585fb1f175f386a24a79a2b2c"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":3,"u2":16,"len":5,"rows":10,"Q":["909f205ddf615035b0a91602a9538cc41ec83d69683ba0aa2863b8e33edc9a11","054d246e56c297f3275b9bbe1ca10bd5ecf6e2b4d5588d5cb4229c8a24b746b3"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":4,"u2":1,"len":3,"rows":7,"Q":["9ed9b922784802622a7608d615ee01aaa5198a465aa8d428efdc352b7eb7797f","e64ee7291ac75be03debf71c8952cbb3ad1c7833e7486bcacb233fe43d08bf20"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":2,"len":3,"rows":7,"Q":["0b9d56cda217939002cad28b700930dbd1702fea1f875d04fc7fc8b57a32435f","7796ac9fef7946274c869f8f581bcdb02a4538e992c8d3488e95ef8feda86a7e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":4,"u2":3,"len":3,"rows":8,"Q":["31b9723d42477d4ec10d955ca31c117eda3053e65a233c470b03f38d9dcbacd7","5bf4a224701822cf2ee1e9cf11b49cca31cdcf96e6c00fc42e3a31a850ce9fe2"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":4,"len":3,"rows":6,"Q":["617ef4b09b46997aabb846fcd10f74a46d5bdf4819c148f908ca6fb185a33902","79a99d06c2dd9a14abfd36fab960b978a19322f709cac33c055d2c2d1de08efb"],"shape":"Precompute,Double,AddP12,Double,Double,Correction"},{"pair":"G,R2","u1":4,"u2":5,"len":3,"rows":7,"Q":["ba35eb9b4afd1cafd5354ac8c63c01843e5d792b4ce2cf2f915e2995d69a75fb","6310dacf80154953d4b11f4cb86798d6455f9e524c832bb88fcc6dd337384505"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":6,"len":3,"rows":7,"Q":["8b25308e0205e3154788acc2254657cff51c320c4631ca62b84db40acd89b620","c9d116347294f897c87105e4d2370da2df29965547f35fa20563d89e1d547c8f"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":4,"u2":7,"len":3,"rows":8,"Q":["441c31219e42692b9122792b894ea7bfff42b8e27ccc13be6a32343189134489","f1b2afd959d4b68d7547555b7bd05ae8603f0da12157e3ad079218860f829c4b"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":8,"len":4,"rows":8,"Q":["892e16fc836bcaf5afee936a340ecc52fe484c71838ebc524b415e6f1c4f7d26","63633519d2054576bebb33eaa46c9b206d0b78e30f1f2cdaab2f31207d12f2c6"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Correction"},{"pair":"G,R2","u1":4,"u2":9,"len":4,"rows":9,"Q":["90c5410e35dfb4bd9c786b1950f66fbbc0174e0cd7860cfa4d3597c3e539e73a","cad071398548e5faf06563bfcff9f2f9e1897be8c516e3cd1165492b2bdb301e"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":10,"len":4,"rows":9,"Q":["2ed3505bde5c2f31c954bdfb40b398a74c48d58e76135ef6c4c0ee1e55355e82","5ffab70d8da885e6424620d01878a8818caff9ec30b8da1aef0cf5f1c248ceb0"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":4,"u2":11,"len":4,"rows":10,"Q":["6c8f92bfc3a8585b94bc381e1090b6aa067ac09a33edb9e095faa40d9b111859","d4406e9b84453c5b47428d21968ff665f5865e693d6c81ccd759c8cbfbfdabc3"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":12,"len":4,"rows":8,"Q":["1588b9a05dc0d6f58bbf4cc0b6496da78cc0255d9d7e6ce895299d8c2532298b","737ec14eaf63a2dd1a9469d4662d101232a507c19914064598a14b8dac19bc68"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,Correction"},{"pair":"G,R2","u1":4,"u2":13,"len":4,"rows":9,"Q":["35dd12e61f4457e2daca107e7c38fb104e202f09d6ae9640eb944b57407931d3","d99f6b83d659c0bf5d4f9bbcaf241e722741fd78a54ca91470491e71450bf127"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":14,"len":4,"rows":9,"Q":["c54c81ef50f6ded1f7b697eb42759c4b705b0b77607b3346a36cf7898a29dec3","3f08e60390b48ee509a434f006660cff001de275ac94e195f86bb22048240ad9"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":4,"u2":15,"len":4,"rows":10,"Q":["99d91a6d48791bf73c8e696d55d53e145aa77d88c5e6c564a01f76ff1c03302c","ee4a02e9bc03cb48545001a5bd56d23c181b3601601b64762ec16091180f688b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":4,"u2":16,"len":5,"rows":9,"Q":["11ce34a59d4fa7cff1cb055d49a84fdbc1126892cf65401ee8161634a11ac8a7","5a8f4b4b68095cd8bce8a416a73194c5c0272b96845ba59c255dfddbffefa068"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,Correction"},{"pair":"G,R2","u1":5,"u2":1,"len":3,"rows":7,"Q":["1968dc8233fc340e1b776d83303e2be1d4c8fa937bdb0826b85d9dd822aabcf9","7497bbe24cc88f36fe37cb2f2b5c7091e18673dfdeb64a9fb4e6250e38c39b60"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":2,"len":3,"rows":8,"Q":["207db8cf6a76044975148bcc719102591a065576003b24b9966772386d4fe0d6","ab83263e6f1b6cb91be9e796a2c300ac61d6c978764ed2b1062bf94188b80896"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":5,"u2":3,"len":3,"rows":8,"Q":["8ea1d0469c6c2fe27132f5b4e32a449729dc265206730077b3a485061613d33a","3742c7874c1409d7c4e9d4fca3333d718e5135e12acf87b0e89e97c4ec8ffc2d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":4,"len":3,"rows":7,"Q":["04f62274d9fdd6bb770013914e6b8388917fbacab72f91121365d0ce0415205b","02a1b18c79da86395132976dde85f2d1f575baa3aea423ce54d3931a72fed70d"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":5,"u2":5,"len":3,"rows":7,"Q":["868c339937895434d4c7228fd03fc4ae3311a9f08e3e1ec25df83c51403995a5","0b91af79565364f7b7e7e813265fe86387ceb885d6c9bbfe1e60badb64a251f8"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":6,"len":3,"rows":8,"Q":["afec2b6d2277b1e486ab7fe24773d104aa7b344d8b0edb773514ed831503d9bc","012f3d3fc2872ec3b1e9f458a0108245dbadc2f455d62ff4a0ecde14366c46af"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":5,"u2":7,"len":3,"rows":8,"Q":["237e4c3be1962f344d1b410faeb3e33db032d1c1969d6125b2ee74a2dfe62208","6320615fc9868694944836bd5fbe5ace7ce5e9e0af598c543ca43e09b71f53af"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":8,"len":4,"rows":9,"Q":["c539dc7c09950c190bae2e8383f3097141022368431435d6175b517bdbf2e6ed","e8f88723cee1fcee3c0fd943606303052b45b5b08983f398094e374751bf7b6b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":5,"u2":9,"len":4,"rows":9,"Q":["f46604292ae417402e7f617b7c4409d40c9d6ae4b3f77730698854bb7e0e4aad","3a74502b7b685eac97cce4f350dee8b22c1521687881600253a875409c825e42"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":10,"len":4,"rows":10,"Q":["c27be3c51656b28ad827561f0cd5f30fd2168d3e393513d080cb4f3126a0eb52","6840b429595ecebfd5aff81d620141c67de4b1a02fa9dfc2dff97338a76cb405"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":5,"u2":11,"len":4,"rows":10,"Q":["922e62fe799ee1fa1c86b202971383e95c01102c2841fadf764be754fe420f2d","c8ef7796b958614267843c27e0887f3e6485b41c50fd2c126d3e66424d42db70"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":12,"len":4,"rows":9,"Q":["17b62f7ea697f44121c75705d4055773e004dfe6207b4391cd3b2055836b3313","c0255c85025fc426571fa72382ac3810f45419afdbf54b4e946d68ea0c7e9961"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":5,"u2":13,"len":4,"rows":9,"Q":["90aa058f71f6cdb1265c08cc3c3476178cbfd3a9ebef2c28f3b588c8ce7d7cf9","552e5c42d9ae7b822953d26d44ae6f8dcbf5cfbada7d6b8bd6bedca503251157"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":14,"len":4,"rows":10,"Q":["666a40528f890d5b0536130b8029652aeca99d71dd3395400b0aff64072a7974","03b5d6dff4b01a7bcbf18e6e05726567788fa8d108e5d352229ebb94123fbc3c"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":5,"u2":15,"len":4,"rows":10,"Q":["d801e2f86ea4c36a4ebc1033f527e5428fd88e1aea52bcd5a0f15e302263071c","0892f19d695892ad339d52c1b9be3d86e81881cff02947e714c729226b066cb4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":5,"u2":16,"len":5,"rows":10,"Q":["840602e49be792be90378284a1be6056ba492e5c025466521d8449cbfee4a051","3d022a49ebbe2bc772934f9dc63e77293100749b45c5cdf1a57580a5a7672f8e"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":6,"u2":1,"len":3,"rows":8,"Q":["96a0f352e42219273c9c41fbf8c8223b39cd845358a848e21fd033cfade2ad69","8e4e078822c8b44da330205eb0a1764c7e65b33554b9cd759e904256ba476d68"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":2,"len":3,"rows":7,"Q":["12e8ca1a129edd90b57b12b9aa5bb14bf1a6254f847e0925de89b809719c2af5","0fe2fb53e9471065054ee466b78ae1bc7bbc4ff520ac9cd7a9d4877daafda2fb"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":6,"u2":3,"len":3,"rows":8,"Q":["d71b73ab6f6928ae65204756f14c21e6f7ec2cf63badc4df0a778bdef8b4c53e","d14d74b9923e2df6b76d1f476c43261799d4684d8af74fed79b26707ebfc113b"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":4,"len":3,"rows":7,"Q":["2e7da444795e1e1d9560d5a0ded5baf514cc0754024a31e75b8a4e27f75d538f","d706b95a6e86fd194e8e0cfe49ee6c22228e01b2682314f1f3484aba764992ff"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":6,"u2":5,"len":3,"rows":8,"Q":["af65265c80b3a224bef0986e4835398db5b4a6ae2e5c5c5a3a2fe97e04758417","63769bc87045e6083dc91ccca937c5755ef08a044fcec17b824776ecb90641a6"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":6,"len":3,"rows":7,"Q":["846130cb0d3f8ae3ffeb3dd83f91c3f1c5660a2589efa337dae6e85a32434f53","fd88e3c48e3684a3cb9c9439efb4c7295ea1f46bea0f18322e21e4d9e1ab173f"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":6,"u2":7,"len":3,"rows":8,"Q":["f786c4db801d44210eb7cf00eb232a810fb926b17008e65afa34de4303701cbe","ff58d37bfb737b101950e336a7370065185016c5cbff03836a7ec4d9fd80cf9b"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":8,"len":4,"rows":9,"Q":["024d418519c7097df96b7d920dcd7a25cd908424315c6becf3f81507957e0cf8","fd310cae03d1aa48928a53e5ffeb98d9600377191bac6a8fb3c9c3d70f49c2d9"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":6,"u2":9,"len":4,"rows":10,"Q":["e0ad29457960963c934f86ff28da5281d3348f8e3318196a4631010ea58fc7d3","e69072032939b1e8a562a61624a8cd180982fe1223e6ddd7ef93ed98862ffedc"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":10,"len":4,"rows":9,"Q":["26dff47e078e9aef25863c2590164e1ae5f93642d26d683f915d90f53a09d3dd","6336fe7ea5d84074645d00e56b7cde3ad0976bfe54c2df6d6c6d631210847423"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":6,"u2":11,"len":4,"rows":10,"Q":["3110d0774112adc0058c2d574d4e38686229879c54e338e291ea847dcd59872d","a08a74520a28c4cff3801f356d3cd9606fa6d174ff2d1042360b52caa7093eca"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":12,"len":4,"rows":9,"Q":["b2ba7d0b7ebe77ee2460788bd52a097274a5481e7fbabef79ecaf70ac0ab6fdf","8541a7be5ed9769000375b6ba91b5023ceb9fc11285a4b27eaf34674d39b73af"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":6,"u2":13,"len":4,"rows":10,"Q":["54d89c2d20913826c6db53cce0d05d55d99d55f08c54943964eb0c55bd3362c8","3de4da797f31208a20eb0d6ddc472777550b3ac67e33039902ec4911afb2950b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":14,"len":4,"rows":9,"Q":["fe3d9646ccdd79461c64e2c38e4e5c41108a9ae163e6f7df77cc87e2999d6e88","e4ec919f7d87f22c8cff6229cc22afb23dbfc54a334831da2e13b5d6b914752d"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":6,"u2":15,"len":4,"rows":10,"Q":["fcc07a8c900f2b30e13b6cac6cda54fe258841ae43e926c4cef072d3557fcb45","b9eb791a2013b6e15f766ae5f90c6deb1b57806cc6a09503314414f7d716dbb4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":6,"u2":16,"len":5,"rows":10,"Q":["51b937bb09115913e10b25afa7f2023efa08586eb8f695730ccb513a746533d2","06233de8759586effae66f0e7fba4dc020bd784e8e28dfc2bf0a7137109a3dae"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":7,"u2":1,"len":3,"rows":8,"Q":["7730d61f60aea0e22d5ee99aeb03613074fc9f01001602283a0b8bbb5e2131d1","bd9927f14b8cfe8475f6b500366bd25b67e90f634b19c8c545ce187b96595372"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":2,"len":3,"rows":8,"Q":["330459ede082dd9721867c5b1edf27e987ff80eed8c9c5d5bec7a24f9adaf8f3","eb52d0746ad68bea261cf56ce694d4c129495080d2caf79fee4b251436a94226"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":7,"u2":3,"len":3,"rows":8,"Q":["b7b49fd5b21ce4307ba3ffa300f10a1b6fecb794ad0a08494473a8db214219b6","7ad02f35a62eb9630dcb00d5f7de1b00bff2388aaa228beda53aa9b9c3c1e598"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":4,"len":3,"rows":8,"Q":["1f3067ad70e40c90b54bbfd04780ea336021bc685b8b572a6d7078f729b8ed44","553adce2a440925bf2039e330d8ab3dc3707a7c2b5941c38333ada432b162c55"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":7,"u2":5,"len":3,"rows":8,"Q":["99ac294ab6a5a89e8af603f099d03143c4481fcf670e031534598529035fb610","1e329bf9c8f633ce34ba14604da7f37ad3a88234ef99a4637895f63ba89eec0d"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":6,"len":3,"rows":8,"Q":["597eabc64e082dd78c231d90552fce2996a4a4d3465e73b400a5c6fff5e08311","c1779e75f69285d544bfecb137a8455a16c9732ab3deed06a031d939e2f69519"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":7,"u2":7,"len":3,"rows":8,"Q":["153f4d20d6d905db76d35e953223bb75a7c4a42d3256a3df797a96c23e4b8846","74d1f2c39439c0edca945ce3bf88440d02945f251d8c91cacc17a12f27cadaac"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":8,"len":4,"rows":10,"Q":["a51881d7dfe21b0072bfe6ac86fba1e35edfffb23b0518550ae74419d3040f09","db789e484e3a5ce8f53ac47caab50313bde73451fec197a7a39217794838333e"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":7,"u2":9,"len":4,"rows":10,"Q":["d18955a21f581154a33483cbe004d6668a8bb2072172617911c3d3f44f8f0ea9","a7b8be605b3edfa150be6bc1b3a075138f4ba6c2e4522ee46c29ad7a3f8f3aef"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":10,"len":4,"rows":10,"Q":["6a7ac195ffabd95cb34bda72f89f44dd171e9e303291bc91bddadd3ec676e1ba","bf220c01e823e9402b441c02ecbce358bb82e7760bb6329004644ce63846b075"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":7,"u2":11,"len":4,"rows":10,"Q":["323f6ccdf3e331b46c6654e0daa5b68f7b754dade09f1fc5fdd92d9419f6c2da","179d9b2665ba2aa01d3ec7cbf22675e93c3a7ef07fc5d23925b4a0ba78066f15"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":12,"len":4,"rows":10,"Q":["5f9e75ce523bbab0744cf12909a25c9451bb4ab60bf9cbf878ea8b72e5c1e094","b0f487d18e5727c0866592980424e7d706bd2ac4f34b7de0f3828783e38c2323"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":7,"u2":13,"len":4,"rows":10,"Q":["d240e4dc4cb65ecc2233fc2f63a45c4389fc8c5830c49315aed20f129251bf11","093ed671fa3fdf4b63d6ea88c9de036e4290c7e021ec29a0f2557e51fe511f97"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":14,"len":4,"rows":10,"Q":["976f551809761c0bc32cb4cc294df0addf4503e1343141a01ac6e7793286614d","d61e9a7d8967b19c41f6183f8940f91ae68996e81fa3659564189e29609c0086"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":7,"u2":15,"len":4,"rows":10,"Q":["67d4f8160309838c8552c6f7744fd7b937dc0a2f521e82d922af55607f1a683a","6abc4f3898b0bc3f6e1c8a3447f63d5dcea77985c059f85eccc5ed325ea8bbc8"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":7,"u2":16,"len":5,"rows":11,"Q":["ab99680608b1b8e244211a2d6a51503d43633275ece16e2c99d3f93945482623","da2bbd78d2c9206d02a417c919c919bde5a3bd4736fb885b34bfb8acf1327767"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":8,"u2":1,"len":4,"rows":8,"Q":["8af1e332b1afe047d269f3e86734ee82fe05aa20df8ce5ee340d150e7b9cd242","4e93b03a10be8bd7645dfe1bbaa1db47761c10976c54d146c83c465aeb96c3f8"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":2,"len":4,"rows":8,"Q":["9217203b421e2f9ffebb97216de2c82a6303a234d9e9ea2d78825d2daf8d8cf2","092e87903037be47dd312163aaa46822776463914a6feb55593ed14e29ff8eb1"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":8,"u2":3,"len":4,"rows":9,"Q":["498dbb6ea1b4fa844280de59185ce46f559d9640525f00426c0452db7205b144","c863141e627286ef8ae611ac6686235d463eaadb599fb8aba31e7f8dba6e2fe9"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":4,"len":4,"rows":8,"Q":["5760e19b12be5d9af171d820c0e259c6e1da54fe1f210bda2b3052ace57201ca","eb03bf5caac3010a266f37bf4f01a0a8770d1ce3e293f392458c6c7c5f75a742"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Correction"},{"pair":"G,R2","u1":8,"u2":5,"len":4,"rows":9,"Q":["6b221e4ecf43dcbd7d48eeba0c7efc19a89ed05ceed25fd08ec2063e72bec5b4","b1a5db64daaee799ac76d5bbc022b6e1e47605abe21b07a791b229a519216b1e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":6,"len":4,"rows":9,"Q":["f3f608d56caa65d3b6f347b74a11443ab7c1a2c9c4fef40928e9ff6ae28473f2","0072dd66f6956b7e96891f28a1adceb954f4752ff80f0433ce2a52a5bde14531"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":8,"u2":7,"len":4,"rows":10,"Q":["878ea009e019b8199294b79e3b7ea051e8741ccbe8fd24715a64cf48275506e6","2fcfa87a49a4e3a6c5a0dceab4f3af7f045b4e5d815177561683a9338d2bbd09"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":8,"len":4,"rows":7,"Q":["b3d27b7d0d7cd340a04537e0c98037dc75295c40b21283ad9ade3f44ad4a4720","535e29cf6409af46828dbbbf5cecddb59071c085f6e41dd9c8d0ec17a6ee8df5"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Correction"},{"pair":"G,R2","u1":8,"u2":9,"len":4,"rows":8,"Q":["8718a871b8b612f11a9918099aa998f5f39c60b84eff0b1fd8459526e2774797","a41eaeaf5950e4ca4ed394ecac761dcf86548ecb31853f5096b469fcffaab8d3"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":10,"len":4,"rows":8,"Q":["973aaad749d02b4166c664f3cfe7bb8da88cdfb13b9a470e6c58285d0a0904b0","a55456933765c2e3e66f4aefc2db060cda852183ad36e2991963f2e684488f9c"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":8,"u2":11,"len":4,"rows":9,"Q":["6416bcb824f7f8ba5a752fa04ec50523028e93b8f8689a4ec562a20591aef212","db9fe28dd40967617667a617fdb3eeac626ea11b4d343a5097ee77c2bb8b169a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":12,"len":4,"rows":8,"Q":["b1ec49ff2c6dd6ffe2ea8a643a5477011a65936620d8fca467270f480466b006","14ce94c779eda09e5d27a1903a84de29f99ca5e7a88c23bdcd6feb8e88e52ff2"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,Correction"},{"pair":"G,R2","u1":8,"u2":13,"len":4,"rows":9,"Q":["bde7762888ed94d7dd3fca376f00c673b43e3bd85473b027c0720339494cbfe3","8e9399f89e146c20777f4388094365ec9ed85d20c0edeb40b3d7bb2c3e2be8e9"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":14,"len":4,"rows":9,"Q":["32ab4131e0b0e64bca33859215eb15f30c7bacf737c32874491fcd543f92bd93","729c4b38e7da6115d246e969aeae23458bd3a8c4d7093a99c42e84deabb29e94"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":8,"u2":15,"len":4,"rows":10,"Q":["09af0808214506d8942f62f356bd4f2fcbf9145da7c447b4003b9cf4c8b6efdf","d60e612c114508d886d2c0c228a9815cb18ac67ac765a08cda1d975159b48f0c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":8,"u2":16,"len":5,"rows":9,"Q":["1782965d1be45720c281ac77df44fb172dc2e7d79f871ed39d0f9ed39022891f","2a52bd08266401d83f64020dd08fdc3e562f49e9ca7cd2b903ff82ef1bdc79f9"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,Correction"},{"pair":"G,R2","u1":9,"u2":1,"len":4,"rows":8,"Q":["11e34196673d3286a578d8448f8e58c77de32a8121021da340df0c9024500fe5","e27e8ec242a05835e951c0085d4c5ff49e2509475651a2a17350cb36611473f1"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":2,"len":4,"rows":9,"Q":["60da50f76018b9c8a36fcbb68baf53c54a35e61e61177b112b6b86867c254e90","e83e02ea6c6d9373676760d05004897b1401b2f68ee18cbc225cfd5dfdd7d42e"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":9,"u2":3,"len":4,"rows":9,"Q":["2336f51bfbecd094c781e36626311f590b092637ef6ee433c7740b9fe6eb67b0","ecf365ded69090ea2892c7da503aea462d5124b42b99df55de4a7fd8c4e5d511"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":4,"len":4,"rows":9,"Q":["ff8df0ec03c4d79cc9aa82283da28516096198109947025b1ddf4b6524af0b2a","66cbb320d87ae25438bea1ddbb00259ecaad59f8fe44d23845b47422f5576e1d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":9,"u2":5,"len":4,"rows":9,"Q":["7b35f971c6b4f3663990e62b810c59e092b571d6f4f395a9a0f7e4e8d47ea061","c56ce0e46a5d803e326e7fc53abcefa9b239f9c4c6ea2941f741dc5fa4cc7d04"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":6,"len":4,"rows":10,"Q":["26162c33203b300dd583c726ebf399e52dcde76fa1a3a34e43f021f5f28e60af","20229fb6d4b89da140f38305e34fb87a2ba32bbc874342335762b2f83ecdf66c"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":9,"u2":7,"len":4,"rows":10,"Q":["d573a92785ae468f110cdd26bbd2709f946d6f3a717a912f5dd71be72d065c53","10c3f7e767331db517141efb34b1a11e1a8890deb67f3fbaaf53f6b5114d7cd7"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":8,"len":4,"rows":8,"Q":["e2ed9e6ced87f6866b23234a03cc0639e54df7fe5c5f4d5a3b5622afac5b3103","0fd290118eba87645c1a38e94f59fca30cd5b5f76dcdab275834ce6b196b80e7"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":9,"u2":9,"len":4,"rows":8,"Q":["ab2ca2a0d282b2c9926abbe4930cdd2ff0963acb2356d0879bcd576c35c9a305","464894a31624ef1deb512284c195f4dcbea621d7fca08d593ba99d28cf8d4ccc"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":10,"len":4,"rows":9,"Q":["f708084139bf325b4ca47d097a186ba7f19f2e6e5f99efdc0f842928dbaacdf1","cca4cf7c593c8c9df4867a96c004f8d391fdd1526c336f17dfe8efd84312ae7a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":9,"u2":11,"len":4,"rows":9,"Q":["ccad4ab767d0aa5d64bb874ccf753b80677049fb1e25cc81ab212ec4f9ea6d49","6162784eaf171112b17b1aee71e0b55aed38611e3558bac6acf079eacb169861"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":12,"len":4,"rows":9,"Q":["76a890c02183e0610dec1ad0bbcec068060cc471f6e59b5715808fc12d09fab3","97ef451b4099c1d4c2230a9bd04596a945ea2b995c2ab79499f638e3d73c0735"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":9,"u2":13,"len":4,"rows":9,"Q":["53ade4793f0f29db4291501b7c47eb9cdf6e6a6fb9986a925dc479a27aaf823b","ee73702276ea78e830308740bcca4e73280535f0d07d2985fd2f1e1789dab7ea"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":14,"len":4,"rows":10,"Q":["e51ae2e8257f209a480117b80738be55d1085b86e38a1d825bbbd691e9496f66","22fc8b9c675fb6da750dd191c45c69bb9625be70f50d294ed1cdae1296fc9ae8"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":9,"u2":15,"len":4,"rows":10,"Q":["3e251f985291feecab78aed9cbcdd4f1f0dd1491bdec81ed7ccada7ce77c4f3d","41b1f403d93ef9b5dc462bd2cd1b2cf820a8fa0e445269507d8bbf47d03d875e"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":9,"u2":16,"len":5,"rows":10,"Q":["cfa0bd1568177e102160dffe800e1be4196283a8c1c6692391d8ed7eb9e110d4","959ac26b2398bdf287d75371418486b7bf0397bb30c718c591eac0629f6683c7"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":10,"u2":1,"len":4,"rows":9,"Q":["6829ad44b7b492e19978c152c79a9e3e0751e18bb3cb781c92b3d5987d9ca90d","2bf1d35ea1f9b0ace9e859060a7a47c0371ffce0f053cf99c731897a18b25e46"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":2,"len":4,"rows":8,"Q":["225ca03412b131768d3491cda884cb1551dc458c76990145c2ae7ed01d25cdb5","6c0e1d55ab558bc785f65b4e7286fc0f49752d51d2cd27f4994b4ac418d2fd31"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":10,"u2":3,"len":4,"rows":9,"Q":["adae49ca62953d9797023a5b9cf5af375340fce35fe783be8e6ad80022168e21","cfa4b4a2c8b9a814184e60f21aab4514a26fae999cd952f2f70f1b7b5b2644e8"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":4,"len":4,"rows":9,"Q":["b5878cf572516f556aa20c8ad945fc6fa3ccdfd42f7f89fae9bf99fc8b3bb207","21c5c3e7cd89af85ce9bbfeadb3500b896d0919f0ccbb41ca907fe1d1509807d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":10,"u2":5,"len":4,"rows":10,"Q":["c837180c6c9e43d13e3efebb41e0a22ad501feff07d25ead9786df9a9b6303fb","804bb3c79a0c1bd5f862f889a678f6e086758bc3375933b86cecc338817e9bab"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":6,"len":4,"rows":9,"Q":["ebf61f65282e3e224ee53b7c6bee32a26574a3cd5b5d3687c1997a92aa16fc60","3e5e8cd6c1e6e581d108fe1398abb7a70f8a6a751b0942152e81c3114c96c6f5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":10,"u2":7,"len":4,"rows":10,"Q":["670d3f4c9e2e3d4e7adc7f543ace490ceba9cc922502fac0f0c3a7f42fe4c8fb","f38d67ee5bbe8636836707736f45a6cfc0a42416cfeb4f423371359f0d0cd470"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":8,"len":4,"rows":8,"Q":["e8b24c5db579f86d5c3936b7bc458515bdc33d9eb20a519a143933d94cddb71d","73521640f21c9dd3996a0edf18af02965ca95c7845ffd51142f638527a98dacf"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":10,"u2":9,"len":4,"rows":9,"Q":["961e056bfcfe8ba6f21079d9a41cd419365ea2e23f2f5c09011b15ce013eb892","d75d5265ad242a563c25b1983025e7460d1781df5f4f382847e9e632a30902ea"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":10,"len":4,"rows":8,"Q":["81cc4712194e6ea72eae86c1f62f92c5d3a98c91c65a07ba1b27b441a610d062","aa4aa3505656b8533b4476c7bcfbe5d050c3377d5cc116f080ad77326509401b"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":10,"u2":11,"len":4,"rows":9,"Q":["f6742409b50069c409068950ce0659d1f8d92dc69d36d90b8c24374548bccd14","0bbe820c35c4fe21188baed6787d0f2f29a6fabd8a1852c1ebea4a312a723693"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":12,"len":4,"rows":9,"Q":["e327b8537ef9d07ea2cd2f6af7dac5c62f67d59c7ee5b317de30c17d61889559","5556b7e98f567d570c14c8a09b315a47f7c41f08700edd37e7a151bcb0f135d3"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":10,"u2":13,"len":4,"rows":10,"Q":["86efb905233aa33fd96cc059d51c5144a05dce31515e68b328bacdb0867a229e","0ccf74ec6eb7c5e0f04a5cb29b418f4f5098a0e84f6bc9f92a5b9ed3d39d23bb"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":14,"len":4,"rows":9,"Q":["f640bde2b35e03710feaffd101b139f7d8ef22a9dcabae392f800c3656a2d5ba","9bc65f00370f7c714c6a71e7dde1fc39d78f206de98c9ebb2b8856e4f656fbd9"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":10,"u2":15,"len":4,"rows":10,"Q":["6ffe34fc0666765ecb89923ae38fcbfbaa695c1856cfc62c7723dc68e5f457ff","b2da059fbaa062098ec1520340bceb298434b73f76c4a18183271d7259e8cffe"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":10,"u2":16,"len":5,"rows":10,"Q":["bb17e2d1fd1f931d05cf20c06446ba2670720ae049a6af845e2dc5bdf0589467","0b15f1e2ca862b4354b2a56b0665f58f27dfa1a4dc8a137a801384027d5d7f4d"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":11,"u2":1,"len":4,"rows":9,"Q":["8c46e36f32e163c8a5b9c2c6338bf7c67d88a15ad30fb7b5161172ee332f510f","c11e7a9fe037695f7ff9dc69f685fa7f7dbeac3588551f0954b0c2b46ff4ccde"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":2,"len":4,"rows":9,"Q":["523069b57ad6f5de17159a3dbea7e4370d5311c761e5e068d5874218b214c46f","ec8882ecde18e4b82f85864a0e2c00b353b0f25f5b59b8d16708430518236b77"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":11,"u2":3,"len":4,"rows":9,"Q":["d53d294ecf4dd4ded09dce55460eeeb9ec168ce11294517a36cae646933c93c0","f1cc2463b3197ee7431d2c38dfc86ad977d7c372181c765f9190615629018258"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":4,"len":4,"rows":10,"Q":["357c60dddc7cf608985052a6a61c3140e56dcab64595ec6ea18d6e984eaf231b","3ba12b8aa3060a94b2d88efd2cfbbbf79f2a7db5ccd7c7b63d081200d62d9e12"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":11,"u2":5,"len":4,"rows":10,"Q":["21137dd02c71c6561f74c7f15f5d759ea76fa9a13b553afa4b23a9e43544a3ba","499bdfcc466636120dfab29c808ba732f9dc782d4c4f4ac27e064b81efe7a407"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":6,"len":4,"rows":10,"Q":["533f2e6594e71a24b9c8428ab112de19bb35682ca59926e999c4e9eb163711b6","96f3ca3ba4c115a89edfede4e9ca0ab333b6c49da8356ed019b47f4f2aaf47b6"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":11,"u2":7,"len":4,"rows":10,"Q":["470383cf08a8f4c3e1177a891e028aa959b497ac6cacf2f2b2859027fa7768df","a5010220ea729f8bccede5579010ecd5db4a781164c606af189006a1bf5c6049"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":8,"len":4,"rows":9,"Q":["b7403a2ab7fa2a05af21fdaa0a61aa1a3fdb2e22f9b9bc7d134193c0ced7cb4d","6e58979597c8a0107636dfd1288bfa9af0d74f767f39bb391987b4c326d723c9"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":11,"u2":9,"len":4,"rows":9,"Q":["fd6957bc54c92171de6f75f3500e6afea97f6e841a69dace7d0825d7a8e02506","aa0bdfd2fe0f5edc70572a8f73616b1d29ab749d46668c754d6f205ca6a242a5"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":10,"len":4,"rows":9,"Q":["dfbdd4d410eb2ca1b6d24b27ed655fb4f25e4723c68453079a5800938f3b5f97","41573d5fd3fb25ab0a8851c26185e16dc920768e237808754940b2574ec0efd9"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":11,"u2":11,"len":4,"rows":9,"Q":["d49f4305c1d7f271b627d38f3e874a8e6e6aff2840aa3cf6e58e2adeb414ce7f","da98e250ba67a68b7e5275c92c6feef6d503e75ea81693d3f9f29c6f5209b36d"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":12,"len":4,"rows":10,"Q":["1576cc8da1e4301ee1381eace60218542b944f43eba185fb44305fbd76eb6098","e6671cabe05206068cf1e440b756b0400f563c6458ed6503b736f9988e3a9a76"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":11,"u2":13,"len":4,"rows":10,"Q":["02f0fb7bcd8b54e39f7dc9afc56a6ff008e69b90b5041cfda3bf3807d38c0db6","30e5882f0fd7fd748cc22ac70059d84c08c38cc08cdc42d66b7cd2c39b80ce57"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":14,"len":4,"rows":10,"Q":["b4c06fbbcc9131a028876a1dc88c6b7f96d23dd07c6dadd470fc174b3952c559","4644c6c1cbbc59384907e2256774384d2d1b1763d943c6cf6f4c121095ebbaf5"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":11,"u2":15,"len":4,"rows":10,"Q":["7b4740b8cac8f58e93cc2d939db1f5ddafc00c3893a02af1ee700d871aa5ffdf","cd5a6016edf73ed39b8370a6dff9e31e97e47269917e479c57a0b73a0032d1c0"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":11,"u2":16,"len":5,"rows":11,"Q":["b8152f05364638245cef786b2494dfd834c29ce1d3fb2320fd3c393dfac7af5c","27b71c1ae152f66850416ffe4ef9455a02b575c37c188482051060fdf98bf46b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":12,"u2":1,"len":4,"rows":9,"Q":["2e0de633524d2a016598a59422dd22b8757b911449c5e5d0a5b16bcdad2fd907","f0f1b1731255b38a5ac2e6118e968760779d43651e45ff001c11c68f992b8098"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":2,"len":4,"rows":9,"Q":["f6e6d465c8e5e78810f3d3dff1ac7aea7c594dd89e091f949e64b2dcea527116","04fd60a0fc5d029236215b5ed7e9a700a97bf67662a69e941dba3e8ffff01f61"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":12,"u2":3,"len":4,"rows":10,"Q":["8699f011cd733a1158e1f8740a04dda4741d3be895b8a3011571481fe47611c2","ac3f3ee843cce482b0f0b6586e8f458ede596f749c9b53aa02f21504a81b7eb2"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":4,"len":4,"rows":8,"Q":["568c2be3bd7966c21892c95985ffe0e986b4950a87404cba646d92107078c542","9bb3462b73cc614948573ebfb8f3a6c616ac820f88ef7685c94b6e8b8abb620d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,Correction"},{"pair":"G,R2","u1":12,"u2":5,"len":4,"rows":9,"Q":["e6f78d00947c4b56f662a48813362683b9cf03fa00acda5b1a7fcdd5460d8721","20af63d83371cc9bfa19bb49a295cc11c2dbf08bb7d0c32bc1d14c0b01cf3b53"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":6,"len":4,"rows":9,"Q":["a02b4638a42d9404e2152ae5c20b5350567b0fadd4e4e0fdfdf24a1a607ca971","fd2fd28b95eaf90b200fe77d98048c5bbc057b0f38dd2cea7ab9101a8fe6b8fb"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":12,"u2":7,"len":4,"rows":10,"Q":["43ab43681a0b60151d9390f61c874c5b7e423e3fa6b73373ebe886859828a5f2","679df8835f4014090e41d214ac11a37e4cad03004415c151a8256858fb462272"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":8,"len":4,"rows":8,"Q":["334b29fcc0d0fe94f614c2ab53bb7ea247fdec97d2921e603f775f0112def565","d449df6fee8e11eefe8aa95a427566df7588830c0e3551c5c76777cc4b5ea6f8"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,Correction"},{"pair":"G,R2","u1":12,"u2":9,"len":4,"rows":9,"Q":["232112410263fcef8b0ef558562279ebc6deab2d424466ea362590f5b0e5331e","6532bec1c0703f83f934d1bf3ec5fcc0e098ab4c56c7d44310f004d484ec122c"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":10,"len":4,"rows":9,"Q":["cb9f2dab1ff3a97846e072d42a8fd2e93d7944d3f672fb28da5ae3b8baac3654","0ce27f3c1814399aa6e55071db1886a30480c5375a10cc8abf3b7a08dc15e39e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":12,"u2":11,"len":4,"rows":10,"Q":["115e453530f45294873cd24945c8a425b057ca33f2914f07ea9b14279192eb01","36b4f8f2b521cb348315f35cbec2b0bce228aad6f0b659485845bac71487c219"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":12,"len":4,"rows":8,"Q":["4d2f01f800395d43ee75c8969e4b2805d28fb35077662773d630817ed6da1ec1","526a88d00c67e513575b371dce6dcbc3fa3004dff6d77969fa3467138bf8fb00"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,Correction"},{"pair":"G,R2","u1":12,"u2":13,"len":4,"rows":9,"Q":["ab438b6862ea38743ae463fcbfd74670d08175fa2a8d7c4780b130c2c2e3ede7","53a77417e0fa321a73368433cd989d57e9b6d914682884b0e0615f156c4b50ac"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":14,"len":4,"rows":9,"Q":["d3035278b03ceb58b15306b8a146d880b204413c039afe6ba9260e3be968aa16","f75ace9f2aa37a7effde21a242fa1f61a86df1cc3c7c69066762a0c9ddff95ac"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":12,"u2":15,"len":4,"rows":10,"Q":["f50bf536054200f17a5f0385687d26755bd64ae9b4976d2995fc1c6532a1e367","01c0fc6635223090b1de4d0f6688e8c89d0a8ce47c7aa1901f44faeda69e8dd3"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":12,"u2":16,"len":5,"rows":10,"Q":["023ab5ed9b0edc23133724893831c4fbfc3d7c4b78091e1ac871a0f49e7d2abf","e5b9cda2dba2083c21e0ed30dce33eb56f9df500e689537e60efbd11a90a2781"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,Correction"},{"pair":"G,R2","u1":13,"u2":1,"len":4,"rows":9,"Q":["87ce790a0bedf219c530a3d57cd429374fb14b9f479d10f85015dcdec162ddd3","e15855857199ba76cf9c2f72e2f78db700d2688f6e5c086610bff9aa957f650b"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":2,"len":4,"rows":10,"Q":["a7f8c7e4316d81db1f50e361ac5c599815d1b25f8e3a2958f4648d07754b5ee7","67ac7ed8ab41015754ae1cfce25de306033a425e74b6d0e70559fbd726b8ecd5"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":13,"u2":3,"len":4,"rows":10,"Q":["1419f1ff0113e4e5be02438473be16fdac1b5a3e35b461732a60580fc9c92a11","0310095cc03c5e0e6ba4a9bbc0df8122cc7f2cc2432d661e512bf154026c461d"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":4,"len":4,"rows":9,"Q":["ec548f76894b021995567026efbd6d30867f7d735c7504723697352ead838035","ef4494bc23863d6299d2b28d375f1020be562e421bf839be9fee446916bf747e"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":13,"u2":5,"len":4,"rows":9,"Q":["94e7cf28690c9e68fe0165326c706a9d7fb8ab409d425f1b86c54a30c091c968","bc15955b5c5e57c433a92f52f87c4e937aabe4bd78c02f5e75600daf5230b94a"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":6,"len":4,"rows":10,"Q":["2d770a01f3eb3c0fea65223b2569ce6bde8d6f46e97b0170557edcb183acae70","f4eba4d0b38d7b0e58d7aea48f3e202b6a0f86a3d5a57e57cbf2a295ca30582d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":13,"u2":7,"len":4,"rows":10,"Q":["ac780fade2e69f0df9403395006d67575ec86b676b4fafd29346f457cfe3aa18","4cbda07c14153f2f162381b55bba933db625f1bf6d810432b80cb7902b20a488"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":8,"len":4,"rows":9,"Q":["b79b4793f2b8551e810cc540d787d03400b3aa5971e13899bdb9674432959ed5","0835a950d55e667d47a0edcbf556679fc10a6e49fa6602866da774c48ee1712f"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":13,"u2":9,"len":4,"rows":9,"Q":["42edaa5804e3fbf38a0a373c9cc6fd17225bae481c4a9820a3c08d97c1c52f59","7a2f6b4e9973276be1fe22fbec4d5fd0bc7372b9c34b6718f1f346601f89e6b9"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":10,"len":4,"rows":10,"Q":["1924ef06364e7ef572dfb2aaa4cd8c9ffd0216765296cbc6b9352ba13250cfee","21681af4de589e22de8cfe29dc498ff82d2b8b8f33728af2af1f783d610913c6"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":13,"u2":11,"len":4,"rows":10,"Q":["e7d269259dc3940235b9e672190e7a8c491f3a30f3822c8cd1b9a4c1437a5556","33087376dcc5828f3478e774c990a8aa81b964d59e5b18e542cf7d4d981c64fc"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":12,"len":4,"rows":9,"Q":["07785447dcea028fb42e906173fdfe44267292b83c6ada7033458b784bffbf59","bd7ae7ae4bd57101bf9c4aa4bb52f6561196cc817ae34413026d0205895d1944"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":13,"u2":13,"len":4,"rows":9,"Q":["1c0822346477f1aa5799c305bf639c3b6276638103df40113024d802596b72c3","3ceaf7d7d502db735483213db2f694da6ad2ffc3c03a6c36cc4fd368603b2bcd"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":14,"len":4,"rows":10,"Q":["723a1d1d775bc3f3af26146aedb1289cf3c2a131f1143b9177d367f8ac9c5094","6f55fab1b05f166f3128fdefcc049dfdcca4f53931435bb3294d4200912072b5"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"G,R2","u1":13,"u2":15,"len":4,"rows":10,"Q":["8806e957ab7c813c77054c5c8ccc9c0d2bc9aa4c6b6beb08e3639c0a690092b7","e784127d7199d7b7faa6817c01a70cf0a158926312ca767d57300727d861f7e4"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"G,R2","u1":13,"u2":16,"len":5,"rows":11,"Q":["645f4c040336aa8407533343d9124d800bfb134d44ea6ced6f34e459d125f19a","b98115bda13cbd6d58f235628a92211db6476ee5aa3276f2c7c49cd9c0767ab3"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"G,R2","u1":14,"u2":1,"len":4,"rows":10,"Q":["92df15f56d7eeafdcbc762190b0bf9f9f5a3a60acde567a6cca30f82b2179540","ff725365d91aefcd4b2de4a3b65207dbbfc49f9f85d955c48c819a92f7677c49"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":2,"len":4,"rows":9,"Q":["581cbcd89b637471f799879ee0134833e6e7842965f306ec76b5e7f154c0db98","6776bec814b081d6fbd4144f8a6ecf4e9dc56de509b3ef10c657735bd66f6b02"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":14,"u2":3,"len":4,"rows":10,"Q":["56f4d087dfc2e4d7b50c8f83fe51a9c8e916b7cbfc77551e88e5392c0e4a6e0e","79c609469336e8d7c71d6a67150060b6c1243ed9235249e59f95a4933e92c264"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":4,"len":4,"rows":9,"Q":["a77ddc99362548a4ec0b14c4e517efd867c27808b5fc7e0af2f0c97b09e8f856","83e92d21568ccb828748e93aa7f76191a82e8fddf67138bc5525070fed309e8b"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":14,"u2":5,"len":4,"rows":10,"Q":["c5b510a9a11b7baeadc2117c999189669c42fd3feffd286f2426c2dee40f6080","a651aba32491b56eb176757f5274ff309b2f2fa61bc0e0af0e22c2281f38d462"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":6,"len":4,"rows":9,"Q":["fc91d585dd19d3496803a5aa78c395af53bd996c8d6b9fd9022e6b3c65a294ec","875af94d1726d348af1130b8d087afc78a4bdedf2fd5c48f74af5dc416a65f83"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":14,"u2":7,"len":4,"rows":10,"Q":["fd240dcb3167f9068bd364cf650da14542a2e73cfd3bcb1bd4cf1e0cc836e115","3d13585fce97ac26a0a278208f0fc6716458038793827bd89ad5fb6a1b03bd8b"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":8,"len":4,"rows":9,"Q":["45f13a43817635a34ca7aed625cd84a1f96c8a70b182070c60061aeb3afb6dca","455de09263d0ba5d428b431259afa87d5eeee447ce6ac12dfce8a61f0edccf62"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":14,"u2":9,"len":4,"rows":10,"Q":["06d2eb65f1213b771f348bce9126bc11c07ddb3f512c8e5279ee9936f0c576f2","067af95169004f7d1f03f398eaa37c809f49560812e29dafa8dab55fe914400d"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":10,"len":4,"rows":9,"Q":["d8ffdcabd4fe96926d9b20c7b8016cb9a22cda3adb33e16c3439e42383bf544e","0b8a8ef92a668e890f8b19da77f340b2b698eb890280c96e3f5c86ac5b74fd98"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":14,"u2":11,"len":4,"rows":10,"Q":["064f607a38f21c7cae4a3320b3d3ac28e754b7ccc58b9ee75bf67ecad9e5fa52","9da1aab1adb2455e7264fd36892c6aaf12a614353574ccf649fadebc7bb50a41"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":12,"len":4,"rows":9,"Q":["3b8cbb2b4dcce3b281a2d044cd60019625d37d4b86ae7dd5a97916aa70a4ded8","48b21bdd8c8f31df01d92a3580a07e9bafa56d1794dcbf12a46e2782bb13e809"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":14,"u2":13,"len":4,"rows":10,"Q":["0ee6f6ef76d4c94127ad15db6ba0212c3c07b81175e591ae61e00994bf3bb8d7","8d9673a173fee3fc4b2e48673a974088b7d978385892989b3fd3b6bb7b69781e"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":14,"len":4,"rows":9,"Q":["39588fdedd6c0796f0d9e32a5a0bc2e4653664a4881044f1efcf6eed56cb5620","3b6bf6f096a8b59a7da8d120292e981f4c3a10a12c4a82812fd7d7d898a05ba9"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"G,R2","u1":14,"u2":15,"len":4,"rows":10,"Q":["891407f8282ee76055fbaab38fa4f6c02974fbb4e0475dc0e75a91aaffdef88d","9caa58e3d968586ce71032da6f2e1638a1ac769fb3aef8f17a224a85b1c54be5"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"G,R2","u1":14,"u2":16,"len":5,"rows":11,"Q":["00e5af7bf7504ff8f65aed6fc1a7e9c925124e5c0241535da2fc2a518565eb20","b29a944eb2f7b644a2a2bb89440650c1bb5dbd07b912d3bbf329c2e4d1b0917f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"G,R2","u1":15,"u2":1,"len":4,"rows":10,"Q":["1d64e4ce9543388b49f7cc5c01a08a62fa3ff59bec2a6922caa064ea5b7c91bb","5ccb4370bc40d08c8b843958e163e7220749a4c4d625473dec4fd0b08ae0755a"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":2,"len":4,"rows":10,"Q":["b1c3c1204d842ab1ae933c44186386b9d9333d5a8127f8b263d62be9c0d63c3b","9583b4b99255184e3742bb62c471058f9eee9d6f6a61e97f1c25771179461ff4"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":15,"u2":3,"len":4,"rows":10,"Q":["ff6ecc8b4e4486eee79cd20075c827646184f53760fe7459c11cc5e502b52f96","b94c49eec710f6be059a32097ca95c7770742954d2e9766b4ce7721843f991ef"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":4,"len":4,"rows":10,"Q":["bdb434905097ea9933e491ea452d250e409bc8fa0b73393db8316e7289795c16","523344f16f581b6483418a8672f8beef87c6a44266241d00ff28f77e57abc2f8"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":15,"u2":5,"len":4,"rows":10,"Q":["e19024234f1425b62b0aad83c887f159b022bd5fee96160c6e50d13d20f92e83","c7ff60bf21c739bd037cf762ed9c74aa90832b26400761f37a053e13fa85311c"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":6,"len":4,"rows":10,"Q":["db419785f7de38d57e0ccc97f7d46d741d777edbcc7f1623ec78116e4a178c78","d3cd5f27e04b4e31e9db9b768dd410456c4ea617bd41a663441b39b98ea31e3e"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":15,"u2":7,"len":4,"rows":10,"Q":["ab4e5878b65668b652716ea4053b96820fc960743437575911d0d1b9b4bc4585","a0d96b4ab39f0022948ca30e299e12d697a23930733047dc3aed6e074dee23ea"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":8,"len":4,"rows":10,"Q":["af244fa1a64358853b79a8e0596252f19fabe16fcafb2e242789af2c99e097ee","7c0c7fa970c3dab010effefcad2e654fc679cf9f3e049de3ebf3ea6552bd2f00"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":15,"u2":9,"len":4,"rows":10,"Q":["b043623f6a9f1731a39a5661540e7cecf911542eef9003f293b24e6aef3336cb","947915b020d55719119fb646932d954d74a2e7486502182b3bcbc685a1902e6a"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":10,"len":4,"rows":10,"Q":["f47a3f7811f62b9d861a932f72d7f5b8b78319f64c681e77282042cd093e15c0","37f5776930adb9c02322588068c71a662cf23b1e10723d66361535ef5c2bb755"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":15,"u2":11,"len":4,"rows":10,"Q":["9874ed69f606169de64b8ce40a14154f4352cda27c8e80d063301dae207629bb","f1a9d13a12c2cd73dbf8e73c58d4e9106998a3ee2f1fd6ad3ff246ed2cfc1c58"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":12,"len":4,"rows":10,"Q":["15c5d26d75103b18b80afcc0c71c49f3f9cb22bc8e344ca83385fe4e9ff66d38","6db615ac0b9523c615852f871475296af0efa6ec7dd6f2a6be0b86e822df9760"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":15,"u2":13,"len":4,"rows":10,"Q":["485107e2b010d687970b451ec35e3c3f85b47012fdaa8ae473653b24900fe080","58b20cf829c099d67cb16b5d6aa5a9b681c626c62a5d28668519ac19cb5cc4b5"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":14,"len":4,"rows":10,"Q":["76050d82e292502c5b91f57b70a362c04045228d5063ae1472f32c53d4421f8c","684a597067dba2111a2b6196e051f43a0d505b2beddeb0befb7a57b65fb18900"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"G,R2","u1":15,"u2":15,"len":4,"rows":10,"Q":["414ace4c976b796b9767904836535db706a771e6c9eb88fec0adbe4295b41c41","ff4c201512c144d40106ecf963d6edf5a656286d59822f3693c7f39254190465"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"G,R2","u1":15,"u2":16,"len":5,"rows":12,"Q":["a21fcfaf15a524d74e4c5908e4f27fe00fb9f2b64dfd4a298661abe06293e27f","41d7419f88b752f75b1effa8a0c6ca959f9a6f2df7ca0a94b4cc6cda2fa17f50"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"G,R2","u1":16,"u2":1,"len":5,"rows":9,"Q":["6cc753fa48ee1947b3a9752801c8eeeeeddb9a1d4e200c57d96873f1b7acabb3","c031aae6e12e389133dbee6130e290468b9a8f1887c788d3cbe56152ca90006e"],"shape":"Precompute,Double,AddP1,Double,Double,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":2,"len":5,"rows":9,"Q":["45cff9156f74b2f4426c6f047a73413656198a11ab597e3e4f9345e64ee8cc66","c209cc0186b64932b80a0fbb6f057f9c16f3b67fec9e31c62230c332645b80c4"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":16,"u2":3,"len":5,"rows":10,"Q":["ff784b0b6d3ac2a6b0d8f54019fc275bb845ca2ba4f6fc76c461961b239b97c9","9b28e8148a44d7c908eb5866e0c152f038c114a49d7b8ee92cf1f83e166bdb2a"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":4,"len":5,"rows":9,"Q":["2ef9cf218a2e5a9d1eef02d6d951a4081cebf857b0808a30cb75a54e8a30581b","05ddba59cae8fd646ac95947d85e4637ce8f8b8178c37330b5f89ec6ce55c5a6"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,Correction"},{"pair":"G,R2","u1":16,"u2":5,"len":5,"rows":10,"Q":["fb1f06a687f0dc1ae5a0e62e7620fb88c6812b2d31ec7e4681f21012f13edc26","b9a48e627bb594a16b17d4c0b0c87124fc684e703724241c10de784fe7736f89"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":6,"len":5,"rows":10,"Q":["b226457a7256f6af9dc66cb1731fe24d9128bd8007509cb842000bf28bfac44a","b7c3071c392dc668f80a459d9d07343cf81e5a18e98d10e0024aff41999b024d"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":16,"u2":7,"len":5,"rows":11,"Q":["1f4ee648c8539a28723ae65526eea3b4d17385e2d8a00937239a2d6453b48b92","52d0e3083a4999a49b0ea4f0dfefa37a5c5df0b40e6a3baa08991f3f5c2b8663"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":8,"len":5,"rows":9,"Q":["642971cbf1e50211bdd23d3bfe2ff7fe4bdca8ef1f327cd4cd4049e127702c8a","9d9f70464b3125dbb74fcd0a95a762aa22d097c370a3aea69213ad49fdd8d1ef"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,Correction"},{"pair":"G,R2","u1":16,"u2":9,"len":5,"rows":10,"Q":["27ed82ecfa2769886e04c8d706902a9b18a5d1fd4c523ce2d5692ba80f605240","4f2306a1f7ebf644a1cd2551934496b79b415ab2fab968ac498a6454f8a23af3"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":10,"len":5,"rows":10,"Q":["505d4d0d288b3d4758754e98d174e553db4e36bef9f9eef3ec9f0d7d38dbf58a","9ef0ebf450fa50d8930113092f4e0cf795d9b882851b55434b8d0a88a8357fe5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":16,"u2":11,"len":5,"rows":11,"Q":["1d9714707dd13ff69183ec45f6cd37984e957751c95dd5b579a52c91838909dd","ff806226afb308fd4cc61fb19a3ddbeeb0068e6c85522a6c496a8dbcfc562deb"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":12,"len":5,"rows":10,"Q":["a95122e31d5e2c21c11fb50b655b081df908620f9e25acc5216a36f93219d09a","ea16c1c9dcad892f7aea1504e03ad7034016a978f53b0f10cf8bac0578a5c801"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,Correction"},{"pair":"G,R2","u1":16,"u2":13,"len":5,"rows":11,"Q":["f993fd0aa5794e09a23b2c7a6b3b089fa3931c8f1d4e0555ba85a81bd5025070","306454e6c8d95b59e776a1b279cacdf8fa0530762f6ae8b43efd760cf8e8edf8"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":14,"len":5,"rows":11,"Q":["696e822bc36d968804e9abb19d2e0beb4d81e228916832bdf61ca9043454af78","0cff41b3b748faf3e8a7e182fb6cb1277cdd8c8cfeb373070a998fac4cfba44e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"G,R2","u1":16,"u2":15,"len":5,"rows":12,"Q":["c6351a7159bc0e71053f52bb431819dcd9096de33918e0a9cc2b94ba2d4977b7","e59b2c9d52b9b2b7a703e2a36810f343e9f678d13413a4883b90ba2193504d65"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"G,R2","u1":16,"u2":16,"len":5,"rows":8,"Q":["7558720bb526c78d131a3ac0382bc35568823741ba80dcdfda88b429ca804a31","551452017becac334093bef5d930531abe26fc238cfc5b0ae7adbaa3f6e2a689"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Double,Correction"},{"pair":"R0,R0'","u1":1,"u2":1,"len":1,"rows":4,"Q":["68588a16f999d9eb34afa6362ef3f929e8c9f7e4a3bed1519110811a75a7ac21","d1c19d5331830f472a2bccfc01e99265d2fae0a132101d1fdaca94dfd8f720ae"],"shape":"Precompute,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":2,"len":2,"rows":6,"Q":["620cbcbae341bc37a03d77299affc9f7537203a3455a83179fae4484eba49118","2b719fcd782589ae1d5ff09458214dfacf5e03f73d70c4b967eab036e8bb1959"],"shape":"Precompute,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":1,"u2":3,"len":2,"rows":6,"Q":["9a8eb6c99893019994c2ba00ba4f83996679695da6ec3daae071c3ac43891b49","ea4514b78f0f093076c5405c245d179d99fc2f69718096d1f485360cb3e0225f"],"shape":"Precompute,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":4,"len":3,"rows":7,"Q":["529ff513a9a438ad8456d5ac49a6efba1aef8602cd69756e13a1471a7d4bb073","95f0673c58c92279c324b2645cef58091bc89865aee20b7dc2dab6bab97834a8"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":1,"u2":5,"len":3,"rows":7,"Q":["c157dfa8233209a92d006aa5ddee348d20f7800a7a9e49835d342147833ccf27","186b8c003ad2e81955eb7ab44a11e3ad93ae730f44770c5b94074c6ec5e66df2"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":6,"len":3,"rows":8,"Q":["931caee7e660da3a24600336ae5842f94baffa332d4c34e8745bda537b2080e2","7ffe04e3fe849df871ea2a10fc64f54c125e6cc4a34b4e08f799440471af78d7"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":1,"u2":7,"len":3,"rows":8,"Q":["acba716dc5c739674c02cd65e2ac2492f34eb52784b6f4f73e1b599b202f1c6e","2da3c379e788c0094082d0f28ff064d4b52dcde9280d26a79700b650664b95b4"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":8,"len":4,"rows":8,"Q":["92a183d09acd1996da5344c02703b69397a3a081768094415ebb20460234cbeb","2166e09026ab8b5fb85704bd8455733986c4a7b6b24045161aaa44eac27f31d0"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":1,"u2":9,"len":4,"rows":8,"Q":["c711f52d558cc7b25f5a068d61c0306ea83644ff2acfa5d54ef5edd5a59c91fb","ab76155bb3b9f0508b1c18f767ee2417668d729ae288f47737cb03e71eae8dc8"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":10,"len":4,"rows":9,"Q":["591eed9311d221af27111dc8f4e987d175e89d006df787caa7df0cc5a3d11bc0","b74f7271c7fd8c778a9896af26700d5676295d2d609b80d14f09071d650cbfe0"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":1,"u2":11,"len":4,"rows":9,"Q":["e3d6565f277cc015c69add629a3473700aac441fdf509320c92ed0894608ca06","9e3c5a50172137b24515ddcf0a9100ef7a7eb67bf284fe0a584e26120a9870b3"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":12,"len":4,"rows":9,"Q":["9db4089d6aa4b2a1a8ca37a2d49d6bd22c3c7b05b76e0445a50e38e03b60eb0f","72dedf916eab1bfae397e957419be5baa266af0bf3e3a6aff5435d177b76d8c5"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":1,"u2":13,"len":4,"rows":9,"Q":["b08446b47bf482726734d6b01a36dc18c09579435b4670cefbb16e69513816ce","8123c5a3fac5481096702d719c4e779bdb83566e50696d8865e5e8a957902e1e"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":14,"len":4,"rows":10,"Q":["df77de0f6cee6e760bdda2559fbfa3e3fe643008754973fc084049dff2d074e3","d44c7ac9e1b4050c46749d7fb7333710b9ce0727166188ceba21c79f3ec208f3"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":1,"u2":15,"len":4,"rows":10,"Q":["6410fc82cd75f602054e50af4df8e157d774d6a6c900cd0d04c8d22b75914dcf","b667836b49277e6a5801cde64f72825d1368ead01f416d918d3b353d3ceeddce"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":1,"u2":16,"len":5,"rows":9,"Q":["726359298ea92a193fa38638091d12aef7d05af7264b3e87e6c9f5b381a6ab36","1baf32dbd6c5ccbf8cf91615373018669606d70ccd1569e43eb3de62b2a66128"],"shape":"Precompute,Double,AddP2,Double,Double,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":2,"u2":1,"len":2,"rows":6,"Q":["648681f298ea1b68c688a6a295f6fac5d118f3ea809a181c25bcae85b69ba71e","178fa61721cd02c8d5222e305e0f1b23b0e1052f12bdbcfa2d5a55fbf56680ba"],"shape":"Precompute,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":2,"len":2,"rows":5,"Q":["bb54adf129d18495e09db8085845404c901e3986ff4f8b23a519402be93fd17b","e9f3225c863f9c3f1eb63c80389c5694d7497d744f2adc0d1b481cc3bc0d3d78"],"shape":"Precompute,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":2,"u2":3,"len":2,"rows":6,"Q":["42bc4a5e40d76696c40fb35b1ff62c5e022e04559463ddf8d15e14948666fc6f","a95725d7264734efdbb2c71fb2bed2d9e9d3db37349a7c769e06165151a8a846"],"shape":"Precompute,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":4,"len":3,"rows":7,"Q":["2413a841778cdd3eace247c33d1d921790535dc428f8ecb866f9f2f99f47b5d9","53ab71fbe5258724f1bfffaef32772008729ded28d29346b7c1c2f5eadd9689c"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":2,"u2":5,"len":3,"rows":8,"Q":["1dc45c787b2188bcf36af7e33c9173933026ffae986a012b117d6da690276193","c9cd98824c010709f7b11265c2767c743dd34fb963ee1d0ab5aeacaecac8ad88"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":6,"len":3,"rows":7,"Q":["c91b5bfe60b6560a2543e1a3235a876a57a7ee65d4e6ad73d05ea63a7f56e65c","f49fb46a658e62ec5cf23a8af6c7b1bc874c45d8e11258fd96409f9d38f4123f"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":2,"u2":7,"len":3,"rows":8,"Q":["d81b407a086882c2d9608724764c857e72ac3458248c768d15ca20f9d8d3a96d","4c8d824ff413a3e23d2a6d58b760b0a6889a0dddabf55e236ff50b289a4db9c0"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":8,"len":4,"rows":8,"Q":["6572f494c6fdd57a6f2db22af9a2e1a28c6417750cec86a304a5993f51f6a39c","2bb0f0096ef469de51b3cb00034f898169be384821c499bf2a89fba78b1c3cf1"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":2,"u2":9,"len":4,"rows":9,"Q":["1e0dbd714c40690df13d2c2e51e740ea0cf6ba45aa8fe2633345303798e60f8d","585e8eec16243525b7942e63c646c5a06edda74aa17af086b6c9a1b96ae0d174"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":10,"len":4,"rows":8,"Q":["efbfc6685e17b1cfafe2b00ae13409601b1bed9696b4b99eeda21cf42e5e3d96","e2ddb2b776fc064231cb983a5b212faf398b5ace76573365f6ed1e25941b7450"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":2,"u2":11,"len":4,"rows":9,"Q":["a9519561afccb368d766c901fe74bacaf29634ddd0442984fd7cc842c000d290","58f5191067ce5b5d746d85a7c142314eb58b5a45c3173fb801f8f22d5adbb63e"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":12,"len":4,"rows":9,"Q":["fe43300adb82039f305f09def70434d7b8a34d6186c7614d72bf1aedeb038a84","9e420b5b14ee98d90ab7788325534b30c417b9cc89ffa23c968be80edcef6a10"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":2,"u2":13,"len":4,"rows":10,"Q":["a92777f5ee6525eabd3e27067b950dbe8a80f273268c55b79c799b4997e1a550","9123d6af55a59b462d1c6b8451a350a2d044956f56273fc8dfc67604acfb3da6"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":14,"len":4,"rows":9,"Q":["fa8066e7821df797364814f751d97275cb858f0ffe38dc484e5048469c81049b","5061549ac7c0b23e762a6dc23457ec287e8de2d46aae2f6800f7086fcca22a2a"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":2,"u2":15,"len":4,"rows":10,"Q":["8174b7d9192bb66029b78b97e732df8c32f450899b5f194a2a0a898f7e787614","82b336210e138d37a50e405e209e6064aa58bfb18f216377064d194d564a9cc3"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":2,"u2":16,"len":5,"rows":9,"Q":["ab61e8e969fab2d2e967668d5d4efa544475308cf4869268ebe750bf9729abc7","851139d946c5c7025cf1487ffe886c5400295d04fee695b3fb5724e87621d091"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":3,"u2":1,"len":2,"rows":6,"Q":["ae95a9bcdd2e8c48d37c3d18573467315fdd9c9c47eca486c63a3b54e3794ae9","07e5f180799b9eb828ead3ab91f5d87f54f1afe450efc1a1303f438ad92fd61d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":2,"len":2,"rows":6,"Q":["e12f1a3be4c694959a44dde1917227b46456462fbdd366c541269d80facee5dc","c13792bbaeceb7084150b00bf3cb0548fcd778d5e9edc3ffc27bbe7432ed2eca"],"shape":"Precompute,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":3,"u2":3,"len":2,"rows":6,"Q":["9701982092b81326c79723e7aed369e66321db50b338d77deb4118b5d7ecf2c3","43d0b0f4434ca895ee04311fbc8c7e260df6ebc04fe37e8031fa229b523a290a"],"shape":"Precompute,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":4,"len":3,"rows":8,"Q":["8efb4d1b56776f05518fc95d3b0477b6ce9e3b4aaf261082989e335e3902d589","e0a08ab6288c5ebf761a3a43cd37911ab4f816bfc5813db11906ab95f366acd8"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":3,"u2":5,"len":3,"rows":8,"Q":["df719147c5e6a94c095868e994a8d9a95f540d244125a15f8599afcf8b4040dd","21fea1c1e2714ef791cc9ac85eb1005d450323a7e4b2a43fd176497f921f4111"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":6,"len":3,"rows":8,"Q":["5d7efa9721d62c7bca9ea291bc22f77ce9e37827f21e33b3f4dc9e158015905e","15d3270e7561556e12038f82c7db0fcc544cb0efddf3d0c42b21652c5ece6398"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":3,"u2":7,"len":3,"rows":8,"Q":["553411fa197bd43b0c8344b063d051c650b12b87d0e0c003bb795b801483896f","989fdbb24ef83619bd99f93d68558b3c7c8bd05f605281e10c3a2ac243928f49"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":8,"len":4,"rows":9,"Q":["33b597c7ad0b968d0ad63472f6eb9d46b83312a9e3d3c4919b64b564b8909206","b50c20e8eabfed697c43f9bd4b355cd9e982aea76c6106fd30ad9a6b7c6dd53d"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":3,"u2":9,"len":4,"rows":9,"Q":["dc300b6c74df8e32c7a3d94481a593e3327c973ef7cb8480a64e7c236bc3e5e2","7c593970f8839be909fe7c9d5bdc274b197bdda5befe9f3be6d7fc1e8e92b5e2"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":10,"len":4,"rows":9,"Q":["1cf2243691411b12620ed69e18e458abc62b9f7b0a712ac4818ac5e75589053d","309f1439e921aa9b64818bf138014387ee1efd2d86d21ed0ae06c4b8ef8fe5f9"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":3,"u2":11,"len":4,"rows":9,"Q":["10cd2f3101030973ce80164f285ecad6c32f97f28444a3691f9c72fc7d540bca","38a024e7c8ac692383fbc1c4800855c895985e1895cc8a1605cd98be01b5538b"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":12,"len":4,"rows":10,"Q":["194f9005df2ac32c13bd86c17aa2ea1a14929170ada027864fce28b31e992439","85c2a093badcd2e93111edb98fcc48cc6b85529223dbf4dac314ab449a5948cc"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":3,"u2":13,"len":4,"rows":10,"Q":["8865d88c9dada3d069173e02bee2351123bafa877b289076d91ce63b85f41513","6177730c34a919875bb61e784c5561378698edd1e7bb8d147d217c32117d4627"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":14,"len":4,"rows":10,"Q":["485bc52e82ae61b783887d7f71751894e61883e450ddd4bdeed68e52ea0e5dda","092d37904ef4afcd53060f45cc2ba4ff933dbb70dbdb82e02149d11b8c89c562"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":3,"u2":15,"len":4,"rows":10,"Q":["f9721e357a0155f3ff4acb107bdc3f8a459d6d07a9f62d0dfc6a019eb61463a7","6b77bc87380034066960890d55f090b80a022693ae8c0a40d63d326d54674958"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":3,"u2":16,"len":5,"rows":10,"Q":["3f4cf74a5db00952f520537d2a8ed9d97f7a1c7cdfe160ebfe1d20495931eade","b230327127544b91d7ae28279179468c7653f6d113a02e3f5ef778b5d91d4259"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":4,"u2":1,"len":3,"rows":7,"Q":["954026f74203c97b480a50b91b2486d413b94a3acaadbce7982e45fa266eae62","5061d6db13b5263697692d28a4ac21550bdee8aa22ed68fff026293fe51dbbb9"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":2,"len":3,"rows":7,"Q":["d120655329d87fd919e29ff73e031585033707a296749b5c307811c74587c87f","311b94ba8e18b3e983b33d873aff78e8904fef3ecc470972a0d937d876d24356"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":4,"u2":3,"len":3,"rows":8,"Q":["92502c8b3f8c5e0a40c00a622c93f81c6f499d456f1bf6ab2466fd7e5d0172a6","680ea1f0ca5179c8059fe305c4115e516851a4fbfcf69040da555a040cfc426d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":4,"len":3,"rows":6,"Q":["4764632f66c9ab19518fe24d37fd28d07e6057b03dac41d19fb192a58c825bfb","6946e0bf04432c86552b29bacbf4bd3405280ad8aab14612d8a602f680bae830"],"shape":"Precompute,Double,AddP12,Double,Double,Correction"},{"pair":"R0,R0'","u1":4,"u2":5,"len":3,"rows":7,"Q":["950ea3eb075159def08dd6bbf0079df7b68a0e44776eb5c4cf654de057074b5c","14d713d9cf05383e107d5cf3982e7ff0291a84e703bfa009853a50bef66e8678"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":6,"len":3,"rows":7,"Q":["1f81d6d98ef7a9de9842749f3a46b68937c7966db2e2e744991442e465175b08","d688028b6afb9fbe06f20341b969f54efd2a60e27e37a9739d3b136e0728cdf0"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":4,"u2":7,"len":3,"rows":8,"Q":["bb3853b9f076bca01a740f388cb30a794597e0fd31aebe6cfae1807aeed3a878","aaa0387e38523b94d2635751013675e5079c67e4e703eb7f1c8e9490036ff270"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":8,"len":4,"rows":8,"Q":["2726b6a1c7ce44b9ab423fcaad8a5b9592341f11fe07619494a2e26ab91b6a96","cb001fc07a0e734fddeb72363a777a9e4d2eea6cf3e6ed3b2606e59270e29ceb"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Correction"},{"pair":"R0,R0'","u1":4,"u2":9,"len":4,"rows":9,"Q":["f6dab56d2e5e0950aba2ebcc82cd424b6698c66612ce30640f4a482126cd32da","0ed85b88c113f9b3deb8964a2e8620754735a8065f5116f36dc82bfd6315db46"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":10,"len":4,"rows":9,"Q":["f4bd003298ab933cb49e00024f7b51931248abd068e63b48ef41c1f4940db662","38c5caba1e51edf2fd07f7df668e9d80da916f240547ee677d45e6a5b198465e"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":4,"u2":11,"len":4,"rows":10,"Q":["f3c611bb58c2a12614611f038d339e1df35cc5abdaa5ed8d23767f8d3306117b","3b2e27df32e6f331acc27a03ed205a6370ce75ef367714475ea0b6a7f0e6c8a4"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":12,"len":4,"rows":8,"Q":["ae42a8643f4f340fdafe411302c01480f2c618966d38a95f3db6a5d0aa303b70","e0c1c2bca35778c9fc6fe31f38661861805063b70d4a1e807571b0e8b5a9767a"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,Correction"},{"pair":"R0,R0'","u1":4,"u2":13,"len":4,"rows":9,"Q":["7457bd63a012b4dcd97c447cf0dcdc7e86969db60f97839699ecba6797ae8350","e85f02d2bc47e09735d9c23e0409bda071b727e3bc31208f10e211ec41f3e8f5"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":14,"len":4,"rows":9,"Q":["5793ef15e5a0c4571b676ed237c76759483679f3821216e44aace76d12d60633","e73c028148befbfc43526971cf1ed50ed6c73fbba9d03b7187f3877bd1e34d49"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":4,"u2":15,"len":4,"rows":10,"Q":["5c43e6a811422748be23dd6261cdcf549da3f572e6cc4982a62711e8b9614119","11c04d69cc0edc5c5d534d70f7adb657443b238b9e398b85f33e6a5c9b3a2b3f"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":4,"u2":16,"len":5,"rows":9,"Q":["083360427ab231e71fcdb0b0295f7b792cb530e1a3ac1b1fd859176327fa8b56","aff6f284c8cbe9d74783c3548aa9906ae6146c11172b061d7db67d029a1661ee"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,Correction"},{"pair":"R0,R0'","u1":5,"u2":1,"len":3,"rows":7,"Q":["9d24511eceff70e6eee1356f79df1b9501e1956fbe45d8d56da20db9fc312536","9a311ca847c4efcd95c4a0c279af69257843f2fd75b8b9b35a7e3ecb95e794ee"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":2,"len":3,"rows":8,"Q":["8e83f0bd28ce0c079336b0f9563f13d5ab6d23084948f0a96ca8b3b6d29665f0","4cd39911154a95bf7785d269ee6ff8a7fda84e4f1429444a60d8800c32b2ea06"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":5,"u2":3,"len":3,"rows":8,"Q":["373e1c6b1d5acc6cd467b5d864a3b7fd547bc59bcb7c9f6516aa69741f24b6f4","ebb8caee7544ebc7e4da888d395cc6845d5e700ff95c2048e9bc3406a6edb63f"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":4,"len":3,"rows":7,"Q":["4b99cfec9d81824b1bc3227132b7587f110146018f10fc0dc927026c5ca8b431","834a0a1e012a2740335a85e69d3ec8838cf193f7c0bd3929420b5d32f421d5e9"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":5,"u2":5,"len":3,"rows":7,"Q":["e8c6952923656d4cd2a865c456c46745c06575a82bfe8d519666413c2381629f","60677e0a77b67df4b5578f4411eb3ea099833029f2f1721bc32d39ed4b143c7d"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":6,"len":3,"rows":8,"Q":["74a9e4750f92faed24ecc14201fe6f46f87d6b74c989f5a23d51c0d9a285175b","9b43d7608c1882b11b381267f712d90a1be7b118a37ff7c7127306c93f8cecc5"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":5,"u2":7,"len":3,"rows":8,"Q":["53273fb0c15938e8e03f614da4b0b729048be586ca4d0bff4b9d500acb40a18c","5bf76e644a7ee4635a0b2a60b44b7c7c85af9e0a78588b01c01f23e43c1cb1a0"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":8,"len":4,"rows":9,"Q":["c51704628ec7924deb08c34bfcd8a3e382011bfb630a4e4bb498dc56867e17ba","b97d4306f99dff24c9b4ce816ce17004f2f71424e8e7dfd01ad5735ee7f5daf3"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":5,"u2":9,"len":4,"rows":9,"Q":["972c005d88a493b3f50ef4261731450b8e98d2ecc6fb1dfffad49dc75d067fbb","2da0e5aaf8d7446c8a5ffbf783272d896ced58f35e4fe086c5be734db45477b7"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":10,"len":4,"rows":10,"Q":["a4f8b8a30d034a751f28f51dbdfdeb78b028fe3f4eedbb1368d9dc550a7ed233","f1889ea5b93787d9a8f83bc6d3743643719a7b666f5b76160b49a8a6aab9617f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":5,"u2":11,"len":4,"rows":10,"Q":["3bf299035857ac06a37a2aff9750012023f292c6251cf090ec97a2490a158be7","2d9fb636c896387893f931551a9c683fe117f00583902a3243ad38ae5df7c8d4"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":12,"len":4,"rows":9,"Q":["b0621820582d2ea7c3176fc067361f9db5deb7964b38516b15ce7962b5e6352f","cf767d9fecc5de64754a69e0c5153ee2e4c78063b57d999f156854e28b9c0700"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":5,"u2":13,"len":4,"rows":9,"Q":["12dc9a40e9af75eb308c0880cf6ab429787c477fe86807a46021e12036aaa8c2","78b611e8017cb5e58ff42315846b5ae17ae4896bb13c7570a4b1e0f0e06290fd"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":14,"len":4,"rows":10,"Q":["e83907e8cc71f1a3481502799c8b9dc766667b35c6f3c426de3a4a6de6a02c11","9c183a922b9c30c24baf629a33feb4061e377fc3d2d7ffce45fd7edde616217d"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":5,"u2":15,"len":4,"rows":10,"Q":["2e992fa572fdaac56c01edf4ac458cf96e54e1a30c5285dc83dc00935ddf06d8","8280fbb566ae24549c4382f376f7767444a16f6756d4b6cdfebb88ba071fa852"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":5,"u2":16,"len":5,"rows":10,"Q":["6a28f208bc6488fd2c6775ca68772cc2408fb42aad897f67d7cf4dcd906dba39","f24efe2a393c0cbe267c525ce3a7a2c5dc77fa98b3910e020d61d5ea0e887859"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":6,"u2":1,"len":3,"rows":8,"Q":["40ee75b528ca477335f9d5853afc2a9bff9f73b7c1ff726ff431ac253c8c9baa","01eb070f7f9a60ed6ef9c85e3177c16e4d62a6cf46839fbbaaa7f154a7fad691"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":2,"len":3,"rows":7,"Q":["07650653876c83952f33dcb806cf4b331603e13bcb329541414ddee1a37963aa","405985a97161dcaab3cd3b32f8301b234182c83cbf0eaf062cfb3f5edaac44e7"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":6,"u2":3,"len":3,"rows":8,"Q":["323a68a41d94b32852f4a5138bb18534f2bde08f1613519113fceb2cc1c324a8","16c55ada3d58f76344fe1225a895a02842144bef3ddac4275cba89136ec08716"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":4,"len":3,"rows":7,"Q":["2212dff88e9549d8c9ebe5c82d34a7675ba18b6fd05212dd17d03e63d2fd7321","473861fac331dabcf602fd9955ed50677584b1b186690d9da26aead0431e86b5"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":6,"u2":5,"len":3,"rows":8,"Q":["944f8edc4f9a86562eefad4c6ae1ce849aab70393a79d7405455bb8ce5c05ffe","91704639dd0193561d07fd48e22de38ba2fbcf63f1399251ff79af4818a03777"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":6,"len":3,"rows":7,"Q":["bf348f34cfb260fc4b88ce8d5d5b9fca1af6f1e823a88a6120710869b886f682","452bc969d93b2fbf0fe24831c76ffbe72bb15062180cf24394380672d6fc2716"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":6,"u2":7,"len":3,"rows":8,"Q":["330332723aac40df3ea06c3b32c810fb65428af58cf06d05ae07a7ae743a454e","091bd9fbda4469482bd7f3a14924f8712047d3fd686d6da9675b2baa1cfbad88"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":8,"len":4,"rows":9,"Q":["b6ee06f223b57be132dfe47be54d5987a57cba531527d598b68e325bbad6563b","6acaef5d3e1eba58293f38da91fe165d4a9c5421e7a0ff80bfdb1ba17e2421e2"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":6,"u2":9,"len":4,"rows":10,"Q":["f14af36fdf2279049f5226094a95d02a3c31518d98387f0ce2ce31c86dfec801","b16826241ae7f37ba9a3d0b8d7a766772d40ae52207f742dd0f88ec3b92b2d94"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":10,"len":4,"rows":9,"Q":["151ad7b4bc30e3afe0261389954d00ae40a1494ec440677dd1114019e2743943","cf32de558a1ded397103061d856e7c2416d8fec1c5a78456f40fbe51bd64e70d"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":6,"u2":11,"len":4,"rows":10,"Q":["d1748c98248047a5521520c3a0542248569c1d5a813a3513b8e2bf7787c78cac","3ed9891768cb37e0953d09cbceb2a73a2bb27f61fc8678e1b1f8975adbb197af"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":12,"len":4,"rows":9,"Q":["881dfeb0cd422fee20466166c038c586bd49b1782ad7f20f6a83660a4a6a5ea5","92cefde4c94251d59fda2ab357bc945614b3e25118409b595eb214e04e39916b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":6,"u2":13,"len":4,"rows":10,"Q":["10f2bcd716bdec5db578cf63dc8854b9da081ab1270acef55186edb89e5d9241","59d9340287aa270434610089da9a391b3e975fdfc1feb19ee316f63a978cb08e"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":14,"len":4,"rows":9,"Q":["eb5183f680462592c54fa2995b5406bffadb4a3e4215b9312d9b9333d48b71e0","498224ff765e5e8bc0d65dfac20c05edbcb4a16b925749c8d6c52594ffeb734e"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":6,"u2":15,"len":4,"rows":10,"Q":["0c21dafc83f46e44179892e7b5555424d20518ab8bb201385ff27cd1e99a6da2","e097d0bd952405d186b1486da83bca2bcf7003de307fe25b047dd7b0dd1d43af"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":6,"u2":16,"len":5,"rows":10,"Q":["bbf5f9a94bf9a57e068fa3fcc669400d6029a12ea9ab7e1451a91e6d7ce0729a","a7dbbfc668f414116e8391b1523d5d4ef07715b6a4a6a7cbc64e452e196b652c"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":7,"u2":1,"len":3,"rows":8,"Q":["dd10ab1b56bc75f0092e8f8fbee78f0b29d83da927232217cd93b7c25d72e66e","3a6393e89e9308a72cf417fb24516e82cb186158ababa84d0ea77e67de904153"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":2,"len":3,"rows":8,"Q":["83a7aabf11d85563a629c9bf91a2fdab2df5e617771b277c97da15b75b0e40cb","6222b5cb634e6b72b7797ceb43fc33ff29cb5e654dc0f478b2d0f5b99df117ef"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":7,"u2":3,"len":3,"rows":8,"Q":["63fe83f3860c3cb18c830d9da48e6be9d09d94f71ba572f7378b165d9fac86b4","47edd7468831ccac8c53a4b6141e4c1d097e0a086e759985ec402ba4907b6c2d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":4,"len":3,"rows":8,"Q":["50708f7f11ef7c13109047db0c145fac31200e0b4ba546159d1b3e11fbb28929","6fd0ca616e8f9a9d8cbdb450acb3d48708f8791bf9bbd18b18247559f54aa2bd"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":7,"u2":5,"len":3,"rows":8,"Q":["bc0df7cdebc3fb96bcfe76659d3091223fb36a9c77abf01f328481a6804dcc3e","d573abe7f8b667ebdb7d1aba56d6e7b2b6e494ec31b2834dab7ef562e4f8eeb5"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":6,"len":3,"rows":8,"Q":["d6454d536a09847d97176bd5bebab6db52fc05cdfc4d25c1ffe7eb221c8ca5ae","80dcf7d11a6cfad6063f89a7fb71e10768219cbfd8df8cea5727ee624038fc72"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":7,"u2":7,"len":3,"rows":8,"Q":["393007535cf782040c01c51e367d5ab32cad21430877aaeac4d00fb749e3bcbd","e84eba8f879ab6de87f81cffddf17223d80b0f9fa4dbc5697efbf3dd249034de"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":8,"len":4,"rows":10,"Q":["65ae7aa6aba3efca91d2f6a3e17a262a4571583f7117d332ea1086d30d386bd7","716c924f82cf3f8954259a4fcf0b56422eb1e2250fcf5b2389855011607e5ecb"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":7,"u2":9,"len":4,"rows":10,"Q":["93000fdf2e7cd571560f204715b4e5a29abfa2d938f510466dbb1207e527bcef","d5ce3b3e826d837cc9cb2b52fe6db59a5e0702c5f5668c0b7c3a6edc4881a508"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":10,"len":4,"rows":10,"Q":["c09ad8e3de3cac29c50302c97d3f984f07e2fdcdc3c2294c664058b96834b179","c2c65dd3394644d72efc852125b9b0e959f013f341119b08755d06f706189968"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":7,"u2":11,"len":4,"rows":10,"Q":["2643ffc101c12870df09684b2e5ff9e4fc22becb86f929f272d150af47187b22","aa51a4efd00514537b67a46b6f58c8a96862eadfa82951d11c40ae5b28b48266"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":12,"len":4,"rows":10,"Q":["fa9e3309546572825052bf81b1a178381b9f2953d50796cd39088595332ea356","44d66c9a96e1b0a829046cb9e836a732422abd18dee768e0f188023b8d3b9c79"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":7,"u2":13,"len":4,"rows":10,"Q":["3818fc73b84212bdf12709730028030a801da51cf15988d2fbefa9852e1450cf","f811bfe270e00215daff142750301c9d0d4e51405112b550a46ec3dc685c9bb4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":14,"len":4,"rows":10,"Q":["950823554a908d647e04a1d0a130a3e80c11c459d6968f98357bb4c12c303877","69ec9dea555864057b1170970f3ca51ffc5884100337b22bca1bf79ea29ddccf"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":7,"u2":15,"len":4,"rows":10,"Q":["64fc177298dfa3c3215833f16c837ae46209787bd0b3e40b017414ee298acaf3","1a4a65fe601b5ad71e6390a0da5ae30b2bf4f89e1333ccff48a0d6e5e20e2fe4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":7,"u2":16,"len":5,"rows":11,"Q":["f1a3c000b72c839c1f1fe70f1c4ba1cf849338123a2502ef238cd3bb09a63c4e","3ed27cb7de2047d0d65af843c0b903516d30cc38f1d195cfac1599ba7b1b3c23"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":8,"u2":1,"len":4,"rows":8,"Q":["10cf3e7d353a9660e2e8ec19818a0c5a732f3cc9274b8b76981a137cdd3e94fb","a4ca620152a4fc281b857000a4f13086cc9df0b2d90be453c8a39c19f940a305"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":2,"len":4,"rows":8,"Q":["4e2a4842d1ce51758c449afba0933638748f0a6d75486106cec25149fb8c8190","c3eb88783747eaf069b343e8ad057c82a2884231ee4521c71a7a94e09aa04b43"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":8,"u2":3,"len":4,"rows":9,"Q":["c41e6580cb6037dec98f04ea5027a7ff48834225c75dd832b46435adf48ec9ad","3d1aedb9633654b3ea0f5ee65207675e676edc4a6defd032e7d47ea9443565d6"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":4,"len":4,"rows":8,"Q":["4cf24c75f32a85fd2b636733fbce3070289e5240a7aa8017c11c9ed51f27fc15","4109883f882b23a980b766b342424fbe8fe85911e2bdf434b50502273444f649"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Correction"},{"pair":"R0,R0'","u1":8,"u2":5,"len":4,"rows":9,"Q":["9c636b844734f960386a1e17d34844ae4a5cda87e3031895bdfea5d6f8df9b19","82a1398fbfb7c8eb0d1bff459393b54832fe8cd4049a34b017fbf741685fcb52"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":6,"len":4,"rows":9,"Q":["cf5a4ecd260b9e00065abe7bb2093143fea2219cfb6c6ec83b14a3b9318edfa3","75d5811fdaa1922fdfd6e573816b7c1feda5b8433d1f0102efbba4baef255afc"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":8,"u2":7,"len":4,"rows":10,"Q":["17e8edadd0c7b31e83d5cc0e98bd043a20fa6d64fd2891d79d8540918d11633b","91f2123c65a7b6156187fa7fefdadbdf903a3e28c02215cfbdd2f70b9ddb9b40"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":8,"len":4,"rows":7,"Q":["a4b86f0bd3d80fff964414ed2c202c16dd846c53dd86bf1de1b71c996915d9fe","e12dc56a6cae590a9e08e141c20039c04805af6ae31e479353f26d06235b4f8d"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Correction"},{"pair":"R0,R0'","u1":8,"u2":9,"len":4,"rows":8,"Q":["cacbc156763e3a2f77fbe2f87b31c05aaf65651b8c9fe47b2003f86a45cc62c1","d4664f8db8417c668042eb8370f77337002e31008a86c88b2d903f39c8a5d42d"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":10,"len":4,"rows":8,"Q":["45735b7c175a2777d629951bb00399187181c62407af426ac1bf143097dda3a2","31146031d39c92b4f06ff6d651cfef645e9775b953d659afa774af80ff1ecd74"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":8,"u2":11,"len":4,"rows":9,"Q":["c83ca2f38deb72f55e2448926c396b0af6a7886627a65422c12992a99bb3906d","8d6f54b91dcb899ba692e6a9e123494e1ed8e693b3f7e9c97691f53f97440f8e"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":12,"len":4,"rows":8,"Q":["6ee488a7a3eb86290cc3c6f9444b6c0c710f32430f8162e2748e6e6683f4b871","52eef850cc5f512867ebbbcb4e33128a68b980fbc5b26b8e79b5e054998d7a59"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,Correction"},{"pair":"R0,R0'","u1":8,"u2":13,"len":4,"rows":9,"Q":["a6409379ff910a26e6cfea4e16a3fa33a2fa5f82d614c1e7404253856d145b94","62b93809a0db4f9ad42e763176c2811728931a183f06677442c1db1c6ec73552"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":14,"len":4,"rows":9,"Q":["b59ade32f3ef1d3ae17f4e1f21a55ad18a7c735972835f67c6bca7b1b0ddc7da","d518beccbb6e7c84888604db84db153b42043cdcee87dd81eb81715eafc452ec"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":8,"u2":15,"len":4,"rows":10,"Q":["035cc84959d7356bb43a090c5eeab616fbbc0df0e162e3ebe71119fc35e59133","00c92bd17bbeee6ae1c14826356b980633974e031df16847740e379e24270595"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":8,"u2":16,"len":5,"rows":9,"Q":["18c52e7d2e8470b4ce1c0eb8a587310b525e82e706606889a8fe361d19acca4d","1623edee4bb1e7401c0122d1120980802587113f74ecdf97308e2a952ee4241a"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,Correction"},{"pair":"R0,R0'","u1":9,"u2":1,"len":4,"rows":8,"Q":["3402b7c738847dcff14b82468b299a6be0fbb3db556f6f3c74a3f83beb07f063","b2e34fa1bd28e204be0c019e973dfd2e9510e6974f95ecefcd394621846f7dc3"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":2,"len":4,"rows":9,"Q":["e29ae39ce756b0cd472d1c0126d4db778e289c99e6bda469743d421f4b47f7ec","8a94fb36a321f3ee336bc00f2317e4dd6e70ab7e6e5d2991ad975fe55123b8d7"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":9,"u2":3,"len":4,"rows":9,"Q":["f3a2448c033c4f1579e9dcb9c70f99000daa087a8d9b322af8555683ff6f819f","c1357f82b6dc175dd448f48b592c166621d1f09683f75e2fb33c3e6dfbfbb151"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":4,"len":4,"rows":9,"Q":["cad47c89c7ec0074aed1b7de73a8e540a9a34c6cebcece7b799ee76e87601cac","87db3e5e9b3ad869c749d67ee9373994d9c77e9caf06dcce5335b1414a87343a"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":9,"u2":5,"len":4,"rows":9,"Q":["f11beb5cbdf69779e6069b89463109ba1012a3eec18e4586e55389669ffffd79","a1650a289039d8a2997ca05a55816661a00c847c176025175b374452be5f4796"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":6,"len":4,"rows":10,"Q":["9844d94f68f26dd227facb0c34d454f5c7180eb076ec049306a53f635be0e2bb","8f78c87122c27f9b1ebbfce4a87ceb80f63720088a4ca5d15117d7ad5b485f06"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":9,"u2":7,"len":4,"rows":10,"Q":["02dfbfbc9c57db3ec4a9c72b86a69e42e5ae32976a811e22f234b43285cf8b17","3bb2211a8df7e75b10bd806cec3de84a5c5e7a52f111d9610db350787bf916c1"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":8,"len":4,"rows":8,"Q":["dbe5df51cb34bbb91c8a3423c639572bb15984933e439686ea45c763fc4d22b0","bca18c9a82397e73bc1c2719933c698586fdd18a3ec9f14b482179dec282b054"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":9,"u2":9,"len":4,"rows":8,"Q":["c5a360916acd77ac9f0ceeefc515f804bd870c6f128ee8ec5c5bb1ed596b7047","d9e176b365ba9eede017a46e803f7597c95e0a4b7e82552c487f87891a47f76e"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":10,"len":4,"rows":9,"Q":["ac3ad1a780c112daba33a78d0b7165e217944125e6ef7ef8178aef80a5688bc2","53716ce9faf3d533b6cd626953f48e3a3c48a3dcd6a367d3c5d62d5fc8d6e31a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":9,"u2":11,"len":4,"rows":9,"Q":["274839b02eba1383061f6ab79134e7a82a8b4595caf0556d4267041640b1cad5","2bf01862010eb95751b0dbdd789c07bd6d029f2a150fad0ee89ff3a691a005b4"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":12,"len":4,"rows":9,"Q":["6138d59f0e767c5f0559a65d2a063455977d2db15c802e69da9c1f2fd8110051","611ed2fbbf73bb9e0b87f44b75ab3da81b4a4b2455a393831dab3868107018fb"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":9,"u2":13,"len":4,"rows":9,"Q":["d23643431ef878d7b6fc1ab0a47083022f9a6d2b21e35ac0b8131b59af8fe244","79e45f534bff20372fac3c06ffae8e53107ec2348d61ade894c27204b03f3660"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":14,"len":4,"rows":10,"Q":["e07ee0988e1d26145bb95bab3767ec4ef2a4a47a944c8c37994945665b61918f","d2dd5bbdbc594d990529cec9422b8ec4d444e83580cef283731210a943903a99"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":9,"u2":15,"len":4,"rows":10,"Q":["c0390bce02082f026a697be5aa34e4cd1de6d41e961a4d4b440553c8d6723bc1","e2d6882fc68c89469051024771d8bd87152ce26ffd26df2910f6e0154e8c0095"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":9,"u2":16,"len":5,"rows":10,"Q":["6961018a3dd0813fc38d0f4b4c51c2c8ce9546bccfd2566201deab13760b492a","528533d79176f7160739d8b30c691c3a4ee20a99d9730b7471bdbd1143dde154"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":10,"u2":1,"len":4,"rows":9,"Q":["d6bf54056bd73c6260d14848d708745a84a95a970d4fd5bc93df60120471f060","f229e2c6a2e8c913ca841fb1538236665e1f7168601009da028dd325f4588ae4"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":2,"len":4,"rows":8,"Q":["9a6c494e16ac89f73b99215f5838fcda8ddd3b10335b057baf046425f2de347e","09d40c743b729a951f34bfd43ca711c5be08eaa62498bfedd37e3cacac7e6aae"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":10,"u2":3,"len":4,"rows":9,"Q":["f4f37647f0ec3a99460db8fa8ca91306420ba9e37d9c923a34623aed02eec42c","57b72089fafd1c09ff00abb944ee367a7d5f0a57391db6f98345998482b082f6"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":4,"len":4,"rows":9,"Q":["a94d219d2c9a974c86d3a161329535a4714accfdc2d498b50bc10e5554a244a4","ddb87193d74c2b099a7c43f0e05fbe934b5de86be396b628793b2a81be0e2152"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":10,"u2":5,"len":4,"rows":10,"Q":["ba4648b51ca406455306011cd697a7ef9b46416ed1dca877440c2ed5bbe16b36","fbc7b2898aede6e34d9eee44b5322e1f24c35945745c69829be2541ec96a394e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":6,"len":4,"rows":9,"Q":["758af7dbb161d11e1bd4155e28e901908a66b0e4a2138858f9ed9f3c64303e02","b7b2402f94e3c79bfc1a0d3d11634ba8b7674c8e23e2e31b71621cb71492155b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":10,"u2":7,"len":4,"rows":10,"Q":["57f7fac688584578d55fad0b247f19be237fe2e9c5a75a42edf342e5a826d073","888c431cf96694ab7fefa86ca96206ff8335637fb39fe62d0cff6c8d776b5fdd"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":8,"len":4,"rows":8,"Q":["4df04174e82c893b0885e4bb6ba1539375c1a1c9d03c6c656ae83fd9d4026a41","0bae988430b7a7422a649e7279dd9214541d6a29452ed64cdc1f28fe3668cbf9"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":10,"u2":9,"len":4,"rows":9,"Q":["96f6e6486232bfd1f283b5786ff87ff5f9bef8ebe6274fb39ed9836d1f3cd33f","6b8bd8593bde0e7357f58ceda44b68384183891ddc4710b3a98e82fd349a9286"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":10,"len":4,"rows":8,"Q":["a2d6f3a7455ba5a155f19b5a518b453975289b1a586232ea22bb28fd0fdb23e3","fb27f5d5ff9b137b74c0c68c14aeaea26bf725bf24221f3a0ae0952cb06f751a"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":10,"u2":11,"len":4,"rows":9,"Q":["38687b9acd04bda0c57e3f4b8a85cfca9db91d3f0cdf560e174c46e0f92eb35d","d21de1c9db6334a1fc282cfe558e5dad658b8edd8edd0219714e631307cbde71"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":12,"len":4,"rows":9,"Q":["76a3cb72311ca5ddbe96a83136b72dbaea7d4e5fbe6baedbcf50228b66209605","54e78f6b40bced0ea04a08dc69ce8127aa1a2d6f51ce68ab897c745d502b0db7"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":10,"u2":13,"len":4,"rows":10,"Q":["18f5ba0d21bd3ec506fa57f8eab82d828f151766146d4a1d67affba12becd9d6","9b65f414a4f46b0c4da959066e125d057cdd526626db7966d24cd4bd63833640"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":14,"len":4,"rows":9,"Q":["69f79e65c7fa403a057bcb3078c5d966b718d141f4cf99dfb103960ad7e2fdc5","b8a4925f44e69ca1fa39d79e892fae605080e5f3274a8e714936d2609b213ec1"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":10,"u2":15,"len":4,"rows":10,"Q":["2baf4c1f47e8596ac9f3d725bae6f66e8e1b11359d8f0a902431f94a4d3e776e","61f8009de353c953a59a474cb6d2771abd428451f0705206fe273b6f1e2ea70a"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":10,"u2":16,"len":5,"rows":10,"Q":["167b3e4769fe87f6ee3160dd049593a77d5d953537cd52a850aae54c1e0c0cfb","d4e466f5f439821c663728207a3d09b2e22efd9eb8c91b619da013e4b35566b0"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":11,"u2":1,"len":4,"rows":9,"Q":["afdfaddb46da33bc98715cdb622afe96cc23d27d7af7edfae9aeeee2a901409d","8d28093aa69acade9263bb075caf10925b3378239805a91a97af2167ceee8824"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":2,"len":4,"rows":9,"Q":["b5a2469e122c8e1a9290e41338bab590d14b20666854be3772ff2cde73e6bec5","ce2d574503d5e25ee4c9b68e188b1f45a02d41fe494c82fc3b4a54fb9e1ee559"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":11,"u2":3,"len":4,"rows":9,"Q":["f23c93d7969f7057c3fbeb3cdec8594565e757af38d7474ead92361efb603efa","19cf56b4f011466ea4167eede67306f1144c01abb01d7dae5b39feb856531101"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":4,"len":4,"rows":10,"Q":["e73f16344bd656fbde845a8a186b02fbab063ab0c682c30a3d9baff44b6a34e2","2599991f8892cb4f06e438412dee519d1d27679561f57974851c22b71d340fb5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":11,"u2":5,"len":4,"rows":10,"Q":["075227434a72761f953ace6e19ee5987a6ccb8bbb4c53e9f36db283d0185bf38","d0e86ad900edf65fdeea208dc55b159063f72d916c01e7f43aa81ad7242a4f9b"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":6,"len":4,"rows":10,"Q":["4f34b664b66070d449268a6c320374b39f26cc363d9184bea5a2a4763825ac29","ac87e19df740bee715f76696f547889f572a37b8f38f0b99d5343fee2dc378a7"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":11,"u2":7,"len":4,"rows":10,"Q":["e2d9ceb7766e4e58751be2e331dd10454d414d9362e50d65bf07feae60901c99","b7c14e9f7d1d29d256f2bcc36739db034d074bf4b88e75d6c9638401ae886fe9"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":8,"len":4,"rows":9,"Q":["b70a9705e84fca5182fc6b4526065a293d33673d0a16b5828982bfc81551a739","1e25e052b8e5b22dc5b5484234aba3928e4c6a9aecd62257cea8ea2700f0098c"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":11,"u2":9,"len":4,"rows":9,"Q":["f8698f48d65d8756ee9865b5a5e5e113c200be6dfcbd0d5e59a2699ee7b8bf6a","d77195ccf3738937b433b1a845a589376412cb0b2319fd7db179dea9d333bda5"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":10,"len":4,"rows":9,"Q":["aae16d75e2efb027d14870f50b7c7fb5135a1d740fd7a74405d0825bd18a36d4","8710d5ef3533ee2ec5e44dcd9c533706c1dadd840202462aeaf489a9aba66833"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":11,"u2":11,"len":4,"rows":9,"Q":["af3847f58e321055a491fcff7c99c643cb7b21258832ea5b1e00881857691788","11c3786e36494035969c4bfcc099a94deab51f63939a316c0ae08d80e0ee9c5c"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":12,"len":4,"rows":10,"Q":["7b631e2edcd623b1030204dac67d38fd50ed81d896b35b56a5acea721e74a87c","42eae4af1f621aeee37379afa8051aff2a5db1011dfcdc1a4a8178186e227892"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":11,"u2":13,"len":4,"rows":10,"Q":["4fb51392884bae85ddef4d472dd4025948336613589809657573db82db02de02","8dd74bb056e14047501f6d158461373accb3ed854a9858143441f2ed7850aabe"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":14,"len":4,"rows":10,"Q":["4fc173dfb3e31d8792d0c4ec38d2ce44f223a0d90873edf562209e07f56dab12","f60bde70baca164b2d4fe506f581b21e20be41f9a9ab0f655d3538259fdca056"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":11,"u2":15,"len":4,"rows":10,"Q":["fd90614edf3c2ee337e48a3bc4a8a0bfa37a122af658dfa83fa53c40447892be","b8bcdd9d261faef8577cf58a4761dfa9971afb353e07d5213cd96233ad8f2026"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":11,"u2":16,"len":5,"rows":11,"Q":["84a0000faf8f48e7354e35d47b9e7bca65625888fc423f72a87c7b6f55685e55","7c7195c78ef46e4b85a42e1f9a07bc059dd7def1326e84ec548708aa5b4a04fd"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":12,"u2":1,"len":4,"rows":9,"Q":["4e5dace12c6a307d2244fefeb16441f6c11cdc9f54ce8a710f5923e83114356c","c08aa3291bf847edf8f11d8c978207e09af647d98ccd54b85bea030a0fa912db"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":2,"len":4,"rows":9,"Q":["dc507103cab343e86b8cdf82ea55b920440c91152ccb82c94e5e854c47038e05","a829cec2e5031957778cbae105e1aeb3a69190c2cdd467d22bee398436cd8bc4"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":12,"u2":3,"len":4,"rows":10,"Q":["6ba125221ec80d8f4b729baed217166ea1fb0367de71f32d8822cec5871d5581","e7d8de7c0e4923f50dd8d8523d609294a9e50dea6a8562fd06ebfeb0b2a9546a"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":4,"len":4,"rows":8,"Q":["2560fa23cfa490b165755834ec69eeb2a8efa256d57824803c04af884777582d","f5da96c5c9b082577b158461c8b3f8541c092b30f3ff3b5c05a4ed8652f28462"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,Correction"},{"pair":"R0,R0'","u1":12,"u2":5,"len":4,"rows":9,"Q":["fa6e03b92e5484ceace237f53616e43062298e331e436e6b533ee70460de2d76","4f194d8ecca3a3bd28eafcdf563fc0796b43c43be312610d1ea53a1ddf2a69ef"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":6,"len":4,"rows":9,"Q":["14cddfeb8a8c83f8899033a28bc99b434032baec6d1ea7a46818bb3d1314749c","be3fdf5574d573466d2d02b69ea9f1b42684ff5c8ed945f424dbefeeaa9825bf"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":12,"u2":7,"len":4,"rows":10,"Q":["b5e0aed6e49347db5aa74213575595b7eb65cdbfcbd4e88a348a089dc4e9fda4","e2f5657fec1546173137f6330d5bfb34f18f3d8548f799910606d74acf7ac28f"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":8,"len":4,"rows":8,"Q":["6c7755242e07c5698c6782c316db59352741ac713f40ed57607d0fda1e2aa5b9","e0e27327ea0f01a85d0addb62b4769317b06f072deecf283833a37a605cb28c4"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,Correction"},{"pair":"R0,R0'","u1":12,"u2":9,"len":4,"rows":9,"Q":["a3353ac00faa4ecfd776b3bd762860212ca85a4705b5a5f232e477903390ac4c","813f3f884c3ca48f16b5f2dba9a284a7add84fa9893550d3452200588bb26b76"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":10,"len":4,"rows":9,"Q":["c36fd69aeb31593cba8f3c0407dd4fd62b5a54e2d3a808c6515cb7e290aac598","ab265d7f4eb52cae3c995e337fc24b2e4a6a00075972b1d8f74b7b98fbd8a25b"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":12,"u2":11,"len":4,"rows":10,"Q":["52bf416d617c47cc8ef7191ccd6e3023aca589f93a9bd671e2484365489f862f","b426666d9335f2377b39ebcfb5610ff962fd692970405e4e9b2931cc53497a23"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":12,"len":4,"rows":8,"Q":["f184fd062bd7f2138661302c4e23c079ae9eda94fd104e54399ac6cfb7767882","68bf6598ef1e5f22ff7b975914138af671c5025cbbfc41d80ce62ec1d83f3de7"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,Correction"},{"pair":"R0,R0'","u1":12,"u2":13,"len":4,"rows":9,"Q":["233ed490dff5fbd1a14e588b344e80ee9525f7f01f3a150d2191e84a642af3b7","ef5a8e811e7651a2775b10cce204e188d036de59f379280933ce8c5115a25a6d"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":14,"len":4,"rows":9,"Q":["f7ab27a65e6620613cea9d7044fb70731840e4fc14f653927acac3c6aafed22f","6fdb73a821e7150772d90743a37716ed8d579cd75879ac54e3922f583d0b4d82"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":12,"u2":15,"len":4,"rows":10,"Q":["e85b178b4d137612b72182f9ccb0e5f3355bebeccae497e91aa39fcd640a86a7","dbd62c4c3cc7410d29b5eddd248232a6bea9a62858024995095f13cfdb350df2"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":12,"u2":16,"len":5,"rows":10,"Q":["136f8940a916213d590d83e78c9b31cc89d299b622e3241df1338bbc5e6636fc","e67f3c32c7552a12467c560436aca2c461048452c76794b694c5eebeb93cbb2c"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,Correction"},{"pair":"R0,R0'","u1":13,"u2":1,"len":4,"rows":9,"Q":["fbf54f32ca2111a8b105fc1f4d65b3a9f52e7a09f471ee1fd51483478f2ae041","1a4f31d4032252bc281437d5439f20fb463a71c316d1bd95f852b6d63b7cdf33"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":2,"len":4,"rows":10,"Q":["53868b6f961ce4d800f8b1aa2fe9236215fa62dcf93cc27eb7615f19d16cc9c5","3078e8a3222187a6f3d92d1842c809964ac858797e3fe5d21ddac1c0a5ada643"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":13,"u2":3,"len":4,"rows":10,"Q":["915d66a3020c48907283e8b9d0ce9ef4761caff082151d4830bbf1e8e73f58a8","881e9afb602466bfede258216cbaa22f86184738d18612cdf8f4a2955b2e247b"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":4,"len":4,"rows":9,"Q":["cc5fc59d96fa0269026328a6b3d62790421e5e947b1d93f73918d377c7465be1","c933f53c0763da1deea5d03352a0196187aab2681be2569ea1265ffd582f3518"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":13,"u2":5,"len":4,"rows":9,"Q":["d86f49368bdf8fea469ade988ee696103e977ee5311566deee4e469ac8638a4d","ec0488b705238de28399af1ee9094293b1d8dd0b52056a22d42be54be2fc948b"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":6,"len":4,"rows":10,"Q":["61eae53116f343fa7a91279b40b193bd2f1941025274530173b8b3525403e186","72910d1cc0bc8c0fdc3032c94147aec241fbafd36c01556015ec4cbc15776f73"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":13,"u2":7,"len":4,"rows":10,"Q":["a281ca2ab18b51ee7fc97a109f7df29501f47b58d34a4d5818e528e0095fd1b5","d49d7460cf0f1c0f6aaff8e0405e717c0256cc4df86e290cb254350fbf09f1b0"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":8,"len":4,"rows":9,"Q":["e64ebda42374da3c77d869a6cc31ae3e5983f047e9ad09ca7a171e42b8c9cb47","ae76b04f080c7b99f23dd3d6d7c3d5a159635d927c2c119775d83b67f21f1ddd"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":13,"u2":9,"len":4,"rows":9,"Q":["0ad3fb0f8130187b1158d40d9702971a9a0e353b08385378d8b410a71658e2a6","318d56767f5d1bbeeedaf33e1167710ab2d4c0f0cfa543aeef005b2bc9e8d3ff"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":10,"len":4,"rows":10,"Q":["b9c36e05f66fadc802260266e09b1d640905036ebcbdb93f6ec4cd57ff8140a8","e336714d75f1e1a36fb801e86081b56b06816de18ea8f3f015494f1956058810"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":13,"u2":11,"len":4,"rows":10,"Q":["6f500a1f5d47100ae4a6df1c8c94e96d1ce4f16966ff2a8debbe6370786fcf1a","d3b7235fcc9918344f136884e0a129d31a706fc85861fd84c60211711bf48778"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":12,"len":4,"rows":9,"Q":["ffa0a523d47cf08ff60578f958644abe78132fc6d58b49298e25788fe618fcd5","bd922ac1c2bb677ade65aa66d2d02fdfd7a471afa81b18afeebf8cc05c432b2c"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":13,"u2":13,"len":4,"rows":9,"Q":["3b33dec0ba1fe10a7daf7e0070bd11994e12ab030227802714aff778f2ae85df","6c2166562ed50e0ef7418694a341f6989bbb7a87a93ae330ed420c67779c1687"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":14,"len":4,"rows":10,"Q":["d0ff312bfee726684b6b3458c60bfecea4745ce823f4b89d401917e266deb91a","b4a272aaa0175c65fa50268d03ff0b51d383d0230974595615feb63f84bd59fa"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":13,"u2":15,"len":4,"rows":10,"Q":["67a52425169aef4e95f7c5aad0493ee07603b8b900d9a699961f0b99fab70ee3","cf99efd54dccc97fc530d9e97e2f6bd1f100c016fb367bc38a797e8a6009c997"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":13,"u2":16,"len":5,"rows":11,"Q":["48d727b1a9e27c2470f9c6cdaae6cc42e40bb19af59bd1bb048a2c9a5efe122b","d8c8453f6dc37827b28f3756189b6a4708046d283096c0a6f32f822db6c67784"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":14,"u2":1,"len":4,"rows":10,"Q":["abc51c44426835e7a4c2b5f4562a451990d48ccd88a49d317e1c3bd5a5949444","7219ff85d3d88619f6415e06214c331935dad8a59c14647f1d63baf476ac0bd5"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":2,"len":4,"rows":9,"Q":["74a8a4b0edf5cea6f27cd18883e9b61d0257c75c39943ca67db62e31b18941c9","46cca2ec1a6ee0b51cddbff56ee8ae216d9ddc86eb4cf67d124c1a2e62d21ecf"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":14,"u2":3,"len":4,"rows":10,"Q":["57bef7bda7dbc18e69f25e28e0bbbbed8aedd4ee6d6d70e25246f39243782720","2b0912eaed9b0505224a602cc9d307cdeebc7ccf975803acc5c1d8bfc9162405"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":4,"len":4,"rows":9,"Q":["f688d2dc44cfd81584199e82b30a46e8ddf08668ab21d9158ee1a4763144a28d","61e34c38e3427f16325d879fa4684e1841ad2c149e04389f25cd4723bd718698"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":14,"u2":5,"len":4,"rows":10,"Q":["5838699eb1365ac7b10745639f65d6bc0c8384be2ce8e64b3a5736e61e3c9550","c8d06f58a720ffea4e399aa728b0c8815d93b781a60d3719bbf8b7aa7a0de592"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":6,"len":4,"rows":9,"Q":["83a475f180716780aa89c7c37d9a2490a5d4634ccb7d0151daa246cc0c43bcac","050544067d5b7fda18927bcaff6a63a079845d11385a252db85df0049c9bffcc"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":14,"u2":7,"len":4,"rows":10,"Q":["b3f039ddcd0e9cb1e18e7dca59ee72eb441d45a2162e02b69c5176ca44e6bf55","a8ef8c4b86d38ebadbcc59eaf351b77c52bb3c458a93841f4140a195e9f2e02b"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":8,"len":4,"rows":9,"Q":["02e25bcb2a81c722b55c2ae6eef87bbd930483f29dea4fa76de0b98f29d4aadd","7e268ccb02462d48d984a23f83d0c83b8bd3be8de7b225d0d50ad6e8c73d9a36"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":14,"u2":9,"len":4,"rows":10,"Q":["51f142914f29bb71698183a9d5fc77eddd733e081e9e2c9870020490b9f0de4a","5f6be0ddaadf1e96e7fbf5c18b8cf26882d6d4af41c8ed946373e3b8c77f02f7"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":10,"len":4,"rows":9,"Q":["8b8ada9fe9faa74c8fc69534f27fa55eca65aa348c15fa04c21199f57f6abe6c","5263227c3f9a40a97bcefd88c3281394ee518f3e393821c613363aaad0a24659"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":14,"u2":11,"len":4,"rows":10,"Q":["a2c60030e8879384ece8478aa04c1cf8714d3d6b506921e3a2e5e43878784fdd","946e908ce28005e5165d4e210552b3bc2c89f10a75622a4442e3db0867405658"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":12,"len":4,"rows":9,"Q":["15b54e3c3ab1ffa854b4df256324a2b5b507e4face35ea6aaff9d18d4e6ec4bf","5e3f2d01022f88708172576c2d034b507a461b338112e05ca9f570f16a17cb37"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":14,"u2":13,"len":4,"rows":10,"Q":["279f055537ad7931a19f62df5a9c868e62542c87062f3a7bff23a41fa494c469","7fc5eefbc81c682196c5128e3c3a381f016033f2eb1722e976c1b15d41b69c7e"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":14,"len":4,"rows":9,"Q":["54d47bfe76840d9bc86e0b1aebcca11bb73e15e2e8f376a648094eb3598cf92a","e01bad9328bea8061cfe4436d2574b84bf653805f7cd0e4c9a442e0dd005b113"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R0,R0'","u1":14,"u2":15,"len":4,"rows":10,"Q":["c1e81ee6d829252d6c97590614180dff1c8a75333909b98bde475f9177bf35a4","8ad193ebf0ed7cdb5c6ed0b0e5eaab08312b89492fc3ca6093b1fcfa160ff5fd"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":14,"u2":16,"len":5,"rows":11,"Q":["b646fcead985928a3e5f0e7c7f5027ecb89652fd132f538c27798b003f357a77","6e18775a2aeb437b5ff2f530fddf517c26a7fe28d30b3e068dd72620cf509e78"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R0,R0'","u1":15,"u2":1,"len":4,"rows":10,"Q":["3e26cd837ef22f4d938460109c7a63c416a8b78f390b3a3bec5b102fb0188743","222d508ddb4985d1458f399c5cc7f0afeb4664604658aa72c4dbc1133f2a0cb2"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":2,"len":4,"rows":10,"Q":["65bc700ddc67bf9e8a7f05645759cbbf6f4e7fab9c9f36445ecef3f2a51c9b6e","eeb5f926d062f2e68d020eaea7328fc2420fd1418f22e3bec06b35d7a69d8030"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":15,"u2":3,"len":4,"rows":10,"Q":["ca7d232f31c8dbeb7f0c071875e9b7a7b6ed38f7892ed9765deafb78ee1f8191","bc3bc5ce075b24e1c2026184d3db03c867d278adf680430b26327044f3369cb5"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":4,"len":4,"rows":10,"Q":["55232271112ca987928b675c3086ed0e10d80e663f542b54637c142eadacf663","a751e818bd5b28f344fe3fde9ae20f01fa250c5f5e6087e64493a66fdf3ebe9a"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":15,"u2":5,"len":4,"rows":10,"Q":["00d3c463d842c72e20f286c68e0839de261105c1a3c58a1b33372af6658287d4","5dd768ff108539aa7310989c7e12618d2a9bf13d4f70d766ef03d21b61eb226d"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":6,"len":4,"rows":10,"Q":["cc66fb8082363a95ca62d6dbd5e7c6a201e93c101afef0701e1ff0e0ef04cde6","dcf6f35e537cea1483fa092fe4d537f5137c12d87bf4aac71fc21ccb9bb29994"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":15,"u2":7,"len":4,"rows":10,"Q":["a57336b0c9a8d6fdf6d5f49cefce1fd833961a4ba134af50a1e6dfe40a2be1d3","c0ff583308ccb356b8605820b2906f907929e515416bc409732b312260fddc12"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":8,"len":4,"rows":10,"Q":["45e8d0e27f99ecd47bb814a4a90431d954d9373c5e2ef1b6efaca1607aaaaffb","93feb8f4167e91041e02c325514c62de977052becfcabcd9f36d60c105b25fdf"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":15,"u2":9,"len":4,"rows":10,"Q":["3d81a7aa19c3b9caeff6468e50e1387ff6e24bce9646c809f530444b710a40cf","a304a72d9ec179d54bcce19371ab8936abefb1822c3e1152c1e3759c477bd3be"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":10,"len":4,"rows":10,"Q":["2efe7e67eb00d3b25a1f6343eb7640e6ea81ea4fc41fcd16e30655f02e1ccb24","4298f635b3ec1ceef0249c0bdba47498d55d596b89d60c012c27a6d5d7cc8e57"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":15,"u2":11,"len":4,"rows":10,"Q":["a8ea2683c6062da1321cc4394431fbeb3b631496b7bbfccaf27d9ec29be582bd","88837f1d26552d5ee645e826dd4b8a192f9f7e37dd68f0f4e50c091db31698da"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":12,"len":4,"rows":10,"Q":["cb2062f4dc989bd4759952ba58f0ed95fa34faa6685ce7f966c6bbb1cde932e6","bc7b190bf76bd211ba9588ade0ff438629323d7d9fe141d9d200f5c3863040ab"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":15,"u2":13,"len":4,"rows":10,"Q":["0639f68a69f7d732128e956d2880d0f0bb0d2cb4159bba7ec7a18d432fd1548c","110e1d0e234095b11dda0d1db289226c7618fed4349367709bfbe3e67c5059c7"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":14,"len":4,"rows":10,"Q":["81847712e7ade8dba64d3155d19e038a4a8affbdb3b5ab4ce73bc72a9d4cbdc0","bcdf99fe75934b67190ccdeea86a4b5be114d6ed3c566821c66c331acae39abc"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":15,"u2":15,"len":4,"rows":10,"Q":["cade487714948881e1256bdb0cb87a0b4991cc5d11aed8538ebb56b946754cd1","bef26d23812b1c859bc22aa38d00e3db1306c65ef21233f5da1e44a22177b74b"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R0,R0'","u1":15,"u2":16,"len":5,"rows":12,"Q":["8648008d261b68d460cf9cc7bff20e6b6284691b4a3f66443dc21eceeb123075","74aeef1923b8996bed5b4e0d5ee12567d66d8813e88e3a2579b461ecec46346a"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R0,R0'","u1":16,"u2":1,"len":5,"rows":9,"Q":["cb57de8b37de157e9eaa5ef06c303934506896c789d4e69ca62a3c5faafee565","c1ea931de0476336293cf1d536e2336ea6d05f98820e743172beb3c551b1fa97"],"shape":"Precompute,Double,AddP1,Double,Double,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":2,"len":5,"rows":9,"Q":["f7461c7d7364d3544a16d5a37a884f5eabb162201c9cf02da73db0336735b4cd","d3ef91be4327b77d5ea90455e57bed963959dc708738eb43e527d7ab3bb81f45"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":16,"u2":3,"len":5,"rows":10,"Q":["2e9c8c243e1791b96137d8e903a8276369d0e52ea6a73778fbfd65e072a32341","a1b867609b09e404e7100db8afe8b855d97cc394ad5e8250f2e767d3f7aeedbb"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":4,"len":5,"rows":9,"Q":["2ad9de8b86a12b369e5b98eb6b41b20b017df0a0d0a93753b66589ae2def3098","be4897bf861c34f48981a0f960314044777fcaf826948fe84f863dc2714bd1e2"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,Correction"},{"pair":"R0,R0'","u1":16,"u2":5,"len":5,"rows":10,"Q":["ea66b00065d514f1873b73704d2bb974ef09099e10f30e024e313272322f3939","5ed9df48a1f4ec2b26be55bea75a15d6b7ecbe03223e71eaaa85b81c0cb7d0a4"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":6,"len":5,"rows":10,"Q":["f2405d070464a8cf980bce33e80871c9ff2d6b85a34783d7433ac8976cf8b386","2bec606f7a84fa1b0859b015a3e4f3c58ce78b34eaf28728fc1b7e9330081ad5"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":16,"u2":7,"len":5,"rows":11,"Q":["b9a630d2007b9cab0a487d8feb6868de32da6d8de5f38f8284e0c4df22dbdf20","1b6d39c16914962aa61d0fca6cae8b3f44825c0fdb65927113bc44c167bcee40"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":8,"len":5,"rows":9,"Q":["693cbd1b0aa28afd2ec8fa77f565c37e49898b6c18dad38d5a6d0b0e9096c76d","67f24ce1c6fc049618e27f81d3aa9c8fe6bc4945fe8f8d8c6a8119d516895dc6"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,Correction"},{"pair":"R0,R0'","u1":16,"u2":9,"len":5,"rows":10,"Q":["d002f322ceb0473492801f5ee8bfdc0ff91b9241194ca898fb51c0132167d8ea","61d40038a85b613db26457ce681b971ef5ca21a646a1bbd2bc333890953ed425"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":10,"len":5,"rows":10,"Q":["c446d3066c33bf74803de9f6bdb0de1a4282ab5bf9937ec71e90e4b05e5498d7","2c589addd0896f90ec5acdaf1c4df5f86507abe62e893df2a136b22d0c8bcc22"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":16,"u2":11,"len":5,"rows":11,"Q":["e45ddf32977bf8b89f0b84b495aac6debb4b4ad17f85e4efa13db212b667448c","f7952e3dda1670be7562bd9bab731cd522440911fd0d9d5967e4e537b08f9546"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":12,"len":5,"rows":10,"Q":["44bbf89861b7b6edf692d49d32fbf1fc685b6c490043842b8048afd259f013a3","85290309a817c7ecb89563af22ea11f9d3ec3b1352685e26271750e9b6d3e389"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,Correction"},{"pair":"R0,R0'","u1":16,"u2":13,"len":5,"rows":11,"Q":["65a091e988ae3e22d804deda1e957927508907cc8bc4f5e74e09e19e14e3cc35","9aa074bab99fde8e6d5871011fbaae7fcd93f45bd2c32646c46d124dcd52a4f5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":14,"len":5,"rows":11,"Q":["a502d887a59f4cfa264bdc3130db566a188cd7bb1bdbaf0e718e1971d37cb380","62a42687187d7d6fce9f465edbbef0439a61dec0a3c730e37170c5dcd4cd56a2"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R0,R0'","u1":16,"u2":15,"len":5,"rows":12,"Q":["a74028edeb424b389cff5b05071a56bc88bbad16797c53be3a6a7480bb00a230","bec6b804741e8b8850539a326b61577395a359def5057fba9b098313481f41b5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R0,R0'","u1":16,"u2":16,"len":5,"rows":8,"Q":["256cd7a87df426e5fba6bde3aec27a4e2d2e5e6561f1b11d4936de4a58c7362d","78c9fb7eff2ef205e37f99dfa1e07e69ba582fe137a623434148600559610335"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Double,Correction"},{"pair":"R1,R1'","u1":1,"u2":1,"len":1,"rows":4,"Q":["2088f30d5d80d82b1bdfcb30c211e085387c87b8a68a1f867cc179934a188615","98c9e3db4ebc6e244f008c397129efa7984bcdd94172380c07f5f735bf7db83c"],"shape":"Precompute,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":2,"len":2,"rows":6,"Q":["5b1427cb5e96ab8b74b2ad509d7052b39fe36635dd26ebd2f681a5423ca91925","02841206536b33dec7bdd3b0b7ce714a8e3c7b91af74b11e95edd0e679059a62"],"shape":"Precompute,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":1,"u2":3,"len":2,"rows":6,"Q":["7eb0504b4d7c462c8d92c822af5f1891677b67e6d82d066f340c27336a5a139c","b1859023fb74baefbfe10ada935251059c4b4c58c9b9faa9b57c21be5cc95c0c"],"shape":"Precompute,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":4,"len":3,"rows":7,"Q":["489777802b10383cf5132f80879bf68c5731a80df84dbdb95dea933b73459d1d","1221b1a26394af8ffe2918fa4ca900fce30d5cb8ec1219707e54fe436ec08598"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":1,"u2":5,"len":3,"rows":7,"Q":["0824392df18b4d93872c688752145a716727f3e2430a92f716ffc36fa52170de","161cb50d1b6185495e38a35d1502855cd42ce071ffa82e8241233c9d20faa356"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":6,"len":3,"rows":8,"Q":["1de2eba62490e2bd60e95b3e9d9d87c9683d4c9bd29209d7c2d11aa41d2c5b59","a8d39621b9d8d5db6cd9b5421c64814c4b55893e3f579e52be7d020a653972e7"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":1,"u2":7,"len":3,"rows":8,"Q":["9b31facbc0b61a535815a76e216df114dbc47a534abb2a9119f279912f5efe34","682b81dca08cf25da5d14305c3d94c7ff5df5c43b828f4c6d27b0cbeb08ef6da"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":8,"len":4,"rows":8,"Q":["c385f41507cde7e7e3107a47d095eb773ee3c04eca6355fbd348843688e2c6b3","7b96941aa7e66912ff1c21eec695cc4348c9cf336eb0c58ab536f6affb1c5e23"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":1,"u2":9,"len":4,"rows":8,"Q":["a87462c0271f047fa41d3d5d7560000d9d6ff175fc757d6dbc9ab1adc2d84c57","0de91072faa1ee9f0fc0d39130af66e20d9bdd8e21cb9475ce18f9dc4e7fc8d8"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":10,"len":4,"rows":9,"Q":["2697300395db4a9c966ced04e8917a707920327b8d3a83b433833363e8a678cd","7944ae952dd3fd59c38f0c54b038833132a00cd8c2022a54e6f65081fb4e5a72"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":1,"u2":11,"len":4,"rows":9,"Q":["15771903930fb9563f4db71ff876bf50c9c8abf0a9873899fb601e64e0fe7b26","2bac309e05b496f712e1e452072b898844eee60b7bc457c958f28dcd265f3df6"],"shape":"Precompute,Double,AddP2,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":12,"len":4,"rows":9,"Q":["d4febb2c086cf672e7a424dc8f152a1cfbe143c9ad49e5820c99a303db481ab6","9d4be6eec0dade0a85ed8ca0e5dc66dcc0327aba760f787353fea5b414e1453c"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":1,"u2":13,"len":4,"rows":9,"Q":["8ee93d03efb7afc9f484a33c80164731e759bdb90be23e23aa63c71aa7a47ec2","ccbd99a41f6ee13b6ed7dac3e185c7e582cbf10951f9c0e6cd62ce25b6325c50"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":14,"len":4,"rows":10,"Q":["90365ce1498e7389b1e67871f4d06cf4e574be203e54d3c197b6278f5ec9b634","8a11ccc8b4f7322014072740aa106b3e32c47783b985b64be8ceee3989890bfd"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":1,"u2":15,"len":4,"rows":10,"Q":["9084f77ed3d6382e945a972e7fcf439a1a74d3b813147fdebd041f9f328c187f","c38a9b25a37a171c4b07506c9ef1ebbcf1d2a22790059f2629fa91f646fb2232"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":1,"u2":16,"len":5,"rows":9,"Q":["2c686aa166188164b9dae2728a37a3494549b099ab39835099ff58e93dbf6df0","70276c808304aefa1ff00f9f452b838f0060d8d3c4ab6a79de6cb146c9d98727"],"shape":"Precompute,Double,AddP2,Double,Double,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":2,"u2":1,"len":2,"rows":6,"Q":["2929afbc7aacf3c4d6b38785b5176c5126d4024490d8697244af7762858fbb62","e2c830c9f9bfed1dceaf00c82a3ef539bb791f9edf75d15c30c9295129b378b3"],"shape":"Precompute,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":2,"len":2,"rows":5,"Q":["0c1e03238fcdf769cbcc28e0d263d612d69cb60b071abf11dd612dfa38805f69","ad21ba527e791a5847bf012a21fe410d13afd0526475c0ae431710badcf4a0ab"],"shape":"Precompute,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":2,"u2":3,"len":2,"rows":6,"Q":["fc26a6dcfc370157ec4d5ac41f9b0d99551a203c12dad78c6ba2d2653bf107ab","b6046334bfc4bcf01339de8af4a44ed06d82293b2786f07f013ba9e28f35719f"],"shape":"Precompute,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":4,"len":3,"rows":7,"Q":["9ac69f2ed71ad7ba2275df290a22583dd9a628dfb93ad9be6ee6f9c0022bf993","684476f06576f3b5a5632a64ca10220ea435f02043f2b7d6fb05ea173998af86"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":2,"u2":5,"len":3,"rows":8,"Q":["7c1b6ab654af55d454ece0c4fbb7d2554ea01e245bbb1c19757c4ff234ee511e","a83c9b7b776e5fc01511e30576ae5f7ab510bdbc0772e5f7c424f74b4e739c03"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":6,"len":3,"rows":7,"Q":["f8d40d705f532fc7604485c3f27d756f9459ee11058acd8370f84888628782be","1665deaa395914ca6994a3b8f4c2840325d21f35d3659d4d358509bd3b7386c4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":2,"u2":7,"len":3,"rows":8,"Q":["735884bb9d6f9d0dfdec9ebefa4831003d35f8a9420ed83c402a1d2028786e74","28a3b0943dde912505d0765fdfebec1318a5c8866b2b1be1f18a05c8f5f5a6e0"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":8,"len":4,"rows":8,"Q":["95455d29e4b7356606abe878082ea790b5a894e643d692c6121e47454738b7e2","14925b40c1dbdae4ccc277d151727471f0235f1e3cbb95cf90c6591ce44d9d2d"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":2,"u2":9,"len":4,"rows":9,"Q":["04ffc5ce9bdb3a21580717efe3d377801ca4bb8b1002d3a9952a9aac0b282b7e","281b604cffc4ae300ad8b749c5b7f1fe3eb5bca62eab37e09a9507a80f9b656b"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":10,"len":4,"rows":8,"Q":["54486e4cac3e75afffa00292c97874d38816676c84edd11d65ab1982c27c8c7b","b375ca6f4de51b46b8adf163b0f5606d10b3cb8ec0aab675a23c92fcfc506cb6"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":2,"u2":11,"len":4,"rows":9,"Q":["e1b61829ec9729e06e7b72b736c8eb25128e819b538e2f48e7da1a5cf3c0073c","f90c3642a95bd9d64c3a91883b64c405329037fbba8dcb0be0f6dbeb20b86149"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":12,"len":4,"rows":9,"Q":["d5b0f4be9b34f09e5a601c78b7c5ecc3273c93517674574bbcf1486b58086c84","3c94ceea8e5d1a880a8374b0e968c754c042a4ddc56e0ca91b461e1aef48a726"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":2,"u2":13,"len":4,"rows":10,"Q":["9b04c1f436a7e842842adca1efd92e3ab27936b05e84ec376483e1e09bafb496","6de775af64376e09ed5520c273364972723408ac0669bf14eb5ac018660daca0"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":14,"len":4,"rows":9,"Q":["d11a1913f066326e843ea2cf49440c6a754698e73893e1edb579ae9cae6b74ba","b3ccb88fb339e74fb6f2f145adacd536282cf600d853b35ed1d9a835471153d1"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":2,"u2":15,"len":4,"rows":10,"Q":["570a282af38d4ca000c48ab172866ef7f7e82e3168df307baeed9b9ec985bb94","7ea43e9cc08dfaecb218863b6f074c6e3d46dfb3a89307ae5c955592572dd68f"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":2,"u2":16,"len":5,"rows":9,"Q":["b57954c7fa917fc729bd332d12d7b1411a9077986a91eae7a24bb506cce90958","d9be7c540c9463bb4662f68ef93fcaa6e497e0304dbfff8dd6d5483796fadb60"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":3,"u2":1,"len":2,"rows":6,"Q":["587f013f40a7ca6bcb35086ed44cb5f54893a8b30d44d86a2ab6ad829a5acaed","7f2273dbadf9a914a2dfa9042adf8760c381f398c2ba5f68399e5eb2831c7045"],"shape":"Precompute,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":2,"len":2,"rows":6,"Q":["12ff0825df215c1f7aefc0fddbec386cfd47392566f4664318d31a344790602b","1ff15911fd2655ddff9acdcc7bf549bd51b77131654bbf54f062b13d23afdbba"],"shape":"Precompute,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":3,"u2":3,"len":2,"rows":6,"Q":["98463bd8eb7c91b98c292991f0f188fc02c4d6a2bee373d6463a7701fa9a739d","0af2b07716f8c46c0c3fc8c56a6826a1eff0bfe8f03c89c40a3173de292950fc"],"shape":"Precompute,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":4,"len":3,"rows":8,"Q":["2ebb854ba031f3899695ec78bdbcb212c1adc11495178b031d61308e29b1547f","8a182184bb43a9b72d2f8a06b3dc26861367abf4770d507ced3a1161de8ec48c"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":3,"u2":5,"len":3,"rows":8,"Q":["c4b26ff8b57e74857f6564ebeedb29c6adbc27344948cbc99158a23a8f811c2a","f22f11b809a0ff38144b40fca7a03ecdb86ac8a0cdb8b9fea8fdb53da5818b82"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":6,"len":3,"rows":8,"Q":["003c8b9352d7fb0ca8f0ee821716a5f3840da9bda6d9cfbf9fc2128aae167dba","1009fee628a4aa4973e646653b627a27b26c696062fe2d19754585b1545e1164"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":3,"u2":7,"len":3,"rows":8,"Q":["d63f0de3df894869757c2e81b6a6d07f75efda06b7ca3f935ffe7aa3a0090d48","81cd78d11e71b90f0e5cc4e1f6f81b0988dd80b429e2a6f9e55d3d1bde7c10a4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":8,"len":4,"rows":9,"Q":["143767aec71996a61b4f5b440de4fdd2ab5ef05f0a15cc56bbf53eb8b4105d71","d2e7ac929eba9db90ede9ceef37ba229679696bb50d2fefa923a82b88a40e6b0"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":3,"u2":9,"len":4,"rows":9,"Q":["4cd57e4322b011641fa2c7b95da99fe2dd2f310d0a1286a95af34894d3af4f89","976c5421bdc83309fcb9723f0313150892cbc8eee50faaedec91197c03a1e841"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":10,"len":4,"rows":9,"Q":["448e0d008ba5c35ac5ea999ea7a027544425117cf4382ae568d0fa8c6ce672be","43d6e8a18b87834addcf40845de2baff14f836e068a047e40600b3be29bc5f9e"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":3,"u2":11,"len":4,"rows":9,"Q":["392b4555be7f4adf2907219f7c55d209f76748296abdded01d51ae8e3bf5d466","e73fad7d72653286b331e3adfe1b1b5be37be9890262e99f9215071c62921c41"],"shape":"Precompute,Double,AddP2,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":12,"len":4,"rows":10,"Q":["8975adf393a53c9b7f7a12688babdd84cfc1b64eb0e8d3e67881e242c75471e7","89051c0475e099d32af6b1f994a122226cd2ff3969765f3ecc2533389332f747"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":3,"u2":13,"len":4,"rows":10,"Q":["b94fce7774a359a9180c1a7c5e4d17825c23d2f3d5dc50f46e3c4a08076311ac","d568fb64a6de5cc04a29452eba312c1d11225e9edbc6aef9128a9917f92e8d62"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":14,"len":4,"rows":10,"Q":["58f2489dc0b52d551f2c926a8bf240ff2095b3081d7e2c9772b907d0cbd28afa","c0f6145f40339fa05fbb3219045500dabeca29449c362cd5155c82fa149110ca"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":3,"u2":15,"len":4,"rows":10,"Q":["79246c0e64d3528b543f69cfdc92af06ff4d4a800dc15d87236e05f96207949f","bc3ec9abfd3ba7653323b055deeb9f2cd6d69b5c5d3fac3fba6a547c7f9f0e7f"],"shape":"Precompute,Double,AddP2,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":3,"u2":16,"len":5,"rows":10,"Q":["98b430846594ccd70ed01cc71968fe9166152fdabf2c3e44899fba4c4c13a73c","e64becf7857e8d8313e5c416f111e334b0b349b2a8b85c3981b1c85c0537eefc"],"shape":"Precompute,Double,AddP2,Double,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":4,"u2":1,"len":3,"rows":7,"Q":["c7dcb2c33a4d44e5ad8590ba3b7e21c1800b1dc73be7bad7d23fbd98727da174","b0cbb70d2ed8a134b542ce54c9e7171586e65e9c36c50d64ec61362ae26e804d"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":2,"len":3,"rows":7,"Q":["58503b706c7a65f6c694f48bcded61ba83776cacaa2209ceda0e7598a68ccd95","d66e3c68608cfbdbac41e70270f5b2e13f508c3d42fe84f2fcf915073f650c17"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":4,"u2":3,"len":3,"rows":8,"Q":["e248650d64e5d0b646cbe0025d2c39bec1441f41ea5ae2b4ac51c300de702039","15a317b3440cfdf32abbb10241ca6ab590be0b9076649bca3a0f5ad5ccd02e09"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":4,"len":3,"rows":6,"Q":["c6d477669b498087763643aec1e9f0e0dcad3ebecceadeb186e040ab4839907b","3c7fa7e06c75b56ae3f48719df4e3119039e70c74c9a8b0a9bcba04ac0e971f3"],"shape":"Precompute,Double,AddP12,Double,Double,Correction"},{"pair":"R1,R1'","u1":4,"u2":5,"len":3,"rows":7,"Q":["c1b2e72dc69fd76249b7431390144b246b473490d4672e6909cf67dd5efcc1f9","e2df364f7feb776b0f3821d342427491f82c0425fae685ae6f4ae44ead324452"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":6,"len":3,"rows":7,"Q":["fac88e3deca5a2a2d51378124d52c774741fde1ccd47c746ce109d47827e36f3","cf39ed4df62ff78bd9ade6a16d36260ab3f8c48af5a8893b1d2cea8239f33679"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":4,"u2":7,"len":3,"rows":8,"Q":["a11b098bbdbb8b12ac90c080a349150c8cb3ce2f2544709507e48947807d46b3","acd365b4b6dd404dc8eb43a8269066bbe53511b858659f9aade66a05ab4f12f5"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":8,"len":4,"rows":8,"Q":["ba10bfd05021d4709f272f3094b5754ebaf4394d3b58fb08d1d0d965352453c5","80a776f832c38a25c7526c1ea9b510ef078ede61f34023746ed879fb78f6d3f4"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Correction"},{"pair":"R1,R1'","u1":4,"u2":9,"len":4,"rows":9,"Q":["11ffcd720727d030f14f0b7bc52ea788f203cf0b587131962f7248feb010cba6","02b3c2af6df3934459649cd86833b47234c6743a834d090af85a74ad71fcd805"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":10,"len":4,"rows":9,"Q":["578c93fb67fd8e0f7efbbcde44a2d7d4056ed77082fa3703a1737bc3f5b7ccc0","a0315d1226fe46c18bbcfd9c277769026eaefb0faf93a57e6f33ca762d6553f7"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":4,"u2":11,"len":4,"rows":10,"Q":["184abcbf2b48bcd7ec2c5a57e1f57fe92c49a7481084effce4f1c8d526fd84c9","a34cc87954629eaf77989f18316fb7d86e34957835ae3767a178a3b154509e64"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":12,"len":4,"rows":8,"Q":["8cff8bbe7f5c555d4bfaa756c1c286606a49a9a02c85a31f04d3c1a534beec95","33b1e14498dfc7d66cf15232a2123a621e8155c5345c7af60bbf07a715767839"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,Correction"},{"pair":"R1,R1'","u1":4,"u2":13,"len":4,"rows":9,"Q":["d5a374b980ed8a0f250a43b2a40c81e3c226fa395167f1de7d284fb5742543cb","413614e503945b5a8ac7a9c21d22da6ee77ff7f63d0f6266427b824eb6445242"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":14,"len":4,"rows":9,"Q":["4f900bdc277a89499ef408468561c22f050e4c48f51e46cf1a09428229c2541a","d29618db58e9d6c8a0442b3c9f51f1fd536b7190f194a95b2d3d9e8fa2ff8f70"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":4,"u2":15,"len":4,"rows":10,"Q":["1248a8f8ec74fe5bd7f6248a9a205e30ef52b62d851c96a27549709bf89b934c","b3b7fbc4d2085f0ce47c3b918a42a6ce3df2fa32b8a184f95456aaf91ac6500a"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":4,"u2":16,"len":5,"rows":9,"Q":["632d19d51e2af7714541cdd789c4fda5bd6be55cc11ae5eb8c6cc4638de84ee7","fb597255a5a437de10217b732c10279989f65febc33b5bc46fc84bacc8977a1c"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,Correction"},{"pair":"R1,R1'","u1":5,"u2":1,"len":3,"rows":7,"Q":["a366d663a552c132c5d6f4da51c96de31efb11d4ba694ae62e4aeb570c2e30e4","c2f87decc4b7e34c729ddfbd064d870fdcd90cd8a4941a27b0e0a66a53515c8c"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":2,"len":3,"rows":8,"Q":["74b9442e8f9c03f7de7a4b6a8498ed154f83d3130cfe626722b3730b8cdf6619","a2b5b46cb4730ceb866d30854ca78b4548ee12a3038100665e05ef628231b5cb"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":5,"u2":3,"len":3,"rows":8,"Q":["95ff3ac016f36f8110b490a1cbd4879defb3da16c638661818960506735517be","5bdacf539ce4a21057f68d9cd1a3ed4306ab3a87ec5c6f9deec62c4adfe1a9cb"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":4,"len":3,"rows":7,"Q":["3fde55052cc991ddf6910afa08a101821f3918169a2120435944612899afd514","174755c04aa257d35ec706a8aef106e03dbbd570c668d0a8be7612dfe2ed4fb7"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":5,"u2":5,"len":3,"rows":7,"Q":["481a39bf9b4c96421cbad943583cba7d01a30f6c9d51d3667a9398836b38a7a9","b0e49d1e24e606e4497f26dded40ace79d957a362d4f5ff3e63a94a8c5938a76"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":6,"len":3,"rows":8,"Q":["d1f5af117df4562c3dc2598c47c2cdac939e608a5f2a5a402927d12925615789","8fa9f2628c09a98edd0ed0cbaed85cc29e33d2e374214e026a77204b15b143fe"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":5,"u2":7,"len":3,"rows":8,"Q":["5840573ce51b0bdcd606017f1037fe71da4bade175e8284d8135905de48a1248","62c4e1d35272ac89857fac8960ae102b2354a15105ca563c6055f42dfc32ba36"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":8,"len":4,"rows":9,"Q":["d1a075ba6608c6b65d6f75f6a756324278d797a106ac7aa1d7a3129f70aaf6e8","65be8bea0469c6d597cd2bf16a1b6f0a06a4144e83a5f78cf6c0ea9d9508c93f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":5,"u2":9,"len":4,"rows":9,"Q":["d861a7315dec347fca240a01dec16fb9058fcd9cbe7684b495c21ae98c0e123f","5f176525f68f33da2e41dc88e5477771d2b8a4e82cebab95bf0b964485132175"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":10,"len":4,"rows":10,"Q":["0612c0058284477212338e5a388ec53b9c73a31731c283c0ae9efcf693577f65","5519a19f5a453e25dc87cdc64076dc07eed199bc5a9fd6d778892c87f19d1d22"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":5,"u2":11,"len":4,"rows":10,"Q":["8aa888a43ce8079f4ba3967577a1cb3e4041b3f567cde68bc9fb8cab7d1e9d74","75bd1a001da3968bcc2b5d6a758b9879315d562a984a21e120a85fb31383533f"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":12,"len":4,"rows":9,"Q":["217af088dc436848b5402a72e78f3e17523446d5ad8eb93a357acf247ccfb86f","5b6c1c61929dcb143d7d2388149979fa2206229b14c5aee15b94043b1d03cbae"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":5,"u2":13,"len":4,"rows":9,"Q":["7d78fcb6a001f499d5bb3f5e6a15072d46078e583622cec8e2956001fae40e37","f5fc7b4aa60089260c38c72ab5bf93a2baa18523b9e718a097b9aef43cd9d700"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":14,"len":4,"rows":10,"Q":["a2252750b92cc187de04836bbef352ab2652372a92882f67c1b2c6b0fec16020","a34362d25ca9c2618fe95421882c2a77f5f097b6758d80ecad5aa44e3ea0e6b9"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":5,"u2":15,"len":4,"rows":10,"Q":["a59fe944bc5121a6a74d4d7047fd2220dd48d88ee04c478e5cb41194ce595080","c07c3406f9ca9496e46716c7c69565905168364f0b67a6ed757d016b0ad870d5"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":5,"u2":16,"len":5,"rows":10,"Q":["5af12993b43fc44eb636bd6d5630cff0b31f6dc009f49abc85fd2278c5064479","be7fee641ed682b8d25bb9dd1c77659fff272eabcd8c31224bf522d3af5c573a"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":6,"u2":1,"len":3,"rows":8,"Q":["ff6173cd538316397214c61c7d8dfef4e5b135b3a22efdd0b7ca9d458ecd9a0a","19e81d8737b2596a3273bfd73d4be9560180c479e14b7b3b190675db95d2ab48"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":2,"len":3,"rows":7,"Q":["3e6bc83c9eb16ecb6ca6c0156bbc8e8c608be55b4fe66ed34bf08fee841bd80f","006eea81113dfd6f8c352621d91a4036167c8ccaa6234f202fe611c0144c2cf3"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":6,"u2":3,"len":3,"rows":8,"Q":["c10784572b6c8f93a7c3bc57e15462f228a4cfa0ba44e906e33bae0cea9790d6","0aef954ff8de7a5da14c707fe72e1e670877041d46533a9412f2aeeacfe4ead7"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":4,"len":3,"rows":7,"Q":["9bc995c3ca63ae5e533c987c1b537af835a639cb383b7468d3125aac8ebbb8a3","468e481bacc930bee37063b5defce8a49b8c6b8354ff9b69593bb6f11e85b68e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":6,"u2":5,"len":3,"rows":8,"Q":["41b86b44931f2ecaca4b3a6cf81496f48a42245f8651e011076c045e56aa065a","401aa13f5ccda14ba78446addf024c05a2a00f7539f36e5d8a4c8be1ac0b44f1"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":6,"len":3,"rows":7,"Q":["e545cd8e5532e55004af54bb8ad138a85c1892d1155aaa825871c996ccff0ff7","955b4d3f7a670243316c8ad921c53d84b00d7bff43200e3bca7401335cff53ed"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":6,"u2":7,"len":3,"rows":8,"Q":["faf472ca6def30395ba4c234856b43d9ce9c6e4b2ce401ca17fd7c914c0a1828","de0b164e77db64aaeb9ee5f216ce456d9f3e18d48aeb6d66c4b89e1de776eed4"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":8,"len":4,"rows":9,"Q":["7a6a212d6a1ff2383bf90a4bc90dc6f35db67600eb7e4dad1f00030af3f593c6","6178731167f766a1af6c0ba6f5acf76e2be7d7a4135aa5282191b82f42731053"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":6,"u2":9,"len":4,"rows":10,"Q":["ac0390be378f79804fbab3c0d5ddf269b21641a643f6babdcaf756b4b77b010d","a298c1f6f6acc071104f5a842d669d1d24e46447e999f2b35f6ed8aa9e009a55"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":10,"len":4,"rows":9,"Q":["a6b48c960e391b1964ae4822c934defe0a0fcc5624b07e8b261adf5c58ab3926","c89ed6ff6625e9da3572c81ece758fa8379135d2e5dd1a2c21a76cb25b6a4c1b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":6,"u2":11,"len":4,"rows":10,"Q":["42302474ed64c2211a8068a87cd33c6161985164774fc90b9792666074355bee","edb3155474055a7059066c83ba827273dee897e2c20568842f7a1699911ecd9b"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":12,"len":4,"rows":9,"Q":["bd1be914cf5db54c1fe030d9f227e9a0d81a3d249ec1e93d33519758c8089713","5186c8d7d0b290c3009559c06d4b4e4db43f711d3d95e1f0f5ed3b50933c3c9b"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":6,"u2":13,"len":4,"rows":10,"Q":["decac025e16eb3e88d384ce985961065d9c579554c3547388d24fdaadc4d52e1","02aaf4fb7eae02cfbe5d469cb2b820352b4652921b717ad24f10f92675683d9f"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":14,"len":4,"rows":9,"Q":["b824a966291394c5b205b361b47d12bd9191a403230e52f3aae00b1126552319","a40be3182c910ba74a2332ab277737c0147466716fe03ac787854fd2457876d4"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":6,"u2":15,"len":4,"rows":10,"Q":["61b9308286787f3ea70abc06b589234f1a78a064fe22b407b1bbb3c627fd1a09","af2c6978dabdc4ec4c05057dbe58a145ff41d624cdae58c8070ffce692495211"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":6,"u2":16,"len":5,"rows":10,"Q":["a8f7262c262e92677e17d3fe6456372466d1d8b177e3813c0987c4106bca3727","78dc66967acbabc56ca07688baa549f10aa247e45132d69809fdd1dd8cbe6f9f"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":7,"u2":1,"len":3,"rows":8,"Q":["97f3601404e12498e404dd419e37eed93a3625a981942c87ed5cc329f673e958","c8c1a23326cd1d292154f3b3803decf3f729fb79f9be33caa109135348e0d28b"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":2,"len":3,"rows":8,"Q":["964adb60b0ca4746d333e1219183eaad3e56c8bd16580342520eb64e1f4c64c3","f65e5472bee6ec7c9ca19a63fa0f5a9dffe2cd3b04ed3a4f56b308a4486034fd"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":7,"u2":3,"len":3,"rows":8,"Q":["18a38aadb0960b6712526a9707839ebd26b67f58f9daf4e61a510bc4e3c8962e","242bae4ba4e2a8a9e676061b73c2bdce44bc15f7a464be93607c430a57c73270"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":4,"len":3,"rows":8,"Q":["7762abe799ea3f915bcd7ebfc873c836354c12af6409b9ae753b0ac1b6febee6","1115f287e179c3ab67437f912f168619419cc96ec70598620c67eb6abf5bf14e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":7,"u2":5,"len":3,"rows":8,"Q":["cb6295d0a23947a274b62d58de6febcad3c7ebc8164cfe4cfb33c8cb8bc2331c","155b35eec8cdf33d80974ba75ad53aae83f9cd437f9f4aad0eb5c3861dfcecd9"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":6,"len":3,"rows":8,"Q":["d20231b0c3dd7d25a5fe6e16fc08c5228367d7ca6962bfed49713198f7edb2ee","2f6bb357937a49a1ce800edd9759ca4bc3349db168097f4c676749eb0210ea53"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":7,"u2":7,"len":3,"rows":8,"Q":["7cb3fab3560caf2742be937c690afe9dc1d424d9df6f97128c132a48e9a1a24a","37810fa0316bc7d7649d137e678fc2632ea70bdaf5d518593a57088f3d687a56"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":8,"len":4,"rows":10,"Q":["41b006c260ad0d91c4534e778396db700194f69836ed5dd9f23ea875e51c071e","b11c9b5c507b0a6df3b236f80ccfac02ecd76de76a1341ea64ab7d7169599a83"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":7,"u2":9,"len":4,"rows":10,"Q":["cbd5192a7ee595d7015ffa6c4145e9cce3f191ecbe2fce794518e1451b8bfbf6","0c327b6264fe9d0adfeaaca78dd2d13cf6671c0561e6b8d01bab90e9749d4119"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":10,"len":4,"rows":10,"Q":["81a3192a566d366c95205c1244d0d4d5922d4ad9daf1b24c541f2c8f381c4396","770d6bccc46bcd1d41741e2e1b47d40b188ffd6e07928e5ff4d7bf264990d436"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":7,"u2":11,"len":4,"rows":10,"Q":["d6327dbc12941fe3d06f63bacad10aad173a9f0aa03a166c3cecd19b7301ce1d","4c4e98f60634f68b87c3f2adc6f38cfa0882f0e130bbbc3bca4ae608e07f2754"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":12,"len":4,"rows":10,"Q":["1f719e1ba29d4d86df8f2686c37cbc08debda97f9dde67cf74c25464754aaf3d","0f08fa324d493556e22aee49a4895b9dd9efef613c75a43a76c29b6f2dffa755"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":7,"u2":13,"len":4,"rows":10,"Q":["d1b0fdfd60ddb887f26895018e9c10d7cfad5fe7da991b671f275d6961667be7","f4bfb41a2d11e5754448df8e795dc12ccd1df49ae4d4f3b37cc7c6291a5d3ebe"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":14,"len":4,"rows":10,"Q":["58f7a975e6a5c5ecdc4cba43c8e9d722ec1787108682afa94576248daea27bdd","747c732b6e5153b9c8de51d136943fc91d3272fc282ab06fc505ea10cfb85cfb"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":7,"u2":15,"len":4,"rows":10,"Q":["1578f765a812448871b55794729c95816d6df5671de42580e915992f4841a017","625b99e2c59e404750dcb329f6d43fd84edad22fa043eba9ad8b585ce4185d86"],"shape":"Precompute,Double,AddP2,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":7,"u2":16,"len":5,"rows":11,"Q":["47ba77d82d6462489ea01f100e2e49e3cd2af1dbe8419187df767229fb41c01a","7f702fe6fdedf1e805164edcb70a9b36da9c98c2e6449ddcf26413b8a4a3aba3"],"shape":"Precompute,Double,AddP2,Double,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":8,"u2":1,"len":4,"rows":8,"Q":["eebc66b21302c9bbb029393b69a9eca727672446ac0c978eced5c976a0dd88a8","4c6b7af62fce88c939107edc8685fbea516f40cd7a2e0322a280712ce81fd598"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":2,"len":4,"rows":8,"Q":["a99892ccc60348a69583f2f4074fca333834a7715260368551fb3cd555aec847","f79209da6a22fce19c7a4dd8de8a0673b70da457ed04da49b29f5094b11840d0"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":8,"u2":3,"len":4,"rows":9,"Q":["577d0c159394a98b69f4d69da0aa0d578ef0eb8d4f169ba768b7d4d5c41339dc","8afa356db098494dac5a8f4ea462d33c83e8a650cff379a1033e42675b94b452"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":4,"len":4,"rows":8,"Q":["06dfbdf4a21e22f01f900bc69b643283d19a167c2f46222c0b46c7f7eb66e24f","5f7f20ec046d72f4d03e3539b5754764bec461a7ad3fea6f0e052d6513de727e"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Correction"},{"pair":"R1,R1'","u1":8,"u2":5,"len":4,"rows":9,"Q":["477525f59a13cb958b44232b8019da160c5f83d44159fd40d93055401d0c9cf1","df6dafab60cbdec6be8ea01e4494bd528507f29492010c4c13a1a27927397260"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":6,"len":4,"rows":9,"Q":["cef8d79b1cdbf65a8237e3fa1d32ac5280706bb18a851a54f87573ca586db014","0c0987fef7a727e3901b585cbd7f26034842db67f61c7d5fe7eed55015c02860"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":8,"u2":7,"len":4,"rows":10,"Q":["a7b0e0781693888c327babc84c3e0813cfd7d902ee742f0ee6bb217160733a99","0b63c125af389ec50f2a77557e4fb48d73c8fad73b99b3bf0c224ca1f1467761"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":8,"len":4,"rows":7,"Q":["47cdd89c4a758b95e73fd46d7a6b6b9d3ed884158336e6a82383e8d987837bc1","704615fca4c53db8dffb3b8265b938056504bb08b927097ea42e9cdd278e0602"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Correction"},{"pair":"R1,R1'","u1":8,"u2":9,"len":4,"rows":8,"Q":["4ef5002e15ed9e2dce0b860164f36b3739a8bc758499f1702b208d05257a76d5","ba596207924e14291fad2b514489ceb3a16d7ebe08fb8a938d93d7e45b97359f"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":10,"len":4,"rows":8,"Q":["9fda0a9a3b992c4573e24f7ad9d9bbcb1a6d09f11525bfbe63f1b41dbd9a29bd","9f8db302191ce641d43da0bdc83bf884819a8e709cd1076f180eb303a37f4796"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":8,"u2":11,"len":4,"rows":9,"Q":["5521929692f00d1bc15ed9c5d929a49efef0f177ad8fb77555d27b914a4b33ad","30910a5e1bbc41fffa425d167fce87adb9eae8060efbf40bd4ac7fcd16906120"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":12,"len":4,"rows":8,"Q":["f689a5a99739e09e149e0b873f6013a88df930e785f1c4e7d8b4be72b95a85b1","64ff27833056441b58e4bb798ab0d6e1daf3f0c6f7e8edede0a766f0c176256c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,Correction"},{"pair":"R1,R1'","u1":8,"u2":13,"len":4,"rows":9,"Q":["cc43ca48ede1773c41855269c79bd6b1a34782563bcf477b79c9778544e594c6","603091fcd64fe70b4385c8d8544a5f8cd6c772c25d6ebd66d34ab1a2681123e0"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":14,"len":4,"rows":9,"Q":["ec349e05c1a61e6a66d0582f1a9fc2d8c6b6e6fcf0a5f28918de74e6a8e199c9","068bdb8417aa01cbc6654e85d7a995e0d6010649a9cb985d917c0f5ee447f2ea"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":8,"u2":15,"len":4,"rows":10,"Q":["46bc0facf5ffafb133c1a433f1684666bac550189ef50e62978ee8536f500c5d","245f8dba5000bc553b21ae457794687110a06ac49b9576022559881ce664123e"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":8,"u2":16,"len":5,"rows":9,"Q":["528b69695c76f2bc742e4d7ca27fd37ced8a5f5a878f65eeab7d8769553d823e","0af0bb325cff5c7d501b1a107b60edf40c63fb6670761829107f219333cb39fe"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,Correction"},{"pair":"R1,R1'","u1":9,"u2":1,"len":4,"rows":8,"Q":["954bbee4d9abfb99a17be84bd771b16a02a0365a2591221e37f5ead63fd55808","17b590abae6df7f2b8b06fdbc116f7aa85dbfd7ff3369b69e92e333837bac68b"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":2,"len":4,"rows":9,"Q":["51ca298759ffa084d53dfba1b9425442796fca4e8fc9572d450ae5924527d0fd","8e4daa825e3c65368e611eb5255314c05799144ee5dba04aa7c8b2ac6313b1c9"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":9,"u2":3,"len":4,"rows":9,"Q":["9ea65505daa84047599e1ff4511b707d2b2b4893b3dd9805305e7fe97f6b3a60","ca07db57b241dfffa657445c23d5473870675dc704920e1bb3529795a33434a7"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":4,"len":4,"rows":9,"Q":["51314af3c0a97cf3e7aa9ed514d73c07e90760a6524daa4e8db2c253539b3b03","fe2bbc35e7090a3d7e00bfc1f3a6942f6cf3335a8ca515caf067319225922e55"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":9,"u2":5,"len":4,"rows":9,"Q":["b5809a73f40469ea10e36181685ee953d990fc673e008268273e77b1688d34b6","e9a90eeedc3de3f46868fa16fc4a2ff679b849ebeb896e5aba0d0af18d999f04"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":6,"len":4,"rows":10,"Q":["47ef1da3414d20908b9e97ab26b8f79b4555c4299da200722eee12152bfb3aa3","fc99eab86f97736b9960aa5021edfde9b69e54c5ba9c907e81954d0af3e7af48"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":9,"u2":7,"len":4,"rows":10,"Q":["d1ea16ab63489fcf6e9d21c52c167ab1b72a2074d62923d54ebb0babb5df6732","e168192251ddfe09bc2364d3ba4184520c7156b6968429ae1fe494b6c23ac220"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":8,"len":4,"rows":8,"Q":["5805291014e793042c517bb6fc39c37ec3abd147e9268bc9070edf7c458c0d7b","658f19a5862a58cc676ea03f92797236eea9684112afa391d4c4f7131bf6caa3"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":9,"u2":9,"len":4,"rows":8,"Q":["55ce9450411e867684a1fb29623db94c8a1c6173506b415415bcd46ad4dcdd97","71bf34adad23ee0ffa53787aafa116a29f54d15ffca93eef83899a596c30cdb0"],"shape":"Precompute,Double,AddP12,Double,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":10,"len":4,"rows":9,"Q":["011a034dcdff84b2aa8d0b94bd5390618cd53cf7196ed3869aa8eb8b5a83554d","d9a82b958b80cf9f9711a982c53df676bc09a590265f0f74e1a0fe0d77576cc4"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":9,"u2":11,"len":4,"rows":9,"Q":["28dff7d3075322dbb6a54efe2d45707d96a433452f952e739b9a8804334d0055","6048e6141f5994594a1b7a8b2e993ef428c1e8baff4b57d36fe29d6bb45b8a74"],"shape":"Precompute,Double,AddP12,Double,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":12,"len":4,"rows":9,"Q":["6db2fc10e97e191cffc88084ecefca069dce0d9812e4c0bd5e278a5c465b07be","b9c413430eaa8a9af60ca3b5768f1e81a1ac98c8c257bcf6bef776ffb50247b8"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":9,"u2":13,"len":4,"rows":9,"Q":["fb23e62e8eea58a95ca21a6c35e59610b88a22fc9af1f1ed8e46ded6f1b08fd5","957f49cb109d7d7c68b31500d0741b9feb5012df2e7e15beb84c49802f449a45"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":14,"len":4,"rows":10,"Q":["d30c58ceff19370aae80f2cd2e6782db2da9206c3f67ee047a03a81e171b6e10","42be379e9a709e9f86827172796789bc7020eee4b81dc9aabcb11b7648b065f6"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":9,"u2":15,"len":4,"rows":10,"Q":["b0349a5afdd6073416de5db4d15114c9ac584f1bf1365bc8ecc95e1c93155631","ca25082c5c304090fab33769d9153b6099ce2fa0613dc61da869ed2d696d0bd2"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":9,"u2":16,"len":5,"rows":10,"Q":["5ba1198c81a863322d90d561cbc8349627e8578fd278f6fcb966ab96981cfaa4","274b45319970f7243e0179817eadbfc8b6aa7a9178dce0c211a856c5f18a40f0"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":10,"u2":1,"len":4,"rows":9,"Q":["dd361bb7b7321517f205b52de220c2e085eef5116b18743bc86d1f56492cad6c","ca9c758ad417f9026b020fe52e3b2565243027b698df6548967e64e7e9214ddb"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":2,"len":4,"rows":8,"Q":["b1bc4c06178e33d2cea57952cc20896d58d594f6c0c4dc66c1085fb3a22917b5","2c2c163644d93ed7ff510fe2a26cabc5d83a4b60f94acceb0a69ece3d431ddb9"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":10,"u2":3,"len":4,"rows":9,"Q":["7c255d121186b1ceef5d6279899f7dfee6710b2e5719428dfbaeeed1d970b54c","397d572e146049cdb584fec9b643e076ce2490f6c675f8a09fcd3d44176f36cf"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":4,"len":4,"rows":9,"Q":["cc14719a1991551fd7a80902c9e70e4f6e175541f0e8d21c0311b92c75bc3e42","2e51d0792ea686a5b541f56a2df81f31a7e8241dec8b826b4eadb9bd078d2696"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":10,"u2":5,"len":4,"rows":10,"Q":["acb2e618a8eb2b9d7128c7d0a0d0496871d24214b46e31af838049e72600a300","db5b30df4ab0b3b384a183c45c63ce15b081dc059d6052ab2959c9f4cb87bf66"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":6,"len":4,"rows":9,"Q":["9dee2bb82cca0535c203a460c19ead6079d15e73d081e3979fda6a1ddfe8bb40","0009b53b484f529009892b4bb442f934e6385f095c8330842551e1c24b96f4f7"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":10,"u2":7,"len":4,"rows":10,"Q":["b540cc8da08991ea735ab6d36f9c83f5c86d47c99d9b06e5b1b1592260af92c5","3ce72af882d148926f6dcec0db57e17c374cb619aa5691ee50d0416e04e8112f"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":8,"len":4,"rows":8,"Q":["ccb20cac00c3864bccfb507ad184721f371a5ca9d8e36af8f82168ab7acdec58","199e7ca90e4cf445ce295b6daca0798d56771849645cbe22d6a3117019df1e87"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":10,"u2":9,"len":4,"rows":9,"Q":["a15063baaefa04aaff211df1d8d0c58734a2c637921416b225e2317eb0b56ad2","f8e1f54eae1dae1aa47483cd8ddce7062442d621f7311f91a6be84a612ffac98"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":10,"len":4,"rows":8,"Q":["8e6436079cb20fe9089ac762d7ee77bae6552434f39462d1f33d863f2072d479","86906c44feed7845f0c1dd56e796d935362020f5503bdb252296e7d19d65a828"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":10,"u2":11,"len":4,"rows":9,"Q":["307a555217113f74be2fac0b6c4239c81bccda0130d04600ad01fffddf78c895","015616f6b6a023873e8bf175b9f1fd24f81c31529e6fef526f21960733176b77"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":12,"len":4,"rows":9,"Q":["6a2b4bc6906dc942c50215a7d37832865d9fca9bd93edefded12aba2d2bd5bd9","57c6491db198813c0d3d2418612953de26dffbf41a85c2950c8bcf88464c13ba"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":10,"u2":13,"len":4,"rows":10,"Q":["9ad3cce201aa3b64ba4055fa04718e35ef89edfe82b358d0b9b1b331b06dd1ee","b715d1b5164350283d7756feeb30a15df81aaf7e4d439b667cc6004ecf19842c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":14,"len":4,"rows":9,"Q":["d621a6196c4fa291529072260ff4d7aca0aed93e9edad2acde17f96a6c2d17f0","27aa4069f710aa15a83754daeaf722317c6a19a1325fb1fec34c9f779e68fd3c"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":10,"u2":15,"len":4,"rows":10,"Q":["4669acdf33ad177fd2add3d4b1b6c856c7261bfbaf2c5d1ed888c9d96f0ac8af","85c718fdccfbd94a99816e2150387f56a4c05ba53cd3b63a6b4e76db7a98fcdf"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":10,"u2":16,"len":5,"rows":10,"Q":["3df5cbc915d72af95af281d002223635776c1b32f12123d8be02f81cdc677167","f3cbf431f010c53283cd3823a1ed874954cdbcee87ab2fef917429a435bcc206"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":11,"u2":1,"len":4,"rows":9,"Q":["dcc2277d64cc41f11d58776a9edbcfe82e9740d0a55829086739d0171a82d899","a8e696ffb2ad3c49c822c8bdd238576b198eced65718aaf6ce0a5fe4ebfa3828"],"shape":"Precompute,Double,AddP1,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":2,"len":4,"rows":9,"Q":["72eee45a26e6738455220eb68650b167a4e96786b58540266432337d9b119df7","890480bfc0c64deafd5cfd45d985162ab1eea569ebcf9350a98c58f257377daa"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":11,"u2":3,"len":4,"rows":9,"Q":["6f5eb8eac98bab961dc1c1150706af4cc91dccc2f75cca517c35686efa1fe53e","e4f601fca154115de54b5c9e1d69c06bad440c3eca2a19e1d2e80e8cc54e5309"],"shape":"Precompute,Double,AddP1,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":4,"len":4,"rows":10,"Q":["bd34e593eeffe63674b0100a078cc60a04a9f4e21fc7d9b5cdcf1aed6b7b81af","90b43739c408794e7ca226b43aa1d5e9c5e4c405a6ae29855587b251cee21e11"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":11,"u2":5,"len":4,"rows":10,"Q":["0699931e889a336ad71c6806b7ada4242af9ccbab96329256bc0904974534f79","ab152a0f3b6a036d26e253b24a65260228de7236bc3138729929fee4ed17395f"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":6,"len":4,"rows":10,"Q":["3128bb5b7de7619b5bcd1d95d747869f331edff463d1892c4c5c5c48f8efdde7","0ca72f7a9ed7ba19c3a3dfa7080c8eb2dcbb850641a479b81a352ed5d8babf99"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":11,"u2":7,"len":4,"rows":10,"Q":["8913a946e87a706e399ef3daa07c42e219711cdf9897c37b293fa635a0dc7139","b809db2569867e91265e4472537a5e9f583ac34f0c5b5212810d08171e8f609f"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":8,"len":4,"rows":9,"Q":["1e01163ada9fd786c3fdc73c6cee0cb722462e97a2759f4b3ff26889a252a21e","6c2c8e8459ca5d74c09ee95472ee5e8addc80a7a83ee32e792e42e3b917c7e88"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":11,"u2":9,"len":4,"rows":9,"Q":["ab07ec720b46bc15020e42bd9ee807335ce5605e6a63b1988e14c53fe61ec026","21806b5d456941ae8756db1cf5fbc37fa94ad8d9b5ab5ca8727593fa0788bc1e"],"shape":"Precompute,Double,AddP12,Double,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":10,"len":4,"rows":9,"Q":["2c8efa3aa5f80163b99315c0366d6bf2697129cac336155ec03a938fb1b95aa7","054995323fb896f091f24f529a1ba618a12053749a8f8277bf4ec5570641d3db"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":11,"u2":11,"len":4,"rows":9,"Q":["69f64d64e01c9ca3c2899970e07a08b9138804e04666975a159173e20d47fd03","13ed022976bd5e849307ba5923d646dcecc386ca3d98a96608a54b65eceb6157"],"shape":"Precompute,Double,AddP12,Double,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":12,"len":4,"rows":10,"Q":["a221d349a7d437839cd6bbf07ab6e43dad16eaef1c9c3ad5bbc93408a0f9f882","14688f6823c5f94dc840f685257ca4a608751260adeb29a06b3cbfe103660b7f"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":11,"u2":13,"len":4,"rows":10,"Q":["cbdac41ada9395a317b6ceeb861f695cd7f6017e3895d7a56bd24c9c6f9b132c","48e29ed7184d1858e328a3358e25f80083aa840b6d1255a979b3ff453d79748f"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":14,"len":4,"rows":10,"Q":["b937ab0b5b49204249309b1e2ab2dc3a5bc696f375694247478f1e4a72059600","b059c47792d6439f336c49b439d85962ecd1bf7264446a0b7f90fc17f9590f06"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":11,"u2":15,"len":4,"rows":10,"Q":["54c4d1878741de7076df2ce25441b35cc9de46d9a9d94049b89d94b164a91ba9","6e7fcbb828ba9c8838b7bc569b4b09577ef1f4ccf3b36a25113daf0ac61cc226"],"shape":"Precompute,Double,AddP12,Double,AddP2,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":11,"u2":16,"len":5,"rows":11,"Q":["377ea19d0cf6f24da011dfd3593173294c7b6e0ea0a0cbcf1a301c5d435cffc8","be73d1bd928cfe3acde5f3098fbf0a3effc7f697c9493540381e7ce33ddbb513"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":12,"u2":1,"len":4,"rows":9,"Q":["bfd24c46b9ef6d17ddceea10ddee3511ee3c6c4f0b13544e844935c95805ede9","4ea702d99b7ad3fabedde65f3b9c0d8593ac8369553b04269e1e94a69a9f5f0c"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":2,"len":4,"rows":9,"Q":["fbf00d5ee166181c97d18c79f9c0a54425362c67eaa190f9b2c8ea828b9b44bd","aedf04353d4248aa59bc88e9bfcc5be1d455600bf7a79c6db3d2cd509916c395"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":12,"u2":3,"len":4,"rows":10,"Q":["cf0ed0cd218ee7a8d0d19b74bbc44ea88ec4a80abca2aff2ee08d7cb229c2aa5","6069bb20f859e84d57b730df196369186f6c078b8703f1ceaaf1cc65ad2b518a"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":4,"len":4,"rows":8,"Q":["09be9719c929e44bda334ae0a923573983e98434715ce5d6a19b264568fce40c","585baef498a5be50d55ace526a3a95a71e6352d1c6162eff9297f12e578c6c39"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,Correction"},{"pair":"R1,R1'","u1":12,"u2":5,"len":4,"rows":9,"Q":["3dd6e56664aa90c4f065d97d8320ffa2e4a6c7907045b75b60def1de7f27b390","22abf0e789c638bcc270a45522dbd115ecde32de5b34988671a3c21ecdb634ba"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":6,"len":4,"rows":9,"Q":["b27ad02045a8c6b12f58983401c5874521d0ef6af8d1e84279c7c0db10468bea","33c01f267ed47a98630ac06b997814ef88bf138f1e3b31746a69f2a6153d4050"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":12,"u2":7,"len":4,"rows":10,"Q":["86174bde15d8107484d79f0b2f047c9a23209cccafde5233f55f0465d53c8b43","ffb742036d1293f8503ac070b116e6b39ae2b9212d130303e938f094da986116"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":8,"len":4,"rows":8,"Q":["7649e4d8e6815caeaac35cb0afae35b1d32ff04e6e1dcc0ea16d752299cca6b6","9ace8bc4f7aa5ba03e98ba40e3d46c3a84da21f86758387477bcb535543310ff"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,Correction"},{"pair":"R1,R1'","u1":12,"u2":9,"len":4,"rows":9,"Q":["ca8eaa02dd55b5977b7851fa4903ccd1de38b5184b5af91e50697a8c5a800f88","819e613cf1ddf5becdc77fba51b18abbf8e687f962db8c7a962a0702b9aaab4d"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":10,"len":4,"rows":9,"Q":["999527cdcfc79dd4843b4e94de7c3100cb16c67b5d21c1098ede5a3fcbe8ba7c","44b7f99fbb227f0fec16058719a41c894921c77316139389004b78ff5e8c5a29"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":12,"u2":11,"len":4,"rows":10,"Q":["ce9fb2c0b532fdc7112dd08bbc1f3d47da4c818d5a0e522e858c5428d4b255b1","6aeea5a4a00f8c3a302ccb09219c9143a6b62cce128498789685b73fb3d7358f"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":12,"len":4,"rows":8,"Q":["14b7adeb23f66f6d07b0c8fcc3740a1ef5e3db5feb11e93fb033a85147c01a94","2ead5b6dbfa41f1c61c1aa3c535465b727a8df7c8ae96c0db69569bfc4f534b0"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,Correction"},{"pair":"R1,R1'","u1":12,"u2":13,"len":4,"rows":9,"Q":["939b0602e3e302f7729d8eadd545c68004adb04d0b6f41cb7c902215cae70a0c","26bcecf1f2a7faf37600121f196105cd50f9772c48d4b5a8c41f1044582941a3"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":14,"len":4,"rows":9,"Q":["ff048a5a635de9bdc69ae7769dbd3cfc33d31b778734c30b4e1d6b8ab0d3dc54","ed1559affca2fd447782abc27c81ef424cfd397eea1c0c7b5dc60e4a2a9963cc"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":12,"u2":15,"len":4,"rows":10,"Q":["b3d2eb8f265110fa01a3b12ccd463ed9ae338021faf7d3ebf233253211216077","63c9951c687ddf5f90a28ec53e8b55df32230dc760c643ed68afdc9707983e22"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":12,"u2":16,"len":5,"rows":10,"Q":["bfd6e370de98f2f389e80834ae50a9aafef4589c09e7f11e04f1fd486f22a00f","18beb48d133eddbdbbd7e852fa00e49005447935b5d20c652664a419ec0f737e"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,Correction"},{"pair":"R1,R1'","u1":13,"u2":1,"len":4,"rows":9,"Q":["8eae37cd34a288b826c0e87c5fe686acb09bb6ae093f527c0723af312b84433d","4edab23aa2b0a7b3aa688f7770269e32d55681ece5fcbd853cf05fd6c1a6f74f"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":2,"len":4,"rows":10,"Q":["8fbe4f8171be5df850061421f4e7a0b0738b9ac071a658807379ed79457e728b","bc68afbddab14c5fcb4ddbb9c64262053490bc1461a05b3022ad49442bd970b5"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":13,"u2":3,"len":4,"rows":10,"Q":["1d4f55f23479c03c501d108950a6c8a92b6ebec7b9eee64616aa5d1e5dcde123","92b9d112197703991c7b6986880e58e1e4e580a32c1a87fc2e2f3e5829c62c7f"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":4,"len":4,"rows":9,"Q":["2a326f1e36dd0d28cf6052c826bef6f1df49b56aa619584e69df5766261c44f6","6b2f841c2d3d0b749cbc97f3a90f3a8f32623b7193043ff93eb7bfa79cf7be47"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":13,"u2":5,"len":4,"rows":9,"Q":["da9299b95ff4ad3dde07f446733458159aec66fc11acb0a71e55b80639485d9d","7e9803ec42170db6f61b1bc754e727ed2829f8dea3f798af0cd2482a69d9ca31"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":6,"len":4,"rows":10,"Q":["dbd95d7b178920d4074ba6020989d73e3b7fb873277dc59fe56bbbdc858e1c00","47cb162b73d2f3a61a1431f8f2b6c403901554dc2cf58053f94c5a69e50fec7e"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":13,"u2":7,"len":4,"rows":10,"Q":["fab88e36d6842989c9c25d5566ad8c7a551d684c9552d2df80f9111afecadd43","f327e0b7eaf9a037da180a97104e3d61a8ea0adb4cfe807d5296763bdf1eb193"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":8,"len":4,"rows":9,"Q":["a5343d37f1626518fbd42d603b491d83c0fa3ceb074d26ab79474676748a2fc3","d0409e54387dc4b29a1f306cd1a1181121e8fb88501cb3419fe2d3081fe33e5d"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":13,"u2":9,"len":4,"rows":9,"Q":["1f564020ac692dbb589527b1b7cae79ca7247ea2c42284e474c93a2e4ab3cb49","22507f1c6a0e735b56505978db06201623b79f0ebc93b29f09022dc74de839ca"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":10,"len":4,"rows":10,"Q":["b58e01b754a03099cdf9457dd6b9b59ae4121ecef5adff9e6f3cbed96aa4f2c4","24206fb93455e5543c456a711fa04674247d19d963871fa8ab734fabdbbd4a93"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":13,"u2":11,"len":4,"rows":10,"Q":["6b6f51fc2012d6cd8a5041938ef2be2c996c12128bafdc5d4cfda6ddbff92848","6c5813af56d10ea4e4712fa32fd904008b34b82b879b0490edbdc6167905962e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":12,"len":4,"rows":9,"Q":["aaa6e6c0b83edf8332c72b3e16dd0bd2dda87452ed366a694f8ea0a020263640","ff0c5096e3789bfe623e8f32034fbf4e37eba03808a10a6307f3879724fc0ab5"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":13,"u2":13,"len":4,"rows":9,"Q":["6035438dfe01c85c41bee7a54612d46707366af8e07aba7a118930f66567a02c","55f806ad2ec1faa88e7bb8e162fce968e9fafdd62bd927d82917f64d6472943e"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":14,"len":4,"rows":10,"Q":["a90d6c3bb200ab5459fd664bb211a27cd119a7205ad5515e5d28c0d62f7e77be","9891c83359b62d0512ea2c40985f5b4a6bf3fd6f0aa3c0247846026796672e75"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":13,"u2":15,"len":4,"rows":10,"Q":["3ad443232e09d51750d344fe6ccbdfc521872e78d1c662ce04eb35c97128c0ec","8c91776d7c23fca333b87ba31e17f10cdb3c3ff3e200ccb9d7e9fc726df2cfa8"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP2,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":13,"u2":16,"len":5,"rows":11,"Q":["5ce32eb5d8b191944d8d9daab0148425b18d3807596e2e8734698e6b181f07b7","64351ea8966e3f703e0a582f23b6398eb77972b498d57dd75f6e19f696f5c3d3"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":14,"u2":1,"len":4,"rows":10,"Q":["0694209636a3d23ec064f085285cacff0ff0955470f0246a1e02bb6c071580d0","560b52c0ac8a7a41ade21f74da9444d92d6f0f27cb78e526b5b092efe32a4a09"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":2,"len":4,"rows":9,"Q":["932ddd560af3b756e2543273f509352730fe14770fb266116c6f52077893c9c2","a9b56772ca7dcd7a1445d9c4eeb1d62c8a8dbad0603e75815ca13904265f4889"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":14,"u2":3,"len":4,"rows":10,"Q":["458b34f4951b0821058a262a6a59e4a32a56b9a11542a9f295619ae0c4fe2055","8809da5c76afbcb7b92b7115d3866ea626fa77feffc6b04a872c673692995f00"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":4,"len":4,"rows":9,"Q":["bbbca574192cf5bb64ff3b142ebfe308756880517408bc6d2af2dea75da58bba","dd1c4b1264a6e5780f58888f42cee20753c9d9f9568af4e9837db2b02af93459"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":14,"u2":5,"len":4,"rows":10,"Q":["88a0619d81702b15231072363b436b7bbea198f4dc28e4374ed5b12a06c4bc71","9ac2338589f34b5c5462e0882902be2e6fe6016087a3d483d4e6426f466630e1"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":6,"len":4,"rows":9,"Q":["45d9d773d1113e4bbe72d5c21bf66cb4a5c3c664b4023551707efb3069905510","d658329c613aa673e8228645225411092ccdb3aef58f7b1c09a9313b008a6d7c"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":14,"u2":7,"len":4,"rows":10,"Q":["aade21cf443c9bf787274ac0825c9a0c27c91b62fbba5b60f899ecd2dc213a7c","b1629949d679d1248fdae4e70641a116272cdef27fad11cd2d173cfdbb3b0c90"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":8,"len":4,"rows":9,"Q":["5646cbea978f14040361b895631c57ee0a22df9e42d45f950fe1171b5797d580","c302bcc1653bc4923c5571137b3a9b896e1d2bcf60528980bd07e8c5c29e0f32"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":14,"u2":9,"len":4,"rows":10,"Q":["91de11c11d4ec26b4f86be6b16a93f703a8023868f4f29f9d17431631cb114be","1c7e870e673a4c3380892f1212ffc6e06cd7d4fc4ce88f8de5db9bc13544b81e"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":10,"len":4,"rows":9,"Q":["95da5ccd91e65b8feab9c51b04ec4a8e7bf88a94347c787e04f0c67300ed73be","4bfb81272ed9b7c36ddbabe78b9ea279a3cf1c07e93437a279b456cc9c3091c0"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":14,"u2":11,"len":4,"rows":10,"Q":["4b87dfc4282e86e583a57a41442b9756545174e5b94c0cb535667053b9566e30","8c2cd76e5cf962074b59d4395e01d9996bd4186a89254b775c04f71eec8890f5"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":12,"len":4,"rows":9,"Q":["7d8c38ce2024c3f46b1fe142b04e8c1a05b8cef0a32c765d48fe42e4646db751","2ef91de2b3c4eae0cf15271f4c5aee61a3d245ca5a6ef15659aa0f4f0e2ae9b7"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":14,"u2":13,"len":4,"rows":10,"Q":["e674ba70cb4ea2da541a5b4c4641fa2ba661de708098bd6296dea74e31f4f9b6","ccd18043d0c04f9073e8d05b7088825b743a1005eda9f17f7b97ebcb952d426a"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":14,"len":4,"rows":9,"Q":["cae7456a720e8bc57fc19a3354be46c3acb43295b95227853136696d7b613be4","f2e071f86cb3d9544f8467346d304a634feb48e8cd62660ca57d0086c4ff4118"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,Correction"},{"pair":"R1,R1'","u1":14,"u2":15,"len":4,"rows":10,"Q":["be6690582a8970ab46f0866331cb88a9be0a61f4ddeea9548f47246dcad82884","95ce4b7542b884eeee87d7ef6d26c5b16d4b9881992ed4bb589a7f0e505045f5"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":14,"u2":16,"len":5,"rows":11,"Q":["3fb2a4289c2e5be9cbb9e3a93196ecb60da9ae0fe0638bd633b9688d8de65b7c","fb70e4df931e743aee6ae1e7d102db5c7acdad15ee9c74ec057870afc7d63d0e"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,Correction"},{"pair":"R1,R1'","u1":15,"u2":1,"len":4,"rows":10,"Q":["9c8cdece722009e4072583cd9c35ce513b9c665498313ce09c1d455fdb306b28","74090032c6b155df1f8394b27a6dccbce898f2df75e6d5f2936943ea40375cb4"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":2,"len":4,"rows":10,"Q":["e4c1b89404c4f774454384c80603133c03689c39c03015c9b4ab83f6b6d54f75","46ca48a891d37a409fa075be065888e32cb37ce9a444a30ca3fe0a72d7bb9583"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":15,"u2":3,"len":4,"rows":10,"Q":["99aa0a36bdc9a71727ee7601da9e3e658840f39d339f531275cb5dc61181701d","0786ac482d5aeadeef855f6ff918fee9e95d36f42aeedd4a3b659704756ab4c3"],"shape":"Precompute,Double,AddP1,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":4,"len":4,"rows":10,"Q":["b637f6ef6c55b86cbe5dd4c97ed1a619850dcd477533f1b4c726a7cc5ce4c455","9d483b96e0793bf99d67c050ff91ac6087bd519f47bcb3a89eeaccaf26d206e9"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":15,"u2":5,"len":4,"rows":10,"Q":["b2fc75b3d4e4c79d6bcf7b42ef1281a9af322b20630e1e26db4e36580173ac61","642f2b129bffd963391f81f84460f1782de318213ddce9ce2b695f7edbf3ee76"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":6,"len":4,"rows":10,"Q":["19b3cadd0af23c412134f2221dac1169b720074d91fb62a9b07f12dfde0d9819","41b1272cd89beaea9e9e9fd2140d4153c8710282d33c35719e35ff48d1c1a014"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":15,"u2":7,"len":4,"rows":10,"Q":["9bd28f08beb41b0379c430eb80622db4a28ef7f7b2cb57f9c4d70807e3f262e0","6679bf9643c515272cb1631ffe59dd1f7a62be96d0d7ef190ed2b6acff7c1914"],"shape":"Precompute,Double,AddP1,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":8,"len":4,"rows":10,"Q":["585bd1c3bf09910afc6eba15dae35e120c7d781d7701bca2a7cbb47a0ff8891c","1f86db6faf5be01586cc6b5ec32c417fdef691547ac663c01111781c60890a90"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":15,"u2":9,"len":4,"rows":10,"Q":["658043772da750e63f20fa71a5048e8ca81dbb4d361c3236aea8a652df72e494","6f424f3525073b7dfa3979879bcaaed64ee29f986d60ed98b0689b34350ee807"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":10,"len":4,"rows":10,"Q":["c39436edbc7e964b4de02005464d67843337b339810c6a36c5a591eaea8afe34","d3af2fb1115b9d5b3865639f7329afa53cf3642866382a11e8f2e103aca38bb2"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":15,"u2":11,"len":4,"rows":10,"Q":["6923806370001f0029d39292faaaccde7eccb56148ae5e608ea9c51a71f44570","afad41852959459346a343dd577d528ce6cf49fe79fdd6d80b305970d262c479"],"shape":"Precompute,Double,AddP12,Double,AddP1,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":12,"len":4,"rows":10,"Q":["32c22ce77d2280b75eebdac30da95a53ac9fc000cc4819c222feee0abbeb403f","8ceee5efd47184060229dd770ee5bf3ccfc840f798d6693a3a7dae562d489073"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":15,"u2":13,"len":4,"rows":10,"Q":["a7604bd5af700ce03dda7b30b7b5f30f08f779b45820968944033b461b281417","6e974fa0e6ed0acd449f2de6a08ab641a4dcb16b7010e392ed5243a1adb8b7a3"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP1,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":14,"len":4,"rows":10,"Q":["16b8f14dbf172c96f5b31a7a279ac9d00430402ed654ca707a7ed1e91bfa31af","6ad3705ef96a1749b41ba8d870b545aa5bea0afb79288aafdc59d099f77d2b73"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":15,"u2":15,"len":4,"rows":10,"Q":["3ba06aecefb78bf3b51f67da8debe87d4a4d4e1e48b473070033dcbe5f226665","d6dd253730189f400df787b4f78f76b651d32d6884b78b3e4bd1891e7d7a8233"],"shape":"Precompute,Double,AddP12,Double,AddP12,Double,AddP12,Double,AddP12,Correction"},{"pair":"R1,R1'","u1":15,"u2":16,"len":5,"rows":12,"Q":["a91e73a4ea47d73bcaf93319087d23c1450c5aea42f692cf9f818a92f24d53f9","cc7eb85c9e1c6bbdd8802cea8b0df442e06c1dc936cab1ed3eef441d592b34b7"],"shape":"Precompute,Double,AddP2,Double,AddP1,Double,AddP1,Double,AddP1,Double,AddP1,Correction"},{"pair":"R1,R1'","u1":16,"u2":1,"len":5,"rows":9,"Q":["9a4c8443bbe3fc8885c6da88a82ec084581ae9ccf0756f1c98300db42db03975","06148e99b9e89b48624cab37dc3903fd449dd0c97684cba49ed2714f6b193b49"],"shape":"Precompute,Double,AddP1,Double,Double,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":2,"len":5,"rows":9,"Q":["d52c3c019cee53c9438e0932b1db1ee2c0f10ae9afe36ff3de17eddaaab7778e","12afe5a2c894e62d8c252ec5422691033254c2e395cb6add12a4b499b6cc73d9"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":16,"u2":3,"len":5,"rows":10,"Q":["a4f11b2c3090b97e2e60e8d3a19ee990c884ed401e24a3a73873712eaf06afac","274084d53390c5a96cc6f103973e5c527fb2f654a0df6336f6e4d733606a0ef9"],"shape":"Precompute,Double,AddP1,Double,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":4,"len":5,"rows":9,"Q":["f02fb53f521aad446d91ceba9051c807d1b4734e82ee2a0fea959b4e1276ab02","17b37bfd50fde901b1f1880f3556b9f6236ea70f6a8449388c2e321f8b482a56"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,Correction"},{"pair":"R1,R1'","u1":16,"u2":5,"len":5,"rows":10,"Q":["23a93293fab8e99f2b8997d4d0778a30a31bd75d2d980c01514c8775c3a4e66c","c9466ba6cc797461e045c810c17f574d35bb733759ed78cd255c810f66e2192f"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":6,"len":5,"rows":10,"Q":["b9d0e22c0cde8b500a3f47470f801b17763b52c9b04db47a7b7430856e3aa014","7bb981215aa0687c4f7128961df3d4af75d0cd92685c8aa6dd450314f0b63ab1"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":16,"u2":7,"len":5,"rows":11,"Q":["be43c05ae4a60099fa723b2d09481abff2197facbb0b82a04313663e06a3d395","958ed0c276ceeb03e69e7436793d5bd77cee7d42b059f8131522956d93ef2f71"],"shape":"Precompute,Double,AddP1,Double,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":8,"len":5,"rows":9,"Q":["bdadb69386dc68048465f224628f0a192e65ea890c27efc239403a18174a4d3f","ddb2fefb04f7bf5f7f6d9f435494f232f1df1d281ee1696a70e0d55923027bd3"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,Correction"},{"pair":"R1,R1'","u1":16,"u2":9,"len":5,"rows":10,"Q":["1c24696f2abcdf356850b4738537964a915aa1b270e0056ba56c8aa2185bf31f","1d4413b4605ab0c5dee28260973f941cb2ca5cb02e1d7719a015a9ddb219536d"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":10,"len":5,"rows":10,"Q":["1c7c8592c5ff41342d91e942c24f07603f28aec5bd4ce30234d43b51f7f5e797","447842f1677be726ed981e5db8ba246964e7b38942553d9fd2afa38b3c8b0669"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":16,"u2":11,"len":5,"rows":11,"Q":["83fcf76602f76ba50997985e0837d6eadc1a3f1c073613c2e36e0377ae51fb59","4ab5688622bc501831b7f3ffd62e716f778f735937ca91c33828c52f7d429901"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":12,"len":5,"rows":10,"Q":["e7a0a6d861528f3c67b37a9aaf1036abf61828173fb33e4dfc0781c77fc09278","4c5dd371fbbd85ed9b2d6e97885946b73681b7b7895e7751e803e9f888110cd5"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,Correction"},{"pair":"R1,R1'","u1":16,"u2":13,"len":5,"rows":11,"Q":["5e7eec5de8bffe3c36089e04c6ff577b396e3a3303f66378b4d8b3006d0bb0c8","0adaf30da9c22db64fc2447d1e4e25b42c25fbf3f36e9b365a9a11402405a873"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":14,"len":5,"rows":11,"Q":["2196c1219a2a1d6c16dd4a9e8ce0ef8bce39dddff645d19227fa705b4d99330b","91276359dabd64053bb3462fabe9a4a95cc3943ecdb0c6a5c3379d3c002075c7"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,Correction"},{"pair":"R1,R1'","u1":16,"u2":15,"len":5,"rows":12,"Q":["e45d6e40dc8f08060ae7f3b7bc9d7a99d35faf3557506d5fc2e4f983c6f7f266","bb5485347777a9395436c5e72e8ee420ef14a2003e38177195442ee9e269ce03"],"shape":"Precompute,Double,AddP1,Double,AddP2,Double,AddP2,Double,AddP2,Double,AddP2,Correction"},{"pair":"R1,R1'","u1":16,"u2":16,"len":5,"rows":8,"Q":["6e5225d4c2fb61e3356cd8fe37dbf4e39a34c5a7d3e50c6ff8978ed2ffa45a13","fdf4097a24d949c550c755f1ac216d2f5f190bc984bce0bd69900760c60508f4"],"shape":"Precompute,Double,AddP12,Double,Double,Double,Double,Correction"}]} \ No newline at end of file diff --git a/thoughts/ec-recover-opt/oracle/nums_blinding_probe.py b/thoughts/ec-recover-opt/oracle/nums_blinding_probe.py new file mode 100644 index 000000000..dd19f5c3e --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/nums_blinding_probe.py @@ -0,0 +1,179 @@ +"""Probe: is the incomplete-addition edge really closed by the NUMS blind? + +DESIGN.md section 4 introduces the T0 blind and argues: + + "Every intermediate accumulator is 2^j*T0 + (c1*P1 + c2*P2); a collision now + implies a known linear relation on dlog_G(T0) -- i.e. the attacker computes + a discrete log nobody knows." + +This script tests that argument constructively, and it does NOT hold: the +prover chooses P2 (for ecrecover, P2 = lift_x(r) for a signature component `r` +it picks freely), so it can set P2 = mu*T0 for a mu it knows. The collision +equation then has its T0 coefficient cancelled against P2's, and is satisfiable +without knowing dlog_G(T0) at all. + +Concretely, with P1 = G and P2 = mu*T0, the accumulator entering the add at +round r is + + acc = alpha*T0 + beta1*G + beta2*P2 = (alpha + mu*beta2)*T0 + beta1*G + +(alpha, beta1, beta2 are public functions of the schedule and the scalar bits). +Taking u1 < 2^r forces beta1 = e1 = 0, so acc = addend = P2 reduces to the +single scalar equation + + alpha + mu*(beta2 - 1) == 0 (mod N) -> mu = -alpha/(beta2 - 1) + +which is one modular inversion. Cost of the whole construction: one scalar +multiplication. It is CHEAPER than the ~2^-j-probability attack on the +UNBLINDED chain that the blind was introduced to prevent. + +On such a row the chip's lambda relation reads lambda*(xB - xA) + yA - yB = 0 +with xA = xB and yA = yB: it degenerates to 0 = 0, lambda is unconstrained, and +the row's xR/yR become a free one-parameter family. That is a soundness break +(the chip proves Q = u1*P1 + u2*P2 for a Q that is not), independent of how far +an attacker can then steer Q. + +Note the honest path is fine: `ecsm::lincomb2_witness` and the Python reference +both detect the collision and report `ResultInfinity` -> status != 0 -> the +guest's software fallback. The hole is on the malicious-prover side, where the +row is hand-crafted rather than generated. + +Run: /bin/python nums_blinding_probe.py +""" + +from ec_ref import GX, GY, N, P, pt_add, pt_double, recover_even_y, scalar_mul +import lincomb2_ref + +T0, _T0_COUNTER = lincomb2_ref.t0_ref() +G = (GX, GY) + + +def chain_coeffs(u1, u2, length): + """Track acc = alpha*T0 + beta1*P1 + beta2*P2 through the blinded schedule. + Returns {round: (alpha, beta1, beta2, e1, e2)} captured just BEFORE each add + (i.e. after that round's doubling).""" + alpha, b1, b2 = 1, 0, 0 + pre_add = {} + for r in range(length - 1, -1, -1): + alpha, b1, b2 = 2 * alpha % N, 2 * b1 % N, 2 * b2 % N + e1, e2 = (u1 >> r) & 1, (u2 >> r) & 1 + if e1 or e2: + pre_add[r] = (alpha, b1, b2, e1, e2) + b1, b2 = (b1 + e1) % N, (b2 + e2) % N + return pre_add + + +def solve_mu(length, r_target, u1, u2): + """The mu making the add at `r_target` degenerate, with P1 = G, P2 = mu*T0.""" + assert (u2 >> r_target) & 1 == 1, "target round must have u2's bit set" + assert u2.bit_length() == length + alpha, b1, b2, e1, e2 = chain_coeffs(u1, u2, length)[r_target] + if b1 % N != e1 % N: + return None, f"G-coefficient does not vanish (beta1={b1}, e1={e1})" + denom = (b2 - e2) % N + if denom == 0: + return None, "P2-coefficient denominator is zero" + return (-alpha * pow(denom, N - 2, N)) % N, None + + +def simulate(u1, u2, p1, p2, length): + """Run the real blinded schedule; report the first degenerate add.""" + p12 = pt_add(p1, p2) if p1[0] != p2[0] else None + acc = T0 + for r in range(length - 1, -1, -1): + acc = pt_double(acc) + e1, e2 = (u1 >> r) & 1, (u2 >> r) & 1 + if not (e1 or e2): + continue + addend = p12 if (e1 and e2) else (p1 if e1 else p2) + if acc[0] == addend[0]: + same_y = acc[1] == addend[1] + return r, same_y, acc, addend + acc = pt_add(acc, addend) + return None, None, acc, None + + +def package_ecrecover(u1, u2, p2): + """Back out the (z, v, r, s) an attacker would submit, and check the guest's + own decomposition reproduces (u1, u2) and lifts R back to p2.""" + if p2[0] >= N: + return None # would need the recid >= 2 branch + r = p2[0] + v = p2[1] & 1 + z = (-u1 * r) % N + s = (u2 * r) % N + if not (1 <= s < N and 1 <= r < N): + return None + rinv = pow(r, N - 2, N) + gu1, gu2 = (-(rinv * z)) % N, (rinv * s) % N + ye = recover_even_y(r) + lifted = None if ye is None else (r, ye if v == 0 else (P - ye) % P) + return {"z": z, "v": v, "r": r, "s": s, + "guest_u1": gu1, "guest_u2": gu2, "guest_R": lifted} + + +CASES = [ + # (length, target round, u2) -- u1 is any value < 2^r; 1 is used below + (8, 3, 0b10001000), + (12, 5, 0b100000100000), + (16, 9, 0b1000001000000000), + (32, 17, (1 << 31) | (1 << 17)), + (256, 128, (1 << 255) | (1 << 128)), +] + + +def main(): + print(f"T0 = ({T0[0]:#x}, {T0[1]:#x})") + print() + forging = 0 + for length, r_target, u2 in CASES: + u1 = 1 + mu, why = solve_mu(length, r_target, u1, u2) + if mu is None: + print(f"len={length:4d} r={r_target:4d}: no solution ({why})") + continue + p2 = scalar_mul(mu, T0) + if p2[0] == GX: + print(f"len={length:4d} r={r_target:4d}: P2 = +-G, skipped") + continue + + hit, same_y, acc, addend = simulate(u1, u2, G, p2, length) + kind = ("acc == +addend -> LAMBDA UNCONSTRAINED (forgeable row)" + if same_y else + "acc == -addend -> row unsatisfiable (rejects, not a forgery)") + print(f"len={length:4d} r={r_target:4d} u1={u1} u2={u2:#x}") + print(f" mu = {mu:#x}") + print(f" P2 = mu*T0 = ({p2[0]:#x},") + print(f" {p2[1]:#x})") + print(f" degenerate add at round {hit} (target {r_target}): {kind}") + print(f" acc == addend as points: {acc == addend}") + + # the honest generator's verdict on the same input + try: + lincomb2_ref.lincomb2_rows(u1, G, u2, p2, T0) + print(" honest reference: ACCEPTED (unexpected!)") + except ValueError as e: + print(f" honest reference: rejects with {e} -> status != 0 -> guest fallback") + + pkg = package_ecrecover(u1, u2, p2) + if pkg: + print(f" ecrecover packaging: z={pkg['z']:#x}") + print(f" r={pkg['r']:#x}") + print(f" s={pkg['s']:#x} v={pkg['v']}") + print(f" guest recomputes u1: {pkg['guest_u1'] == u1} " + f"u2: {pkg['guest_u2'] == u2} lifts R == P2: {pkg['guest_R'] == p2}") + print() + if hit == r_target and same_y: + forging += 1 + + print(f"forgeable (lambda-free) degenerate adds constructed: {forging}/{len(CASES)}") + print() + print("READING: the NUMS blind does NOT close the incomplete-addition edge when") + print("P2 is prover-chosen. The named dlog assumption on T0 is NECESSARY but not") + print("SUFFICIENT; an explicit non-degeneracy check on add rows (or an equivalent)") + print("is required. See ../lincomb2/FINDING-nums-blinding.log.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/thoughts/ec-recover-opt/oracle/repo-harness/Cargo.lock b/thoughts/ec-recover-opt/oracle/repo-harness/Cargo.lock new file mode 100644 index 000000000..7620d8131 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/repo-harness/Cargo.lock @@ -0,0 +1,196 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "ecsm" +version = "0.1.0" +dependencies = [ + "k256", + "num-bigint", + "num-traits", +] + +[[package]] +name = "ecsm-oracle-harness" +version = "0.1.0" +dependencies = [ + "ecsm", + "num-bigint", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "ff", + "generic-array", + "group", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "elliptic-curve", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "subtle", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" diff --git a/thoughts/ec-recover-opt/oracle/repo-harness/Cargo.toml b/thoughts/ec-recover-opt/oracle/repo-harness/Cargo.toml new file mode 100644 index 000000000..35af4b1d7 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/repo-harness/Cargo.toml @@ -0,0 +1,14 @@ +# Standalone: keep out of the lambda_vm workspace (this copy lives in thoughts/). +[workspace] + +[package] +name = "ecsm-oracle-harness" +version = "0.1.0" +edition = "2021" + +[dependencies] +ecsm = { path = "/Users/maurofab/workspace/lambda_vm/crypto/ecsm" } +num-bigint = "0.4.6" + +[profile.release] +debug = false diff --git a/thoughts/ec-recover-opt/oracle/repo-harness/src/main.rs b/thoughts/ec-recover-opt/oracle/repo-harness/src/main.rs new file mode 100644 index 000000000..2f434eb92 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/repo-harness/src/main.rs @@ -0,0 +1,291 @@ +//! Line-protocol harness exposing the repo's `ecsm` crate to the Python +//! oracle differential. All values are big-endian hex integers on the wire; +//! conversion to the crate's 32-byte little-endian ABI happens here. +//! +//! Commands (stdin, one per line) -> responses (stdout, one per line unless noted): +//! mul -> ok | err +//! recovery -> y | none +//! replay -> steps +//! then n lines: step +//! (rejects via prepare-equivalent checks first: err ) +//! lincomb2 +//! -> lincomb2_json {...} | err +//! Full `Lincomb2Witness` summary: Q, len, P12, the +//! canonicalization witnesses, and every joint row +//! (sel/round/op/d1/d2/a/addend/lambda/r). Consumed by +//! the phase-D0 Python differential. + +use ecsm::witness::{dinv_witness, lincomb2_witness, JointSel}; +use ecsm::{ + compute_witness, recover_y_canonical, replay_double_and_add, scalar_mul_x, AffinePoint, + EcsmError, +}; +use num_bigint::BigUint; +use std::io::{BufRead, Write}; + +fn bytes_hex(b: &[u8]) -> String { + b.iter().map(|x| format!("{x:02x}")).collect() +} + +fn i64s_json(c: &[i64]) -> String { + let items: Vec = c.iter().map(|x| x.to_string()).collect(); + format!("[{}]", items.join(",")) +} + +fn hex_to_le32(h: &str) -> [u8; 32] { + let v = BigUint::parse_bytes(h.as_bytes(), 16).expect("bad hex"); + let mut bytes = v.to_bytes_le(); + assert!(bytes.len() <= 32, "value exceeds 256 bits"); + bytes.resize(32, 0); + let mut out = [0u8; 32]; + out.copy_from_slice(&bytes); + out +} + +fn hex_to_big(h: &str) -> BigUint { + BigUint::parse_bytes(h.as_bytes(), 16).expect("bad hex") +} + +fn hx(v: &BigUint) -> String { + v.to_str_radix(16) +} + +/// 32 LE bytes -> big-endian hex integer, so the Python side can compare against +/// plain ints without knowing the ABI byte order. +fn le_hex(b: &[u8; 32]) -> String { + hx(&BigUint::from_bytes_le(b)) +} + +fn sel_name(s: &JointSel) -> &'static str { + match s { + JointSel::Double => "Double", + JointSel::AddP1 => "AddP1", + JointSel::AddP2 => "AddP2", + JointSel::AddP12 => "AddP12", + JointSel::Precompute => "Precompute", + JointSel::Correction => "Correction", + } +} + +fn err_kind(e: &EcsmError) -> &'static str { + match e { + EcsmError::ScalarIsZero => "ScalarIsZero", + EcsmError::ScalarOutOfRange => "ScalarOutOfRange", + EcsmError::NotOnCurve => "NotOnCurve", + EcsmError::CoordinateOutOfRange => "CoordinateOutOfRange", + } +} + +fn main() { + let stdin = std::io::stdin(); + let stdout = std::io::stdout(); + let mut out = std::io::BufWriter::new(stdout.lock()); + + for line in stdin.lock().lines() { + let line = line.unwrap(); + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.is_empty() { + continue; + } + match parts[0] { + "mul" => { + let x = hex_to_le32(parts[1]); + let k = hex_to_le32(parts[2]); + match scalar_mul_x(&k, &x) { + Ok(xr) => { + let v = BigUint::from_bytes_le(&xr); + writeln!(out, "ok {}", hx(&v)).unwrap(); + } + Err(e) => writeln!(out, "err {}", err_kind(&e)).unwrap(), + } + } + "recovery" => { + let x = hex_to_big(parts[1]); + match recover_y_canonical(&x) { + Some(y) => writeln!(out, "y {}", hx(&y)).unwrap(), + None => writeln!(out, "none").unwrap(), + } + } + "replay" => { + // Mirror `prepare`'s checks through the public API so invalid + // inputs are reported instead of panicking inside k256 glue. + let x = hex_to_big(parts[1]); + let k = hex_to_big(parts[2]); + let n = ecsm::n(); + let p = ecsm::p(); + if k == BigUint::from(0u8) { + writeln!(out, "err ScalarIsZero").unwrap(); + } else if k >= n { + writeln!(out, "err ScalarOutOfRange").unwrap(); + } else if x >= p { + writeln!(out, "err CoordinateOutOfRange").unwrap(); + } else if let Some(y) = recover_y_canonical(&x) { + let g = AffinePoint { x, y }; + let (steps, result) = replay_double_and_add(&k, &g); + writeln!(out, "steps {} {} {}", steps.len(), hx(&result.x), hx(&result.y)) + .unwrap(); + for s in &steps { + writeln!( + out, + "step {} {} {} {} {} {} {} {}", + s.round, + s.op, + s.next_op, + hx(&s.a.x), + hx(&s.a.y), + hx(&s.lambda), + hx(&s.r.x), + hx(&s.r.y) + ) + .unwrap(); + } + } else { + writeln!(out, "err NotOnCurve").unwrap(); + } + } + // witness -> one JSON line with the FULL EcsmWitness + // (byte arrays as LE hex strings, carries as decimal arrays), or err . + // Used by the z3 gate's byte-level positive controls: real prover + // witnesses evaluated against the transcribed constraint model. + "witness" => { + let x = hex_to_le32(parts[1]); + let k = hex_to_le32(parts[2]); + match compute_witness(&k, &x) { + Ok(w) => { + let mut s = String::from("{"); + s += &format!("\"x_g\":\"{}\",", bytes_hex(&w.x_g)); + s += &format!("\"y_g\":\"{}\",", bytes_hex(&w.y_g)); + s += &format!("\"k\":\"{}\",", bytes_hex(&w.k)); + s += &format!("\"x2\":\"{}\",", bytes_hex(&w.x2)); + s += &format!("\"q0\":\"{}\",", bytes_hex(&w.q0)); + s += &format!("\"c0\":{},", i64s_json(&w.c0)); + s += &format!("\"q1\":\"{}\",", bytes_hex(&w.q1)); + s += &format!("\"c1\":{},", i64s_json(&w.c1)); + s += &format!("\"x_g_sub_p\":\"{}\",", bytes_hex(&w.x_g_sub_p)); + s += &format!("\"k_sub_n\":\"{}\",", bytes_hex(&w.k_sub_n)); + s += &format!("\"x_r_sub_p\":\"{}\",", bytes_hex(&w.x_r_sub_p)); + s += &format!("\"len_k\":{},", w.len_k); + s += &format!("\"x_r\":\"{}\",", bytes_hex(&w.x_r)); + s += &format!("\"y_r\":\"{}\",", bytes_hex(&w.y_r)); + s += "\"steps\":["; + let step_objs: Vec = w + .steps + .iter() + .map(|st| { + format!( + "{{\"x_a\":\"{}\",\"y_a\":\"{}\",\"x_g\":\"{}\",\"y_g\":\"{}\",\ + \"round\":{},\"op\":{},\"next_op\":{},\"lambda\":\"{}\",\ + \"x_r\":\"{}\",\"y_r\":\"{}\",\"q0\":\"{}\",\"q1\":\"{}\",\ + \"q2\":\"{}\",\"c0\":{},\"c1\":{},\"c2\":{}}}", + bytes_hex(&st.x_a), + bytes_hex(&st.y_a), + bytes_hex(&st.x_g), + bytes_hex(&st.y_g), + st.round, + st.op, + st.next_op, + bytes_hex(&st.lambda), + bytes_hex(&st.x_r), + bytes_hex(&st.y_r), + bytes_hex(&st.q0), + bytes_hex(&st.q1), + bytes_hex(&st.q2), + i64s_json(&st.c0), + i64s_json(&st.c1), + i64s_json(&st.c2) + ) + }) + .collect(); + s += &step_objs.join(","); + s += "]}"; + writeln!(out, "witness_json {s}").unwrap(); + } + Err(e) => writeln!(out, "err {}", err_kind(&e)).unwrap(), + } + } + // lincomb2 : the phase-A joint-chain + // witness, dumped for the Python differential (Q, len, P12, the + // canonicalization witnesses, and the full row schedule). + "lincomb2" => { + let u1 = hex_to_le32(parts[1]); + let u2 = hex_to_le32(parts[2]); + let p1 = AffinePoint { + x: hex_to_big(parts[3]), + y: hex_to_big(parts[4]), + }; + let p2 = AffinePoint { + x: hex_to_big(parts[5]), + y: hex_to_big(parts[6]), + }; + match lincomb2_witness(&u1, &u2, &p1, &p2) { + Ok(w) => { + let mut s = String::from("{"); + s += &format!("\"len\":{},", w.len); + s += &format!("\"x_q\":\"{}\",", le_hex(&w.x_q)); + s += &format!("\"y_q\":\"{}\",", le_hex(&w.y_q)); + s += &format!("\"x_p12\":\"{}\",", le_hex(&w.x_p12)); + s += &format!("\"y_p12\":\"{}\",", le_hex(&w.y_p12)); + s += &format!("\"x_t0\":\"{}\",", le_hex(&w.x_t0)); + s += &format!("\"y_t0\":\"{}\",", le_hex(&w.y_t0)); + s += &format!("\"x_t0_pow\":\"{}\",", le_hex(&w.x_t0_pow)); + s += &format!("\"y_t0_pow\":\"{}\",", le_hex(&w.y_t0_pow)); + s += &format!("\"y_p2_sub_p\":\"{}\",", le_hex(&w.y_p2_sub_p)); + s += &format!("\"x_q_sub_p\":\"{}\",", le_hex(&w.x_q_sub_p)); + s += &format!("\"y_q_sub_p\":\"{}\",", le_hex(&w.y_q_sub_p)); + s += &format!("\"u1_sub_n\":\"{}\",", le_hex(&w.u1_sub_n)); + s += &format!("\"u2_sub_n\":\"{}\",", le_hex(&w.u2_sub_n)); + s += "\"rows\":["; + let rows: Vec = w + .steps + .iter() + .map(|js| { + let st = &js.step; + // The prover's OWN non-degeneracy columns, now + // that `dinv_witness` lives in `crypto/ecsm`. + let dw = dinv_witness(js); + format!( + "{{\"sel\":\"{}\",\"round\":{},\"op\":{},\"d1\":{},\"d2\":{},\ + \"nb\":{},\"next_op\":{},\ + \"x_a\":\"{}\",\"y_a\":\"{}\",\"x_b\":\"{}\",\"y_b\":\"{}\",\ + \"q0\":\"{}\",\"q1\":\"{}\",\"q2\":\"{}\",\ + \"c0\":{},\"c1\":{},\"c2\":{},\ + \"d_inv\":\"{}\",\"q3\":\"{}\",\"c3\":{},\ + \"lambda\":\"{}\",\"x_r\":\"{}\",\"y_r\":\"{}\"}}", + sel_name(&js.sel), + st.round, + st.op, + js.d1, + js.d2, + js.nb, + st.next_op, + le_hex(&st.x_a), + le_hex(&st.y_a), + le_hex(&st.x_g), + le_hex(&st.y_g), + bytes_hex(&st.q0), + bytes_hex(&st.q1), + bytes_hex(&st.q2), + i64s_json(&st.c0), + i64s_json(&st.c1), + i64s_json(&st.c2), + bytes_hex(&dw.d_inv), + bytes_hex(&dw.q3), + i64s_json(&dw.c3), + le_hex(&st.lambda), + le_hex(&st.x_r), + le_hex(&st.y_r) + ) + }) + .collect(); + s += &rows.join(","); + s += "]}"; + writeln!(out, "lincomb2_json {s}").unwrap(); + } + Err(e) => writeln!(out, "err {e:?}").unwrap(), + } + } + other => panic!("unknown command {other}"), + } + out.flush().unwrap(); + } +} diff --git a/thoughts/ec-recover-opt/oracle/vectors.json b/thoughts/ec-recover-opt/oracle/vectors.json new file mode 100644 index 000000000..fab388d99 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/vectors.json @@ -0,0 +1,485 @@ +{ + "curve": "secp256k1", + "function": "xr = x(k*P), P=(x, even y)", + "abi": "32-byte little-endian x, k, xr; errors trap the VM", + "generated": "2026-07-24 ec-oracle", + "vectors": [ + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "1", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0100000000000000000000000000000000000000000000000000000000000000", + "why": "k=1 echo: no steps, xr == xG", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "2", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0200000000000000000000000000000000000000000000000000000000000000", + "why": "k=2: single double row", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "3", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0300000000000000000000000000000000000000000000000000000000000000", + "why": "k=3: double+add, minimal add path", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "404136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff", + "why": "k=N-1: x((N-1)P) == x(P) since (N-1)P = -P", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "3f4136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff", + "why": "k=N-2", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "2", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0200000000000000000000000000000000000000000000000000000000000000", + "why": "k=2^1: all-double schedule, len_k=1", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "1", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0100000000000000000000000000000000000000000000000000000000000000", + "why": "k=2^1-1: double+add every row", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "100", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0001000000000000000000000000000000000000000000000000000000000000", + "why": "k=2^8: all-double schedule, len_k=8", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "ff", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "ff00000000000000000000000000000000000000000000000000000000000000", + "why": "k=2^8-1: double+add every row", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "10000000000000000", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0000000000000000010000000000000000000000000000000000000000000000", + "why": "k=2^64: all-double schedule, len_k=64", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "ffffffffffffffff", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "ffffffffffffffff000000000000000000000000000000000000000000000000", + "why": "k=2^64-1: double+add every row", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "30de2c8bc2010aaebbb647c5bac00eb8028f78d795f2cd4532bc6c504c0e01e7" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "100000000000000000000000000000000", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0000000000000000000000000000000001000000000000000000000000000000", + "why": "k=2^128: all-double schedule, len_k=128", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "ffffffffffffffffffffffffffffffff", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "ffffffffffffffffffffffffffffffff00000000000000000000000000000000", + "why": "k=2^128-1: double+add every row", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "6c034fd8cc8bd548e12569b630710400e6c24a05d9d6b32f08522a241e936da8" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "8000000000000000000000000000000000000000000000000000000000000000", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0000000000000000000000000000000000000000000000000000000000000080", + "why": "k=2^255: all-double schedule, len_k=255", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "b23790a42be63e1b251ad6c94fdef07271ec0aada31db6c3e8bd32043f8be384" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "why": "k=2^255-1: double+add every row", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "370ebfed473178159fd08c3f7bc07e12301792fbd251554a80298efc666c651d" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "why": "alternating 10 bits", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "5555555555555555555555555555555555555555555555555555555555555555", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "5555555555555555555555555555555555555555555555555555555555555555", + "why": "alternating 01 bits", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "9ac20335eb38768d2052be1dbbc3c8f6178407458e51e6b4ad22f1d91758895b" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "100000000000000000000000000000000000000000000000001", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "0100000000000000000000000000000000000000000000000001000000000000", + "why": "long zero run between MSB and LSB", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "c69d568d6bcb64d6c392763aba2c2b6558f5271552aa6002757e9e3c5a45f27c" + }, + { + "x": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "k": "ffffffffffffff0000000000000000000000000", + "x_le": "9817f8165b81f259d928ce2ddbfc9b02070b87ce9562a055acbbdcf97e66be79", + "k_le": "000000000000000000000000f0ffffffffffff0f000000000000000000000000", + "why": "long one-run mid-scalar", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "979e6659a8eb11cee5a4210c56ace999d6ed86b32c0380e53f9f5ca444ba0a22" + }, + { + "x": "7a60d95a27dcb38933a41c23741b45928b4ed8bf674624a5f04137c658ea36e1", + "k": "32cc04af2f217a3d010e4c356d2586554ed9c64fa9d8583bea536c4dba315e9b", + "x_le": "e136ea58c63741f0a5244667bfd84e8b92451b74231ca43389b3dc275ad9607a", + "k_le": "9b5e31ba4d6c53ea3b58d8a94fc6d94e5586256d354c0e013d7a212faf04cc32", + "why": "random point/scalar #0", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "51dfa02163b90b0dd6592f380e7649cf6d167242d72c89854466344def2270c8" + }, + { + "x": "60c53166cb9ad75624b62a6d930918166d5e7a0cf7c13920f6bebaa7aa5ac917", + "k": "3c59b28b71f3157ad0fb9e94e79dbec8f06d909c7f9a2950853598a32a7c421a", + "x_le": "17c95aaaa7babef62039c1f70c7a5e6d161809936d2ab62456d79acb6631c560", + "k_le": "1a427c2aa398358550299a7f9c906df0c8be9de7949efbd07a15f3718bb2593c", + "why": "random point/scalar #1", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "a96ae772b4792399da09513f2651a58e783a4df7d3765ffffd24d40ba62edb48" + }, + { + "x": "3409defbe13fd315bc1287dc854b447e02ab102bb964e3cea9a93a52620140db", + "k": "9bbaf03490ca9c86eb617203230f9eb4ae302952a148a680b3c983c1cfe9af7b", + "x_le": "db400162523aa9a9cee364b92b10ab027e444b85dc8712bc15d33fe1fbde0934", + "k_le": "7bafe9cfc183c9b380a648a1522930aeb49e0f23037261eb869cca9034f0ba9b", + "why": "random point/scalar #2", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "85ff034e1e3650b06511ba15c60ec590ede4cd390fddad39da72763c23ecc224" + }, + { + "x": "846e98d35f91cbc50b1d6b7e17db9cbd5c65ecf273ca5ff139d9031bf0ee4222", + "k": "effb2d161dd796f854305316cefda045406f614ac05a1e7fa307a0a41334ba28", + "x_le": "2242eef01b03d939f15fca73f2ec655cbd9cdb177e6b1d0bc5cb915fd3986e84", + "k_le": "28ba3413a4a007a37f1e5ac04a616f4045a0fdce16533054f896d71d162dfbef", + "why": "random point/scalar #3", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "74aab8020f2038822eac58e99ff9b3aed86061ce4cd9b0f1f75d45c6af827fc" + }, + { + "x": "23df6b981817cf377df8bc9bcc32d80bd6c253dc83d022cf3882be2569d75a95", + "k": "41ac5863a62d10aaed8ace2060ca02a60782aa98c227fa5e5ba9a05705bffb77", + "x_le": "955ad76925be8238cf22d083dc53c2d60bd832cc9bbcf87d37cf1718986bdf23", + "k_le": "77fbbf0557a0a95b5efa27c298aa8207a602ca6020ce8aedaa102da66358ac41", + "why": "random point/scalar #4", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "5165a0f3969483d8169435e81dce7d6afd78effa8c7dfb7b8d4070dbb1eceaef" + }, + { + "x": "690b2032442bdb1b65743e6cda52fb87539b06bc3e1d626bbf408d3cbff181c", + "k": "f416e69b49d53b69b45767fc519904b0d12e35951fad3cf61fc564cb3bd40b31", + "x_le": "1c18ffcbd308f4bb26d6e1c36bb03975b82fa5cde64357b6b1bd422403b29006", + "k_le": "310bd43bcb64c51ff63cad1f95352ed1b0049951fc6757b4693bd5499be616f4", + "why": "random point/scalar #5", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "21e11dbb4c51be21ceb111dc51fc4c8c6a54dc55566877b23596895e76e3ae86" + }, + { + "x": "682e8eb26d5fdd56f225d55cab3e5d3bac52213644d3766a0448eada7e522070", + "k": "d9367405563873a8ade9d6469c97360382020ab29b92d2a88711087103e1a5b1", + "x_le": "7020527edaea48046a76d344362152ac3b5d3eab5cd525f256dd5f6db28e2e68", + "k_le": "b1a5e10371081187a8d2929bb20a02820336979c46d6e9ada8733856057436d9", + "why": "random point/scalar #6", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "64f1da1d35dbad282279bb7f4428f7fbb194fbf698a21d6f121e93488a60cd84" + }, + { + "x": "f5fcbe24ae9b156313b2785e0f0c937e9be9994d12e87bc13ab18ee7a2e4bf5f", + "k": "23971b85de20df8922bda6f4d30907f36c222f0eaaac9d1451170769ede8217d", + "x_le": "5fbfe4a2e78eb13ac17be8124d99e99b7e930c0f5e78b21363159bae24befcf5", + "k_le": "7d21e8ed69071751149dacaa0e2f226cf30709d3f4a6bd2289df20de851b9723", + "why": "random point/scalar #7", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "f9f969df7d0e4bebb44dbec4b7bd8f88a3be79899160fa4cf6ccc4f1ee60960e" + }, + { + "x": "4d2b4572f97fd48bdffaff30347d84c7a83d0980d2ddde4ca0a2624b4d24691", + "k": "82a882b2462cf7b38db2033114c5e97d979191e0b0adfca20be076cc5480f136", + "x_le": "9146d2b424260acae4dd2d0d98d0837a4cd84703f3afffbd48fd972f57b4d204", + "k_le": "36f18054cc76e00ba2fcadb0e09191977de9c5143103b28db3f72c46b282a882", + "why": "random point/scalar #8", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "87358b5f491fa7d9b2e8cdd319efe9c94137f920bd59b5e45b43a8f12d1e51be" + }, + { + "x": "8b1558d3dacf081c866f6745dc4f19a52c8bd155730448e619b2fabbf9586b2", + "k": "637e59c42a7c697e2b425d5cae23add5aaf5c189dc3f74f6569eaeee5e452282", + "x_le": "b28695bfab2f9b618e44305715bdc8529af1c45d74f666c881f0ac3d8d55b108", + "k_le": "8222455eeeae9e56f6743fdc89c1f5aad5ad23ae5c5d422b7e697c2ac4597e63", + "why": "random point/scalar #9", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "dedf382579eef1c6184c675298b192992b426b9f87544a64b58a758b1b51182f" + }, + { + "x": "68ea7bc00c8f573696f53cf3d4cae2e1c41eaff6ab914b20c15942ce231eb32b", + "k": "b269fd3fa5494deeac0058eb403f44804996335afe73ae3c348eb1bbb7a6d5d8", + "x_le": "2bb31e23ce4259c1204b91abf6af1ec4e1e2cad4f33cf59636578f0cc07bea68", + "k_le": "d8d5a6b7bbb18e343cae73fe5a33964980443f40eb5800acee4d49a53ffd69b2", + "why": "random point/scalar #10", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "e499d209cd3790cbb2fe99e19105afaf336d2c3454a72b8e6d60e458acd22f7e" + }, + { + "x": "1724d83cbc72c321c1ab6c3b4b6a62aeb5cba41c706828474c6b01dfe40c382d", + "k": "9952ada2c9eb4c5d68882c4b9f08e1d976199be7d07081eec9c5da3d448ee61b", + "x_le": "2d380ce4df016b4c472868701ca4cbb5ae626a4b3b6cabc121c372bc3cd82417", + "k_le": "1be68e443ddac5c9ee8170d0e79b1976d9e1089f4b2c88685d4cebc9a2ad5299", + "why": "random point/scalar #11", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "45a236826b4c4893e7ed6512eec9e8ff7ce126ec4d15d31438183565fb90f496" + }, + { + "x": "5fec7c9494a01a0a8f8ab7a27c2cf3b38443a1c01ad435c648f8b2558298279c", + "k": "c9351a6f88538c80fd693667b1a1de5ab684a19abfe6649e4055eb1e0d836f4a", + "x_le": "9c27988255b2f848c635d41ac0a14384b3f32c7ca2b78a8f0a1aa094947cec5f", + "k_le": "4a6f830d1eeb55409e64e6bf9aa184b65adea1b1673669fd808c53886f1a35c9", + "why": "random point/scalar #12", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "841f93b863bee1f50ff0d0027d80bbc5e89beaecd493a305848f7c7d602d89a4" + }, + { + "x": "b3f5486dda9cc9dbbc462f138835eeb5791c54d643356a7163d154d5dfe04732", + "k": "ca5e23d3b250ff05ece9ca5e3297e14b4587d32bbed501064eca7becff29702c", + "x_le": "3247e0dfd554d163716a3543d6541c79b5ee3588132f46bcdbc99cda6d48f5b3", + "k_le": "2c7029ffec7bca4e0601d5be2bd387454be197325ecae9ec05ff50b2d3235eca", + "why": "random point/scalar #13", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "d4a3c334248a6dbf82264f5d53c675fa8ca61031017fab80cd6a235bfe18cd7c" + }, + { + "x": "f02aac9ace9dc236871e3551169cf59a1ab90fd1466c117b7a2146c6b07b51f2", + "k": "8dcff9ed906d027a4ee14cd96b6dc7bd7ef82fcc0a335e1ba0ed90fa6bc2c5be", + "x_le": "f2517bb0c646217a7b116c46d10fb91a9af59c1651351e8736c29dce9aac2af0", + "k_le": "bec5c26bfa90eda01b5e330acc2ff87ebdc76d6bd94ce14e7a026d90edf9cf8d", + "why": "random point/scalar #14", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "f933d27801ae2be6cd642910ffc79fff2c93149f94a0e5796cb8abbb73f610f0" + }, + { + "x": "baa5278d6b777ab7b19fbf8e57b054c004502113e793cade68affcbed126c5cd", + "k": "d9ed927601db147cd5473f2293d053e672aab117e8bb20196ca300149e653830", + "x_le": "cdc526d1befcaf68deca93e713215004c054b0578ebf9fb1b77a776b8d27a5ba", + "k_le": "3038659e1400a36c1920bbe817b1aa72e653d093223f47d57c14db017692edd9", + "why": "random point/scalar #15", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "2f099908dd354a435f969834be9a20a285e0dffecc8cfc3872d876b70a7d97af" + }, + { + "x": "cdf25f073dc26e33dd753a47c93574ae5cc330ac63d8fcfb14979991e4dfacdd", + "k": "b9083db5c148de457289a45852112e1f7abc830e81dc414fd7d0d578c1dbb131", + "x_le": "ddacdfe491999714fbfcd863ac30c35cae7435c9473a75dd336ec23d075ff2cd", + "k_le": "31b1dbc178d5d0d74f41dc810e83bc7a1f2e115258a4897245de48c1b53d08b9", + "why": "random point/scalar #16", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "40c7ca8f479a5bf54e4fd4e2deac71828ec858ba8a2c5e6f26f83370cf8a2c22" + }, + { + "x": "86488a2513ad8dddfc28efbf73b66c0a19b521917a12d2ee81cc65959e62d9ad", + "k": "8a4bc60a3d5df42683d45a166992fcaba4652d0b91de695880cd8bbde18ead2f", + "x_le": "add9629e9565cc81eed2127a9121b5190a6cb673bfef28fcdd8dad13258a4886", + "k_le": "2fad8ee1bd8bcd805869de910b2d65a4abfc9269165ad48326f45d3d0ac64b8a", + "why": "random point/scalar #17", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "26a8ea265c5514f887c30830e19a86f8e19a5bde029ebcf2efc09bac3b4e1f93" + }, + { + "x": "96f0d865e8d6901735f93613531449dcfb78b16b6ffde31b4f363f65ea454819", + "k": "1cd2a40cb09f2e358184a1b78e991415705ff7f1b3c7cba99533c33ad43062a1", + "x_le": "194845ea653f364f1be3fd6f6bb178fbdc4914531336f9351790d6e865d8f096", + "k_le": "a16230d43ac33395a9cbc7b3f1f75f701514998eb7a18481352e9fb00ca4d21c", + "why": "random point/scalar #18", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "50c6b35d4ca58ef0e96351914585f2faf3998b8c00501cc88945af43a9a5b9c9" + }, + { + "x": "b97be82dea0e66b07f5eb675a72edeb48459fb5abaa9356ee1284ff5e569c803", + "k": "aedd6097676ba378e632ad3d171acc995278c0bd6f4956ef18b8ec08eafef4b2", + "x_le": "03c869e5f54f28e16e35a9ba5afb5984b4de2ea775b65e7fb0660eea2de87bb9", + "k_le": "b2f4feea08ecb818ef56496fbdc0785299cc1a173dad32e678a36b679760ddae", + "why": "random point/scalar #19", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "5fb934cc64a2e1f04acac68dac00e4795bc8c83daba99536bb4b27ed00c0f94d" + }, + { + "x": "6da54313c2f25ba2a6ad1d159ceaaa7b86b80b67e414372f4239568af7e0a1c4", + "k": "1", + "x_le": "c4a1e0f78a5639422f3714e4670bb8867baaea9c151dada6a25bf2c21343a56d", + "k_le": "0100000000000000000000000000000000000000000000000000000000000000", + "why": "edge scalar on random point", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "6da54313c2f25ba2a6ad1d159ceaaa7b86b80b67e414372f4239568af7e0a1c4" + }, + { + "x": "6da54313c2f25ba2a6ad1d159ceaaa7b86b80b67e414372f4239568af7e0a1c4", + "k": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "x_le": "c4a1e0f78a5639422f3714e4670bb8867baaea9c151dada6a25bf2c21343a56d", + "k_le": "404136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff", + "why": "edge scalar on random point", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "6da54313c2f25ba2a6ad1d159ceaaa7b86b80b67e414372f4239568af7e0a1c4" + }, + { + "x": "6da54313c2f25ba2a6ad1d159ceaaa7b86b80b67e414372f4239568af7e0a1c4", + "k": "8000000000000000000000000000000000000000000000000000000000000000", + "x_le": "c4a1e0f78a5639422f3714e4670bb8867baaea9c151dada6a25bf2c21343a56d", + "k_le": "0000000000000000000000000000000000000000000000000000000000000080", + "why": "edge scalar on random point", + "provenance": "oracle(ec_ref) anchored A/B/C", + "xr": "5df9b730ca44dc8a96abbb31859d187016e7dfee06ba3ad37eb7f10f722711ed" + }, + { + "x": "585633d29ac84e5c3fab61d4c6c4e90b92fa93c3bf7fc51e311d95d9e4662633", + "k": "0", + "x_le": "332666e4d9951d311ec57fbfc393fa920be9c4c6d461ab3f5c4ec89ad2335658", + "k_le": "0000000000000000000000000000000000000000000000000000000000000000", + "why": "k=0 -> ScalarIsZero", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "ScalarIsZero" + }, + { + "x": "585633d29ac84e5c3fab61d4c6c4e90b92fa93c3bf7fc51e311d95d9e4662633", + "k": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "x_le": "332666e4d9951d311ec57fbfc393fa920be9c4c6d461ab3f5c4ec89ad2335658", + "k_le": "414136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff", + "why": "k=N -> ScalarOutOfRange", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "ScalarOutOfRange" + }, + { + "x": "585633d29ac84e5c3fab61d4c6c4e90b92fa93c3bf7fc51e311d95d9e4662633", + "k": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", + "x_le": "332666e4d9951d311ec57fbfc393fa920be9c4c6d461ab3f5c4ec89ad2335658", + "k_le": "424136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff", + "why": "k=N+1 -> ScalarOutOfRange", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "ScalarOutOfRange" + }, + { + "x": "585633d29ac84e5c3fab61d4c6c4e90b92fa93c3bf7fc51e311d95d9e4662633", + "k": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "x_le": "332666e4d9951d311ec57fbfc393fa920be9c4c6d461ab3f5c4ec89ad2335658", + "k_le": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "why": "k=2^256-1 -> ScalarOutOfRange", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "ScalarOutOfRange" + }, + { + "x": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "k": "5", + "x_le": "2ffcfffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "k_le": "0500000000000000000000000000000000000000000000000000000000000000", + "why": "x=p -> CoordinateOutOfRange", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "CoordinateOutOfRange" + }, + { + "x": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + "k": "5", + "x_le": "30fcfffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "k_le": "0500000000000000000000000000000000000000000000000000000000000000", + "why": "x=p+1 -> CoordinateOutOfRange", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "CoordinateOutOfRange" + }, + { + "x": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "k": "5", + "x_le": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "k_le": "0500000000000000000000000000000000000000000000000000000000000000", + "why": "x=2^256-1 -> CoordinateOutOfRange", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "CoordinateOutOfRange" + }, + { + "x": "203d23e1be4f5921fb267c5422aa440cc991ced5b89f988042ca92be7a2e833e", + "k": "5", + "x_le": "3e832e7abe92ca4280989fb8d5ce91c90c44aa22547c26fb21594fbee1233d20", + "k_le": "0500000000000000000000000000000000000000000000000000000000000000", + "why": "non-residue x -> NotOnCurve", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "NotOnCurve" + }, + { + "x": "54991fac88dc02a0c3d17cb9c4773de3cf1a88a6f059ca760218de2fab613ce5", + "k": "d3406108e972e101de81a695fd08ac5ec8ce765e3b54828370765ceee66e4755", + "x_le": "e53c61ab2fde180276ca59f0a6881acfe33d77c4b97cd1c3a002dc88ac1f9954", + "k_le": "55476ee6ee5c76708382543b5e76cec85eac08fd95a681de01e172e9086140d3", + "why": "non-residue x, random k", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "NotOnCurve" + }, + { + "x": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "k": "0", + "x_le": "2ffcfffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "k_le": "0000000000000000000000000000000000000000000000000000000000000000", + "why": "k=0 beats x=p: ScalarIsZero (order witness)", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "ScalarIsZero" + }, + { + "x": "3895437bfd20d0f6ebfccbde2f2ab411bc0cac12d7e2f3f988ebbfe13c7e9f53", + "k": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "x_le": "539f7e3ce1bfeb88f9f3e2d712ac0cbc11b42a2fdecbfcebf6d020fd7b439538", + "k_le": "414136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffffffffffffffff", + "why": "k=N beats non-residue: ScalarOutOfRange (order witness)", + "provenance": "oracle(ec_ref) anchored A/B/C", + "error": "ScalarOutOfRange" + } + ] +} \ No newline at end of file diff --git a/thoughts/ec-recover-opt/oracle/width_audit.py b/thoughts/ec-recover-opt/oracle/width_audit.py new file mode 100644 index 000000000..f9b343889 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/width_audit.py @@ -0,0 +1,472 @@ +"""Width audit for the lincomb2 joint chain (IMPL-PLAN section 11, risk 8). + +The question. Today's ECDAS proves `A + G` for a loop-invariant, external, +canonical addend `G`. Under lincomb2 the addend varies per row over +{P1, P2, P12, -2^len*T0}, and `P12 = P1 + P2` is an INTERIOR chip output that is +byte-bounded but never proven canonical (< p). Does the convolution +carry/quotient width argument survive that? + +Two questions that must not be conflated, because the answer differs: + + SOUNDNESS -- does the field equation `256*c_i - c_{i-1} - S_i = 0` still + imply the INTEGER equation? That needs |256*c_i - c_{i-1} - S_i| + < p_g so nothing wraps. Computed here as an exact interval over + the constraint system's own guarantees (limbs are bytes, op/mu + are bits, carries sit in their IsHalfword windows), with a + random-corner cross-check and a z3 confirmation on small limbs. + + COMPLETENESS -- can the HONEST prover always find carries inside the windows + and a quotient that is >= 0 and fits 33 bytes? That does depend + on composed values. Measured here on real lincomb2 witnesses, + over every row type including the two that break telescoping. + +Run: /bin/python width_audit.py +""" + +import random +import sys + +import lincomb2_ref +from ec_ref import GX, GY, N, P, recover_even_y, scalar_mul + +# Goldilocks +P_G = (1 << 64) - (1 << 32) + 1 + +# Carry offsets, read from the chips (prover/src/tables/ecdas.rs:24-26, reused +# verbatim by ecdas2.rs:71; ecsm.rs:27-28). +CARRY_OFFSET_LAMBDA = 32636 +CARRY_OFFSET_XR = 8161 +CARRY_OFFSET_YR = 16320 +CARRY_OFFSET_X2 = 8160 +CARRY_OFFSET_YG = 16319 + +P_BYTES = list(P.to_bytes(32, "little")) +R_BYTES = list((3 * P).to_bytes(33, "little")) # r = 3p, the shifted-quotient offset + +BYTE_MAX = 255 +NLIMB = 64 + + +def ext64(byts): + a = [0] * NLIMB + for i, b in enumerate(byts): + a[i] = b + return a + + +PP = ext64(P_BYTES) +RR = ext64(R_BYTES) + + +# ── exact per-limb interval bounds ────────────────────────────────────────── +# +# Every term of S_i is a product of at most two limbs (times a small constant), +# summed over j <= i. Treating repeated variables (lam*lam, xa*xa) as +# independent is an OVER-approximation, which is the safe direction for a +# soundness bound. Terms whose factors are known constants (R, P) are bounded +# exactly rather than by 255. + +def conv_const_bound(consts, i): + """max over byte-valued b of sum_j b[j] * consts[i-j] (and the min, 0).""" + return BYTE_MAX * sum(consts[i - j] for j in range(0, i + 1)) + + +def rq_interval(i): + """Interval of mu*sum_j R[j]*P[i-j] - sum_j q[j]*P[i-j] , + with mu a bit and q byte-valued. R and P are constants.""" + r_p = sum(RR[j] * PP[i - j] for j in range(0, i + 1)) # exact, mu in {0,1} + q_p_max = conv_const_bound(PP, i) # q free bytes + return (-q_p_max, r_p) + + +def s_interval(relation, i): + """Exact interval for S_i, maximised over byte limbs and bit op/mu.""" + n = i + 1 # number of convolution terms + b2 = BYTE_MAX * BYTE_MAX + rq_lo, rq_hi = rq_interval(i) + + if relation == "lambda": + # op = 1 branch: (ya_i - yg_i) + sum_j lam_j*(xg - xa)_{i-j} + # |lam_j| <= 255, |(xg-xa)_{i-j}| <= 255 + op1_lo, op1_hi = -(n * b2 + BYTE_MAX), n * b2 + BYTE_MAX + # op = 0 branch: sum_j 2*lam_j*ya_{i-j} - 3*xa_j*xa_{i-j} + op0_lo, op0_hi = -3 * n * b2, 2 * n * b2 + lo, hi = min(op1_lo, op0_lo), max(op1_hi, op0_hi) + elif relation == "xr": + # sum_j lam_j*lam_{i-j} - xa_i - xg_i - xr_i - (1-op)(xa_i - xg_i) + lo = -3 * BYTE_MAX - BYTE_MAX # the (1-op) term adds at most one more 255 + hi = n * b2 + BYTE_MAX + elif relation == "yr": + # sum_j lam_j*(xa - xr)_{i-j} - ya_i - yr_i + lo, hi = -(n * b2 + 2 * BYTE_MAX), n * b2 + 2 * BYTE_MAX + elif relation == "dinv": + # NEW (closes the NUMS finding): sum_j dinv_j*(xb - xa)_{i-j} - [i==0] + one = 1 if i == 0 else 0 + lo, hi = -(n * b2 + one), n * b2 + else: + raise ValueError(relation) + return lo + rq_lo, hi + rq_hi + + +def carry_window(offset): + """IsHalfword(c + offset) in [0, 2^16) => c in [-offset, 2^16-1-offset].""" + return -offset, (1 << 16) - 1 - offset + + +def soundness_bound(relation, offset): + """max |256*c_i - c_{i-1} - S_i| over everything the constraints allow.""" + c_lo, c_hi = carry_window(offset) + worst = 0 + arg = None + for i in range(NLIMB): + s_lo, s_hi = s_interval(relation, i) + # c_63 is ColIsZero'd, not windowed; c_{-1} is structurally 0. + ci_lo, ci_hi = (0, 0) if i == 63 else (c_lo, c_hi) + cp_lo, cp_hi = (0, 0) if i == 0 else (c_lo, c_hi) + hi = 256 * ci_hi - cp_lo - s_lo + lo = 256 * ci_lo - cp_hi - s_hi + m = max(abs(hi), abs(lo)) + if m > worst: + worst, arg = m, i + return worst, arg + + +# ── honest witnesses: recompute the carries independently ─────────────────── + +def conv(a, b, i): + return sum(a[j] * b[i - j] for j in range(0, i + 1)) + + +def limb_carries(terms): + """c_i = (c_{i-1} + terms_i)/256, asserting exact divisibility and c_63 = 0.""" + c = [] + carry = 0 + for i in range(NLIMB): + s = carry + terms[i] + assert s % 256 == 0, f"limb {i} not divisible by 256" + carry = s // 256 + c.append(carry) + assert c[63] == 0, "closing carry c_63 != 0" + return c + + +def le32(v): + return ext64(list(v.to_bytes(32, "little"))) + + +def le33(v): + return ext64(list(v.to_bytes(33, "little"))) + + +def honest_row_carries(a, addend, r_pt, lam, op): + """The three relations' honest carries and quotients for one row, computed + from the group-law values alone (no Rust involved).""" + xa, ya = le32(a[0]), le32(a[1]) + xg, yg = le32(addend[0]), le32(addend[1]) + xr, yr = le32(r_pt[0]), le32(r_pt[1]) + lm = le32(lam) + out = {} + + # lambda: op*(lam*(xg-xa) + ya - yg) + (1-op)*(2*lam*ya - 3*xa^2) + (r - q0)*p + if op == 1: + v = lam * (addend[0] - a[0]) + a[1] - addend[1] + else: + v = 2 * lam * a[1] - 3 * a[0] * a[0] + q0 = 3 * P + v // P + assert v % P == 0, "lambda numerator not divisible by p" + q0b = le33(q0) + terms = [] + for i in range(NLIMB): + if op == 1: + s = ya[i] - yg[i] + sum(lm[j] * (xg[i - j] - xa[i - j]) for j in range(0, i + 1)) + else: + s = sum(2 * lm[j] * ya[i - j] - 3 * xa[j] * xa[i - j] for j in range(0, i + 1)) + terms.append(s + conv(RR, PP, i) - conv(q0b, PP, i)) + out["lambda"] = (limb_carries(terms), q0) + + # xR: lam^2 - xa - xg - xr - (1-op)(xa - xg) + (r - q1)*p + v = lam * lam - a[0] - addend[0] - r_pt[0] - (0 if op == 1 else (a[0] - addend[0])) + assert v % P == 0, "xR numerator not divisible by p" + q1 = 3 * P + v // P + q1b = le33(q1) + terms = [] + for i in range(NLIMB): + op_term = (xa[i] - xg[i]) if op == 0 else 0 + terms.append(conv(lm, lm, i) - xa[i] - xg[i] - xr[i] - op_term + + conv(RR, PP, i) - conv(q1b, PP, i)) + out["xr"] = (limb_carries(terms), q1) + + # yR: lam*(xa - xr) - ya - yr + (r - q2)*p + v = lam * (a[0] - r_pt[0]) - a[1] - r_pt[1] + assert v % P == 0, "yR numerator not divisible by p" + q2 = 3 * P + v // P + q2b = le33(q2) + terms = [] + for i in range(NLIMB): + cl = sum(lm[j] * (xa[i - j] - xr[i - j]) for j in range(0, i + 1)) + terms.append(cl - ya[i] - yr[i] + conv(RR, PP, i) - conv(q2b, PP, i)) + out["yr"] = (limb_carries(terms), q2) + return out + + +def honest_dinv_carries(a, addend): + """The proposed non-degeneracy relation: d_inv*(xB - xA) - 1 + (r - q3)*p = 0.""" + d = (addend[0] - a[0]) % P + assert d != 0 + dinv = pow(d, P - 2, P) + v = dinv * (addend[0] - a[0]) - 1 + assert v % P == 0, "dinv numerator not divisible by p" + q3 = 3 * P + v // P + assert q3 >= 0 + di, q3b = le32(dinv), le33(q3) + xa, xg = le32(a[0]), le32(addend[0]) + terms = [] + for i in range(NLIMB): + s = sum(di[j] * (xg[i - j] - xa[i - j]) for j in range(0, i + 1)) + if i == 0: + s -= 1 + terms.append(s + conv(RR, PP, i) - conv(q3b, PP, i)) + return limb_carries(terms), q3 + + +def rust_differential(cases, T0, harness="repo-harness/target/release/ecsm-oracle-harness"): + """Cross-check: the carries and quotients this script derives must equal the + ones the real prover witness (`ecsm::lincomb2_witness`) emits. Without this, + Part 3 would only be measuring a reimplementation of the relations.""" + import json + import subprocess + + lines = [f"lincomb2 {u1:x} {u2:x} {p1[0]:x} {p1[1]:x} {p2[0]:x} {p2[1]:x}" + for u1, u2, p1, p2 in cases] + try: + r = subprocess.run([harness], input="\n".join(lines) + "\n", + capture_output=True, text=True, check=True) + except (OSError, subprocess.CalledProcessError) as e: + return None, f"harness unavailable ({e})" + + mismatches = 0 + compared = 0 + for (u1, u2, p1, p2), out in zip(cases, r.stdout.splitlines()): + if not out.startswith("lincomb2_json "): + return None, f"harness rejected a case: {out[:60]}" + w = json.loads(out[len("lincomb2_json "):]) + _q, _len, rows = lincomb2_ref.lincomb2_rows(u1, p1, u2, p2, T0) + for rrow, prow in zip(w["rows"], rows): + mine = honest_row_carries(prow["a"], prow["addend"], prow["r"], + prow["lam"], prow["op"]) + for rel, qkey, ckey in (("lambda", "q0", "c0"), ("xr", "q1", "c1"), + ("yr", "q2", "c2")): + carries, q = mine[rel] + if int.from_bytes(bytes.fromhex(rrow[qkey]), "little") != q: + mismatches += 1 + if rrow[ckey] != carries: + mismatches += 1 + compared += 2 + return (compared, mismatches), None + + +def main(): + rng = random.Random(31337) + T0, _ = lincomb2_ref.t0_ref() + G = (GX, GY) + + print("=" * 78) + print("PART 1 -- SOUNDNESS: does the field equation still imply the integer one?") + print("=" * 78) + print(f"p_g (Goldilocks) = {P_G} ~ 2^{P_G.bit_length() - 1}") + print() + print(f"{'relation':10} {'offset':>7} {'carry window':>22} " + f"{'max |256c - c- - S|':>21} {'vs p_g':>12}") + rels = [("lambda", CARRY_OFFSET_LAMBDA), ("xr", CARRY_OFFSET_XR), + ("yr", CARRY_OFFSET_YR), ("dinv", CARRY_OFFSET_LAMBDA)] + worst_overall = 0 + for rel, off in rels: + w, i = soundness_bound(rel, off) + lo, hi = carry_window(off) + worst_overall = max(worst_overall, w) + print(f"{rel:10} {off:>7} {f'[{lo}, {hi}]':>22} " + f"{w:>21,} {P_G // w:>10,}x") + print() + print(f"worst case over all relations: {worst_overall:,} " + f"~ 2^{worst_overall.bit_length() - 1}, headroom 2^" + f"{(P_G // worst_overall).bit_length() - 1}") + print() + print("These intervals are over-approximations (repeated variables such as") + print("lam*lam and xa*xa are treated as independent), and they are maximised") + print("over BYTE LIMBS ONLY -- no operand is assumed canonical. Restricting") + print("any operand to [0, p) can only shrink them.") + + print() + print("Sensitivity: how large would ONE non-byte limb have to be to break it?") + for name, coeff in [("3*xa_j*xa_{i-j} (lambda, op=0)", 3), ("lam_j*lam_{i-j} (xR)", 1)]: + x = 1 + while coeff * 64 * x * x < P_G: + x *= 2 + print(f" {name:34} breaks at a limb of ~2^{x.bit_length() - 1}") + print(" => byte-ness of EVERY limb is load-bearing, not hygiene.") + + print() + print("=" * 78) + print("PART 2 -- random-corner cross-check of the interval method") + print("=" * 78) + fails = 0 + checked = 0 + for rel, off in rels: + s_lo_all = {} + for i in (0, 1, 7, 31, 62, 63): + lo, hi = s_interval(rel, i) + for _ in range(1500): + # sample limbs at their corners (0 / 255) plus random values + def lim(): + r = rng.random() + return 0 if r < 0.4 else (255 if r < 0.8 else rng.randrange(256)) + lam = [lim() for _ in range(NLIMB)] + xa = [lim() for _ in range(NLIMB)] + xg = [lim() for _ in range(NLIMB)] + ya = [lim() for _ in range(NLIMB)] + yg = [lim() for _ in range(NLIMB)] + xr = [lim() for _ in range(NLIMB)] + yr = [lim() for _ in range(NLIMB)] + q = [lim() for _ in range(NLIMB)] + op = rng.randrange(2) + mu = rng.randrange(2) + if rel == "lambda": + if op == 1: + s = ya[i] - yg[i] + sum(lam[j] * (xg[i - j] - xa[i - j]) + for j in range(i + 1)) + else: + s = sum(2 * lam[j] * ya[i - j] - 3 * xa[j] * xa[i - j] + for j in range(i + 1)) + elif rel == "xr": + s = (sum(lam[j] * lam[i - j] for j in range(i + 1)) + - xa[i] - xg[i] - xr[i] - ((xa[i] - xg[i]) if op == 0 else 0)) + elif rel == "yr": + s = (sum(lam[j] * (xa[i - j] - xr[i - j]) for j in range(i + 1)) + - ya[i] - yr[i]) + else: + s = sum(lam[j] * (xg[i - j] - xa[i - j]) for j in range(i + 1)) + if i == 0: + s -= 1 + s += mu * conv(RR, PP, i) - conv(q, PP, i) + checked += 1 + if not (lo <= s <= hi): + fails += 1 + if fails < 4: + print(f" INTERVAL VIOLATED {rel} i={i}: S={s} not in [{lo}, {hi}]") + s_lo_all[i] = min(s_lo_all.get(i, s), s) + print(f" {checked:,} corner/random samples, {fails} interval violations") + + print() + print("=" * 78) + print("PART 3 -- COMPLETENESS: honest carries on real lincomb2 witnesses") + print("=" * 78) + + stats = {} # relation -> [min c, max c, min q, max q] + per_sel = {} # (sel, relation) -> [min c, max c] + + def record(rel, carries, q, sel): + st = stats.setdefault(rel, [10**9, -10**9, None, None]) + st[0] = min(st[0], min(carries)) + st[1] = max(st[1], max(carries)) + st[2] = q if st[2] is None else min(st[2], q) + st[3] = q if st[3] is None else max(st[3], q) + ps = per_sel.setdefault((sel, rel), [10**9, -10**9]) + ps[0] = min(ps[0], min(carries)) + ps[1] = max(ps[1], max(carries)) + + cases = [] + for _ in range(12): + while True: + x = rng.randrange(P) + y = recover_even_y(x) + if y is not None: + break + p2 = (x, (P - y) % P if rng.random() < 0.5 else y) + cases.append((rng.randrange(1, N), rng.randrange(1, N), G, p2)) + # edges: maximal scalars, and a P2 with tiny/huge coordinates + cases.append((N - 1, N - 1, G, scalar_mul(7, G))) + cases.append((1, 1, G, scalar_mul(3, G))) + cases.append((2**255, 2**255 - 1, G, scalar_mul(5, G))) + + res, err = rust_differential(cases, T0) + if err: + print(f" [!] Rust differential SKIPPED: {err}") + print(" Part 3 then measures this script's own reimplementation only.") + diff_ok = False + else: + compared, mism = res + diff_ok = mism == 0 + print(f" Rust differential: {compared:,} (quotient, carry-array) comparisons " + f"against `ecsm::lincomb2_witness`, {mism} mismatches") + if mism: + print(" [!] the carries measured below are NOT the prover's") + print() + + rows_seen = 0 + dinv_c = [10**9, -10**9] + dinv_q = [None, None] + for u1, u2, p1, p2 in cases: + _q, _len, rows = lincomb2_ref.lincomb2_rows(u1, p1, u2, p2, T0) + for r in rows: + rows_seen += 1 + res = honest_row_carries(r["a"], r["addend"], r["r"], r["lam"], r["op"]) + for rel, (carries, q) in res.items(): + record(rel, carries, q, r["sel"]) + if r["op"] == 1: # addend-consuming rows get the new relation + c, q3 = honest_dinv_carries(r["a"], r["addend"]) + dinv_c[0] = min(dinv_c[0], min(c)) + dinv_c[1] = max(dinv_c[1], max(c)) + dinv_q[0] = q3 if dinv_q[0] is None else min(dinv_q[0], q3) + dinv_q[1] = q3 if dinv_q[1] is None else max(dinv_q[1], q3) + + print(f"{rows_seen:,} real rows over {len(cases)} lincomb2 evaluations " + f"(every row type incl. Precompute and Correction)") + print() + print(f"{'relation':10} {'honest c range':>26} {'window':>22} {'fits':>6} " + f"{'min offset needed':>18}") + ok = True + for rel, off in [("lambda", CARRY_OFFSET_LAMBDA), ("xr", CARRY_OFFSET_XR), + ("yr", CARRY_OFFSET_YR)]: + lo, hi = carry_window(off) + cmin, cmax, qmin, qmax = stats[rel] + fits = lo <= cmin and cmax <= hi + ok &= fits + print(f"{rel:10} {f'[{cmin}, {cmax}]':>26} {f'[{lo}, {hi}]':>22} " + f"{str(fits):>6} {-cmin:>18}") + lo, hi = carry_window(CARRY_OFFSET_LAMBDA) + fits = lo <= dinv_c[0] and dinv_c[1] <= hi + ok &= fits + print(f"{'dinv':10} {f'[{dinv_c[0]}, {dinv_c[1]}]':>26} {f'[{lo}, {hi}]':>22} " + f"{str(fits):>6} {-dinv_c[0]:>18}") + + print() + print("quotient headroom (33 bytes = [0, 2^264)):") + for rel in ("lambda", "xr", "yr"): + _, _, qmin, qmax = stats[rel] + print(f" {rel:8} q in [{qmin.bit_length()} bits, {qmax.bit_length()} bits] " + f"min q >= 0: {qmin >= 0} max q < 2^264: {qmax < (1 << 264)}") + ok &= (qmin >= 0 and qmax < (1 << 264)) + print(f" {'dinv':8} q in [{dinv_q[0].bit_length()} bits, {dinv_q[1].bit_length()} bits] " + f"min q >= 0: {dinv_q[0] >= 0} max q < 2^264: {dinv_q[1] < (1 << 264)}") + ok &= (dinv_q[0] >= 0 and dinv_q[1] < (1 << 264)) + + print() + print("per row type (carry ranges), to show the new row shapes are not outliers:") + for sel in ("Precompute", "Double", "AddP1", "AddP2", "AddP12", "Correction"): + parts = [] + for rel in ("lambda", "xr", "yr"): + v = per_sel.get((sel, rel)) + if v: + parts.append(f"{rel}=[{v[0]}, {v[1]}]") + if parts: + print(f" {sel:12} " + " ".join(parts)) + + print() + print("=" * 78) + print(f"WIDTH AUDIT: {chr(80)+chr(65)+chr(83)+chr(83) if (ok and fails == 0 and diff_ok) else chr(70)+chr(65)+chr(73)+chr(76)}") + print("=" * 78) + return 0 if (ok and fails == 0 and diff_ok) else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/oracle/width_audit_z3.py b/thoughts/ec-recover-opt/oracle/width_audit_z3.py new file mode 100644 index 000000000..fd08fefd4 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/width_audit_z3.py @@ -0,0 +1,166 @@ +"""z3 confirmation of the width audit's interval step. + +`width_audit.py` bounds `S_i` by interval arithmetic and cross-checks with random +corners. Corners can miss; this script machine-checks the step that matters. + +Two claims per relation and limb index `i`: + + W1 (interval soundness) for all byte limbs and bit op/mu, `S_i` lies inside + the interval `width_audit.s_interval` computes. Expect UNSAT on the + negation. + + W2 (no wraparound) for all byte limbs, bit op/mu, and carries inside + their IsHalfword windows, `|256*c_i - c_{i-1} - S_i| < p_g`. Expect UNSAT + on the negation. This is the claim the whole integer-lifting argument (L1) + rests on, stated directly rather than through the interval. + +Both are checked with the addend limbs FREE BYTES -- no canonicality assumed -- +which is precisely the varying-addend question. + +W2 is also checked in a TAMPERED form (N-WIDTH): drop the byte constraint from +the addend's limbs, leaving them free field elements. That must go SAT, showing +the check is non-vacuous and that byte-ness of the addend is load-bearing. + +Run: /bin/python width_audit_z3.py [max_i] +""" + +import sys + +from z3 import And, Int, Or, Solver, sat, unsat + +from width_audit import (CARRY_OFFSET_LAMBDA, CARRY_OFFSET_XR, CARRY_OFFSET_YR, + NLIMB, PP, P_G, RR, carry_window, s_interval) + +TIMEOUT_MS = 120_000 + + +def build_s(rel, i, lam, xa, ya, xb, yb, xr, yr, q, op, mu): + """`S_i` as a z3 term, transcribed from `EcdasConstraints::s_i` + (prover/src/tables/ecdas.rs:348-397) and its ecdas2 twin.""" + rq = mu * sum(RR[j] * PP[i - j] for j in range(i + 1)) \ + - sum(q[j] * PP[i - j] for j in range(i + 1)) + + if rel == "lambda": + op_branch = ya[i] - yb[i] + sum(lam[j] * (xb[i - j] - xa[i - j]) + for j in range(i + 1)) + notop = sum(2 * lam[j] * ya[i - j] - 3 * xa[j] * xa[i - j] + for j in range(i + 1)) + return op * op_branch + (1 - op) * notop + rq + if rel == "xr": + s = sum(lam[j] * lam[i - j] for j in range(i + 1)) + return s - xa[i] - xb[i] - xr[i] - (1 - op) * (xa[i] - xb[i]) + rq + if rel == "yr": + s = sum(lam[j] * (xa[i - j] - xr[i - j]) for j in range(i + 1)) + return s - ya[i] - yr[i] + rq + if rel == "dinv": + # proposed: d_inv*(xB - xA) - 1 == 0 (mod p); `lam` plays d_inv + s = sum(lam[j] * (xb[i - j] - xa[i - j]) for j in range(i + 1)) + return (s - 1 if i == 0 else s) + rq + raise ValueError(rel) + + +def limbs(name, n): + return [Int(f"{name}_{j}") for j in range(n)] + + +def byte_bounds(vs): + return [And(v >= 0, v <= 255) for v in vs] + + +def run(rel, i, offset, check, tamper_addend=False): + lam, xa, ya = limbs("lam", NLIMB), limbs("xa", NLIMB), limbs("ya", NLIMB) + xb, yb = limbs("xb", NLIMB), limbs("yb", NLIMB) + xr, yr, q = limbs("xr", NLIMB), limbs("yr", NLIMB), limbs("q", NLIMB) + op, mu = Int("op"), Int("mu") + + s = Solver() + s.set("timeout", TIMEOUT_MS) + for group in (lam, xa, ya, xr, yr, q): + s.add(byte_bounds(group)) + if tamper_addend: + # N-WIDTH: the addend's limbs are only field elements, not bytes. + for v in xb + yb: + s.add(And(v >= 0, v < P_G)) + else: + s.add(byte_bounds(xb + yb)) + s.add(Or(op == 0, op == 1), Or(mu == 0, mu == 1)) + # limbs beyond 32 are structurally zero (values are 32 bytes, quotients 33) + for v in lam[32:] + xa[32:] + ya[32:] + xb[32:] + yb[32:] + xr[32:] + yr[32:]: + s.add(v == 0) + for v in q[33:]: + s.add(v == 0) + + S = build_s(rel, i, lam, xa, ya, xb, yb, xr, yr, q, op, mu) + + if check == "interval": + lo, hi = s_interval(rel, i) + s.add(Or(S < lo, S > hi)) + else: # "wrap" + c_lo, c_hi = carry_window(offset) + ci, cp = Int("c_i"), Int("c_prev") + if i == 63: + s.add(ci == 0) # ColIsZero on the closing carry + else: + s.add(And(ci >= c_lo, ci <= c_hi)) + if i == 0: + s.add(cp == 0) + else: + s.add(And(cp >= c_lo, cp <= c_hi)) + expr = 256 * ci - cp - S + s.add(Or(expr >= P_G, expr <= -P_G)) + + return s.check() + + +def main(): + max_i = int(sys.argv[1]) if len(sys.argv) > 1 else 16 + rels = [("lambda", CARRY_OFFSET_LAMBDA), ("xr", CARRY_OFFSET_XR), + ("yr", CARRY_OFFSET_YR), ("dinv", CARRY_OFFSET_LAMBDA)] + idxs = [i for i in (0, 1, 2, 3, 7, 15, 31, 47, 63) if i <= max_i] or [0] + + print(f"z3 {'':2} limb indices checked: {idxs} (timeout {TIMEOUT_MS//1000}s each)") + print() + bad = 0 + unknown = 0 + for check in ("interval", "wrap"): + print(f"--- W{'1' if check == 'interval' else '2'} " + f"({'interval soundness' if check == 'interval' else 'no wraparound mod p_g'}) ---") + for rel, off in rels: + verdicts = [] + for i in idxs: + r = run(rel, i, off, check) + verdicts.append(f"i={i}:{r}") + if r == sat: + bad += 1 + elif r != unsat: + unknown += 1 + print(f" {rel:8} " + " ".join(verdicts)) + print() + + print("--- N-WIDTH (negative control: addend limbs NOT byte-constrained) ---") + ctl_sat = 0 + for rel, off in rels: + verdicts = [] + for i in (31, 63): + if i > max_i: + continue + r = run(rel, i, off, "wrap", tamper_addend=True) + verdicts.append(f"i={i}:{r}") + if r == sat: + ctl_sat += 1 + if verdicts: + print(f" {rel:8} " + " ".join(verdicts)) + print() + print(f" {ctl_sat} of the tampered queries are SAT " + f"(wraparound becomes reachable once the addend is not byte-bounded)") + + print() + ok = bad == 0 and unknown == 0 and ctl_sat > 0 + print(f"WIDTH AUDIT z3: {'PASS' if ok else 'FAIL'} " + f"({bad} soundness violations, {unknown} unknown/timeout, " + f"{ctl_sat} negative controls SAT)") + return 0 if ok else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/thoughts/ec-recover-opt/oracle/wycheproof_ecdh_secp256k1.json b/thoughts/ec-recover-opt/oracle/wycheproof_ecdh_secp256k1.json new file mode 100644 index 000000000..3ed520746 --- /dev/null +++ b/thoughts/ec-recover-opt/oracle/wycheproof_ecdh_secp256k1.json @@ -0,0 +1,8448 @@ +{ + "algorithm": "ECDH", + "schema": "ecdh_test_schema_v1.json", + "numberOfTests": 752, + "header": [ + "Test vectors of type EcdhTest are intended for", + "testing an ECDH implementations using X509 encoded", + "public keys and integers for private keys.", + "Test vectors of this format are useful for testing", + "Java providers." + ], + "notes": { + "AdditionChain": { + "bugType": "KNOWN_BUG", + "description": "The private key has an unusual bit pattern, such as high or low Hamming weight. The goal is to test edge cases for addition chain implementations." + }, + "CompressedPoint": { + "bugType": "UNKNOWN", + "description": "The point in the public key is compressed. Not every library supports points in compressed format." + }, + "CompressedPublic": { + "bugType": "FUNCTIONALITY", + "description": "The public key in the test vector is compressed. Some implementations do not support compressed points." + }, + "EdgeCaseDoubling": { + "bugType": "EDGE_CASE", + "description": "The test vector contains an EC point that hits an edge case (e.g. a coordinate 0) when doubled. The goal of the test vector is to check for arithmetic errors in these test cases.", + "effect": "The effect of such arithmetic errors is unclear and requires further analysis." + }, + "EdgeCaseEphemeralKey": { + "bugType": "EDGE_CASE", + "description": "The test vector contains an ephemeral public key that is an edge case." + }, + "EdgeCaseSharedSecret": { + "bugType": "EDGE_CASE", + "description": "The test vector contains a public key and private key such that the shared ECDH secret is a special case. The goal of this test vector is to detect arithmetic errors.", + "effect": "The seriousness of an arithmetic error is unclear. It requires further analysis to determine if the bug is exploitable." + }, + "InvalidAsn": { + "bugType": "UNKNOWN", + "description": "The public key in this test uses an invalid ASN encoding. Some cases where the ASN parser is not strictly checking the ASN format are benign as long as the ECDH computation still returns the correct shared value." + }, + "InvalidCompressedPublic": { + "bugType": "MODIFIED_PARAMETER", + "description": "The test vector contains a compressed public key that does not exist. I.e., it contains an x-coordinate that does not correspond to any points on the curve. Such keys should be rejected " + }, + "InvalidCurveAttack": { + "bugType": "CONFIDENTIALITY", + "description": "The point of the public key is not on the curve. ", + "effect": "If an implementation does not check whether a point is on the curve then it is likely that the implementation is susceptible to an invalid curve attack. Many implementations compute the shared ECDH secret over a curve defined by the point on the public key. This curve can be weak and hence leak information about the private key." + }, + "InvalidEncoding": { + "bugType": "MODIFIED_PARAMETER", + "description": "The test vector contains a public key with an invalid encoding." + }, + "InvalidPublic": { + "bugType": "CAN_OF_WORMS", + "description": "The public key has been modified and is invalid. An implementation should always check whether the public key is valid and on the same curve as the private key. The test vector includes the shared secret computed with the original public key if the public point is on the curve of the private key.", + "effect": "Generating a shared secret other than the one with the original key likely indicates that the bug is exploitable." + }, + "LargeCofactor": { + "bugType": "MODIFIED_PARAMETER", + "description": "The cofactor is larger than the limits specified in FIPS-PUB 186-4 table 1, p.36." + }, + "ModifiedCofactor": { + "bugType": "MODIFIED_PARAMETER", + "description": "The cofactor has been modified. ", + "effect": "The seriousness of accepting a key with modified cofactor depends on whether the primitive using the key actually uses the cofactor." + }, + "ModifiedGenerator": { + "bugType": "MODIFIED_PARAMETER", + "description": "The generator of the EC group has been modified.", + "effect": "The seriousness of the modification depends on whether the cryptographic primitive uses the generator. In the worst case such a modification allows an invalid curve attack." + }, + "ModifiedGroup": { + "bugType": "MODIFIED_PARAMETER", + "description": "The EC curve of the public key has been modified. EC curve primitives should always check that the keys are on the expected curve." + }, + "ModifiedPrime": { + "bugType": "MODIFIED_PARAMETER", + "description": "The modulus of the public key has been modified. The public point of the public key has been chosen so that it is both a point on both the curve of the modified public key and the private key." + }, + "ModifiedPublicPoint": { + "bugType": "MODIFIED_PARAMETER", + "description": "The public point of the key has been modified and is not on the curve.", + "effect": "Not checking that a public point is on the curve may allow an invalid curve attack." + }, + "NegativeCofactor": { + "bugType": "MODIFIED_PARAMETER", + "description": "The cofactor of the curve is negative." + }, + "Normal": { + "bugType": "BASIC", + "description": "The test vector contains a pseudorandomly generated, valid test case. Implementations are expected to pass this test." + }, + "UnnamedCurve": { + "bugType": "UNKNOWN", + "description": "The public key does not use a named curve. RFC 3279 allows to encode such curves by explicitly encoding, the parameters of the curve equation, modulus, generator, order and cofactor. However, many crypto libraries only support named curves. Modifying some of the EC parameters and encoding the corresponding public key as an unnamed curve is a potential attack vector." + }, + "UnusedParam": { + "bugType": "MALLEABILITY", + "description": "A parameter that is typically not used for ECDH has been modified. Sometimes libraries ignore small differences between public and private key. For example, a library might ignore an incorrect cofactor in the public key. We consider ignoring such changes as acceptable as long as these differences do not change the outcome of the ECDH computation, i.e. as long as the computation is done on the curve from the private key." + }, + "WeakPublicKey": { + "bugType": "MODIFIED_PARAMETER", + "description": "The vector contains a weak public key. The curve is not a named curve, the public key point has order 3 and has been chosen to be on the same curve as the private key. This test vector is used to check ECC implementations for missing steps in the verification of the public key." + }, + "WrongCurve": { + "bugType": "CONFIDENTIALITY", + "description": "The public key and private key use distinct curves. Implementations are expected to reject such parameters.", + "effect": "Computing an ECDH key exchange with public and private keys can in the worst case lead to an invalid curve attack. Hence, it is important that ECDH implementations check the input parameters. The severity of such bugs is typically smaller if an implementation ensures that the point is on the curve and that the ECDH computation is performed on the curve of the private key. Some of the test vectors with modified public key contain shared ECDH secrets, that were computed over the curve of the private key." + }, + "WrongOrder": { + "bugType": "MODIFIED_PARAMETER", + "description": "The order of the public key has been modified.", + "effect": "If this order is used in a cryptographic primitive instead of the correct order then an invalid curve attack is possible and the private keys may leak. E.g. ECDHC in BC 1.52 suffered from this." + }, + "NoCofactor": { + "bugType": "MISSING_PARAMETER", + "description": "The cofactor field is absent from the ECParameters. RFC 3279 Section 2.3.5 requires the cofactor to be present." + }, + "ModifiedCurveParameter": { + "bugType": "MODIFIED_PARAMETER", + "description": "The parameters a and b of the curve have been modified. The parameters haven been chosen so that public key or generator still are also valid points on the new curve." + } + }, + "testGroups": [ + { + "type": "EcdhTest", + "source": { + "name": "google-wycheproof", + "version": "0.9rc5" + }, + "curve": "secp256k1", + "encoding": "asn", + "tests": [ + { + "tcId": 1, + "comment": "normal case", + "flags": [ + "Normal" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b396812ea1686e7472e9692eaf3e958e50e9500d3b4c77243db1f2acd67ba9cc4", + "private": "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", + "shared": "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", + "result": "valid" + }, + { + "tcId": 2, + "comment": "compressed public key", + "flags": [ + "CompressedPublic", + "CompressedPoint" + ], + "public": "3036301006072a8648ce3d020106052b8104000a03220002d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b", + "private": "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", + "shared": "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", + "result": "acceptable" + }, + { + "tcId": 3, + "comment": "shared secret has x-coordinate that satisfies x**2 + a = 1", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004965ff42d654e058ee7317cced7caf093fbb180d8d3a74b0dcd9d8cd47a39d5cb9c2aa4daac01a4be37c20467ede964662f12983e0b5272a47a5f2785685d8087", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000000000000000000000000000000000000000000000000001", + "result": "valid" + }, + { + "tcId": 4, + "comment": "shared secret has x-coordinate that satisfies x**2 + a = 4", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000406c4b87ba76c6dcb101f54a050a086aa2cb0722f03137df5a922472f1bdc11b982e3c735c4b6c481d09269559f080ad08632f370a054af12c1fd1eced2ea9211", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000000000000000000000000000000000000000000000000002", + "result": "valid" + }, + { + "tcId": 5, + "comment": "shared secret has x-coordinate that satisfies x**2 + a = 9", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bba30eef7967a2f2f08a2ffadac0e41fd4db12a93cef0b045b5706f2853821e6d50b2bf8cbf530e619869e07c021ef16f693cfc0a4b0d4ed5a8f464692bf3d6e", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000000000000000000000000000000000000000000000000003", + "result": "valid" + }, + { + "tcId": 6, + "comment": "shared secret has x-coordinate p-3", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046da9eb2cdac02122d5f05cf6a8cd768e378f664ea4a7871d10e25f57eb1ee1cc5b2b5abf9c6c6596f8f383ddbcb3bcc2d5a7cc605984931239ca9669946032ee", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c", + "result": "valid" + }, + { + "tcId": 7, + "comment": "shared secret has x-coordinate 2**16 + 0", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f2976154c4f53ce392d1fe39a891a4611ba8cf046023cd8f1bcd9fdd2e921191b25cf31caedfbb415381637bc3f599a34fba3e1413f644cb1668469f4558a772", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000000000000000000000000000000000000000000000010000", + "result": "valid" + }, + { + "tcId": 8, + "comment": "shared secret has x-coordinate 2**32 + 7", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045e422fea67cca5ebaeac87745c81b10ef807030367e6fce012254176ec8cf199881592f42c264371e19e3037388ab64f32fa8870e62905e7af205e43b02aad12", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000000000000000000000000000000000000000000100000007", + "result": "valid" + }, + { + "tcId": 9, + "comment": "shared secret has x-coordinate 2**64 + 1", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bb57b9a1231be042d185c03eda6926a6def177fe6745eda000c520d66581f0cdf1d73c80453f2fe30725adf951390c739e36fc8677691db107881342613d00ab", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000000000000000000000000000000000010000000000000001", + "result": "valid" + }, + { + "tcId": 10, + "comment": "shared secret has x-coordinate 2**96 + 1", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045563c76c19377638f7d517bdbe0ace467eb5d4dd9fb4bf18332bab8f07b1d80c261332d46e316711278bacccd88005ee4c115fa84089fd190674626e5ed1ebfe", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000000000000000000000000001000000000000000000000001", + "result": "valid" + }, + { + "tcId": 11, + "comment": "shared secret has x-coordinate that satisfies x**2 + a = -6", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048983aae8c002f2b555acb2370adb9b50ba4cac1bfcc9039a125c70ca7c5fc0d1f6efeb8ae4ba8c69429d93244382447ac534891c66090025282655719bd72512", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0b7beba34feb647da200bed05fad57c0348d249e2a90c88f31f9948bb65d5207", + "result": "valid" + }, + { + "tcId": 12, + "comment": "shared secret has x-coordinate that satisfies x**2 + a = 2", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000423556564850c50fba51f1e64ef98378ef5c22feafa29499ca27600c473cace889d5679e917daa7f4c7899517d37826284f031de01a60bc813696414d04531a21", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f7", + "result": "valid" + }, + { + "tcId": 13, + "comment": "shared secret has x-coordinate that satisfies x**2 + a = 8", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ddbf807e22c56a19cf6c472829150350781034a5eddec365694d4bd5c865ead14e674127028c91d3394cac37293a866055d10f0f40a3706ad16b64fc9d5998bd", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "result": "valid" + }, + { + "tcId": 14, + "comment": "shared secret has x-coordinate that satisfies x**2 = 2**96 + 2", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000464688eae7aabd248f6f44a0d6e2c438e4100001813eb71f9f082fad3dfe43e287dab3dabe7d436001a0fb763015dedbb90f811000ec8f5f29953e3af42f92065", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "39f883f105ac7f09f4e7e4dcc84bc7ff4b3b74f301efaaaf8b638f47720fdaec", + "result": "valid" + }, + { + "tcId": 15, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 2", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c404e17141d102bba2f1cb16bb954a208798b04dca8dd139a8ab7f01f0dbef39c7b8e55f2257a480077e4190570a004cbe668200c9c78eaa53b61b20fce4c685", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "5555555555555555555555555555555555555555555555555555555555555550", + "result": "valid" + }, + { + "tcId": 16, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 2", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e160e87c0a562a1dbb59b4c2f614720e7753608672eb8d883b91e25f8cfc58474623cba584e1324bc49bcdf0891166b545b7704e2bbda705d0d73b7530e47952", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "result": "valid" + }, + { + "tcId": 17, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 4", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045d4d182b18782a02685dcc7b671ec742ce308c7acc8e6260f67e81516eb546e8a38f0756074eea4857953398b6d05597c7ceb5e65e4e8cee31e81c5658824ce4", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "3333333333333333333333333333333333333333333333333333333333333333", + "result": "valid" + }, + { + "tcId": 18, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 4", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048ecd6a2576f42626792076935e2fe961599e484cd212bce2623b83aa22f546d2a7f855b09bef286bcbe9e8bab17fd56d7055df64f344310c3522e8f227e472c8", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccb", + "result": "valid" + }, + { + "tcId": 19, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 8", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046826f79ef84da803460aed09198d2bbb42d7892ed608aacbb281a95acae11465a25809191aa5bdfa61b8963beacb4eb133266a90f33d1b2ca4f6152d37a94fd8", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0c", + "result": "valid" + }, + { + "tcId": 20, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 8", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a54bb2ae80086053a5fa4fdb1836a8c6ac41783650b0f79a5428c98ff64d078a12bbb4cb8af20ca75ec15b2e0d47a83ca93fc78cd92640a02e8002966f1fe80b", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0", + "result": "valid" + }, + { + "tcId": 21, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 16", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bace46eed492743c693e1a33adb046b7722c55ce369d1438e67f9c5b3412783145262dd4a86c8a527b23f4114b8a9b9f36f9701835f50b678b24d2a9155ebc2c", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff", + "result": "valid" + }, + { + "tcId": 22, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 16", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000401055147863aa060c0e104e243ec01eda2b0e0c6814e232d671abcba9715d5ce0c13006aa7960c54fe3f20220bef766756c910fd05764afc318375540cef2d5c", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00", + "result": "valid" + }, + { + "tcId": 23, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 30", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004595e46ee7c2d7183ff2ea760ffd8472fb834ec89c08b6ef48ff92b44a13a6e1ae563e23953c97c26441323d2500c84e8cee04c15d4d5d2cc458703d1f2d02d31", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "7fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff", + "result": "valid" + }, + { + "tcId": 24, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 30", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046a40adc811b09e83ba0fb8a94fea50591ca9e58bb7d47304950dbff78dad777ee3bd08f742d7e8e30cff31bc6a6cc02c8717ee25838aabffa6e48f65cce74d81", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "8000fffe0003fff8000fffe0003fff8000fffe0003fff8000fffe0003fff7fff", + "result": "valid" + }, + { + "tcId": 25, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 32", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045a33fe91d7e35db7875208bee77f4cc0006f1439cc845f695b6a12673dcd03d18f86ee121c5ea0da3eb0210509e12db845296225ca973e2e19ce3e3d01486090", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffd", + "result": "valid" + }, + { + "tcId": 26, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 32", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f6ebaab62c35fd4b8bec9d95bcfc433e6bde7c0f0d5ef75d6fd326aaf28f23b0b2f4d1c2e891706b7bada59fb0f6a32b5463982a9c8c2d8ea38954418183b634", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffefffe", + "result": "valid" + }, + { + "tcId": 27, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 51", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004524392416f8cfc5f84dc9b72f2887c684e4bd24796f0065078e18d16bc43b56ea02178311799eb61ad3b3e7dcda10404dc4541c13e3de0ceb40c9aa7afabc53b", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "8000003ffffff0000007fffffe000000ffffffc000001ffffff8000003fffffd", + "result": "valid" + }, + { + "tcId": 28, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 51", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000499965c477a240aebbd19cd094c8b62852de8663d0cc9f06eeb395ffc92d121f64811882f406080d7d04ea4f339bddd2e5ef0345b5834142f75b562154d5ec7ae", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "7fffffe000000ffffffc000001ffffff8000003ffffff0000007fffffdfffffe", + "result": "valid" + }, + { + "tcId": 29, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 52", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ad3d179877e74ee258ba6f8e128bc2a0045c06a3d3c30fcce01ca8d9e1afee4ea3fe47156fb727fc1c55ef9db516df665cbb073405c2c301a8fe1d10f3b9b300", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "000003ffffff0000003ffffff0000003ffffff0000003ffffff0000003fffffc", + "result": "valid" + }, + { + "tcId": 30, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 52", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044bb19deae638fc5fa7070cc90e969bac3f8384a59ea11cb01bc091edf1a4cbd677ed6bdf8971d3e63c903d9acabc28b75af661a03457261c5a8d5940ad02c509", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "fffffc000000ffffffc000000ffffffc000000ffffffc000000ffffffbfffffe", + "result": "valid" + }, + { + "tcId": 31, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 60", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000424175c078e305d3139e5dab727a6ab8587b26daa470a529a23c10585cb56c038bf1f2b937ae074ff94b15f5cb5e60eb5d32afba2077539db794294bcaab71a81", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff", + "result": "valid" + }, + { + "tcId": 32, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 60", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ef691afe2ee4aa18a8485a71c0e20eff1337ae0622acc09ccda10f49574ae840b82730bb2eef59a17ab095acd131e5fcf8ba11150a9421bbab6b9f146aa78ffb", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000fffffffc0000000fffffffc0000000fffffffc0000000fffffffbffffffd", + "result": "valid" + }, + { + "tcId": 33, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 62", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004067e7df09f5e38f2b2823f65a6b1135c3290586fef6eceffa6d59595748879f66932b3f70d603229e10a57344ecde503a2df930651046c2f1d2b719bfc93e0a1", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "ff00000001fffffffc00000007fffffff00000001fffffffc00000007ffffffd", + "result": "valid" + }, + { + "tcId": 34, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 62", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b8722ecdde7c85317e486b03656b83910ac3c88687a4291e8bb9a4b6a52cc6e02e4158a5a88de023d6a135bd04c1585ef46741890376135453ec562da5b3760b", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "00fffffffe00000003fffffff80000000fffffffe00000003fffffff80000000", + "result": "valid" + }, + { + "tcId": 35, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 64", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004728e15d578212bc42287c0118c82c84b126f97d549223c10ad07f4e98af912385d23b1a6e716925855a247b16effe92773315241ac951cdfefdfac0ed16467f6", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", + "result": "valid" + }, + { + "tcId": 36, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 64", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c3ef35fd4cda66e8e850095e1e697aee56decc29484aa463f879c7b6dd7669e625945351276719c5e3bb8e514f69305b6085b7c782a07b26a842887c33a93dc6", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "ffffffff00000000ffffffff00000000ffffffff00000000fffffffeffffffff", + "result": "valid" + }, + { + "tcId": 37, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 112", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004784907c6be6202770b98d01f1ffe11b9ed2c97515843f57c2c06363a9dadc7011de5fbaa7356cf3ba28cb7b932a07c8321007c7c45396751fe70724343d2b19f", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "ffffffff00000000000000ffffffffffffff00000000000000fffffffffffffe", + "result": "valid" + }, + { + "tcId": 38, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 112", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047c016dee8b5411f8e95184daf8e318119e844b8bdc70d75efb99b8d0ff10ab745e905103d57d6537908e6e9864aee4f0917f5b920d06f980aa823f043ef9139e", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "00000000ffffffffffffff00000000000000ffffffffffffff00000000000000", + "result": "valid" + }, + { + "tcId": 39, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 128", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000436e1e76ffdbe8577520b0716eb88c18ea72a49e5a4e5680a7d290093f841cb6e7310728b59c7572c4b35fb6c29c36ebabfc53553c06ecf747fcfbefcf6114e1c", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff", + "result": "valid" + }, + { + "tcId": 40, + "comment": "shared secret has x-coordinate with repeating bit-pattern of size 128", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047a19501d646fc9332a8525af4cc79523b57d736b69bb24b06270c1b1dadf88ce834efa1bce854ff5bcade40cbcee9f40154bc26036adc5cf87e50ea388af2987", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "ffffffffffffffff0000000000000000fffffffffffffffefffffffffffffff5", + "result": "valid" + }, + { + "tcId": 41, + "comment": "shared secret has an x-coordinate of approx p//3", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f43b610a2a5c5f6e2b395567489657059e3351c6f9a7e2ebde52638abfea006ab2d690513e9187c0cc903ceee022ee421c594a8bd7610c68cd8143adfc741dde", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "55555555555555555555555555555555555555555555555555555554fffffebc", + "result": "valid" + }, + { + "tcId": 42, + "comment": "shared secret has an x-coordinate of approx p//5", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d93bfdaa797cd4bd81dea80d7c72a24923ce50e94bfc4ee1bd5f5f10eea3f8ecc0b5941890a26e88e5029c283e0fadeccc0b980f8a5098aa7835c5c958d471e5", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "33333333333333333333333333333333333333333333333333333332ffffff3c", + "result": "valid" + }, + { + "tcId": 43, + "comment": "shared secret has an x-coordinate of approx p//7", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040ac1ea7a29f7ace8a38b2fedbfe4d0d9ae45344432ab3eb5e0a5b66716f61c6aaaa39a5f098fd4472587d14bdf72b3dd3e966b5f0b6e400fff6e0e9c8453fc79", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "249249249249249249249249249249249249249249249249249249246db6dae2", + "result": "valid" + }, + { + "tcId": 44, + "comment": "shared secret has an x-coordinate of approx p//9", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bf2e8a61a21d96e74a296b397e53044f373acb73a6ea4a398d89c56549e96b7fe846fd0df239691d0682b067a50a2423d88b4d970b1d3d8141a066d13c186f96", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "1c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c555554e8", + "result": "valid" + }, + { + "tcId": 45, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000456baf1d72606c7af5a5fa108620b0839e2c7dd40b832ef847e5b64c86efe1aa563e586a667a65bbb5692500df1ff8403736838b30ea9791d9d390e3dc6689e2c", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff", + "result": "valid" + }, + { + "tcId": 46, + "comment": "y-coordinate of the public key has many trailing 1's", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff07ed353c9f1039edcc9cc5336c034dc131a4087692c2e56bc1dd1904e3ffffff", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "7c07b199b6a62e7ac646c7e1dee94aca55de1a97251ddf92fcd4fe0145b40f12", + "result": "valid" + }, + { + "tcId": 47, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa05a5e4af11cf63ceaaa42a6dc9e4ccb394852cf84284e8d2627572fbf22c0ba88", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", + "result": "valid" + }, + { + "tcId": 48, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a48307eb78d38770fea1a44f4da72c26f85b17f3501a4f9394fe29856ccbf15fd284", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", + "result": "valid" + }, + { + "tcId": 49, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037effffffffffffffffffffffffffffffff0000031a6bf344b86730ac5c54a7751aefdba135759b9d535ca64111f298a38d", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", + "result": "valid" + }, + { + "tcId": 50, + "comment": "y-coordinate of the public key is small", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff0000013bc6f08431e729ed2863f2f4ac8a30279695c8109c340a39fa86f451cd", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", + "result": "valid" + }, + { + "tcId": 51, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa0a5a1b50ee309c31555bd592361b334c6b7ad307bd7b172d9d8a8d03fdd3f41a7", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", + "result": "valid" + }, + { + "tcId": 52, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a483f814872c788f015e5bb0b258d3d907a4e80cafe5b06c6b01d67a93330ea029ab", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", + "result": "valid" + }, + { + "tcId": 53, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037efffffffffffffffffffffffffffffffffffffce5940cbb4798cf53a3ab588ae510245eca8a6462aca359beed0d6758a2", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", + "result": "valid" + }, + { + "tcId": 54, + "comment": "y-coordinate of the public key is large", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0fffffffffffffffffffffffffffffffffffffec4390f7bce18d612d79c0d0b5375cfd8696a37ef63cbf5c604790baa62", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", + "result": "valid" + }, + { + "tcId": 55, + "comment": "y-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCaseSharedSecret" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045450cace04386adc54a14350793e83bdc5f265d6c29287ecd07f791ad2784c4cebd3c24451322334d8d51033e9d34b6bb592b1995d07867863d1044bd59d7501", + "private": "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared": "80000000000000000000000001126b54ffffffffffffffffffffffffffffffff", + "result": "valid" + }, + { + "tcId": 56, + "comment": "y-coordinate of the public key has many trailing 0's", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000001126b54ffffffffffffffffffffffffffffffff4106a369068d454ea4b9c3ac6177f87fc8fd3aa240b2ccb4882bdccbd4000000", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "e59ddc7646e4aef0623c71c486f24d5d32f7257ef3dab8fa524b394eae19ebe1", + "result": "valid" + }, + { + "tcId": 57, + "comment": "ephemeral key has x-coordinate that satisfies x**2 + a = 1", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "12c2ad36a59fda5ac4f7e97ff611728d0748ac359fca9b12f6d4f43519516487", + "result": "valid" + }, + { + "tcId": 58, + "comment": "ephemeral key has x-coordinate that satisfies x**2 + a = 4", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000000000000266fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "45aa9666757815e9974140d1b57191c92c588f6e5681131e0df9b3d241831ad4", + "result": "valid" + }, + { + "tcId": 59, + "comment": "ephemeral key has x-coordinate that satisfies x**2 + a = 9", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000032f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "b90964c05e464c23acb747a4c83511e93007f7499b065c8e8eccec955d8731f4", + "result": "valid" + }, + { + "tcId": 60, + "comment": "ephemeral key has x-coordinate p-3", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c0e994b14ea72f8c3eb95c71ef692575e775058332d7e52d0995cf8038871b67d", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "e97fb4c4fb33d6a114da6e0d180e54f99ec1ece9ff558871054e99d221930d16", + "result": "valid" + }, + { + "tcId": 61, + "comment": "ephemeral key has x-coordinate 2**16 + 0", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000100003c81e87241d9451d286ddbe65b14d47234307b80ce74b8921af7d4935707549d", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "1eea9c2756a3305bb5178f2c37436e7b41cf3805cd0a1087d2d02407fc553c09", + "result": "valid" + }, + { + "tcId": 62, + "comment": "ephemeral key has x-coordinate 2**32 + 7", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000010000000715098598dc12cf294ea5ac1eb5eeae9139f5cfd3d0ffdcfa7297a01dce1ee9df", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "2f1c5c590f97f79351fb9d36c597d1c61f1c409fcdedaeae795112fa1a2c7453", + "result": "valid" + }, + { + "tcId": 63, + "comment": "ephemeral key has x-coordinate 2**64 + 1", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000001000000000000000161bd3a38f707713b97eaf8d0184e0079e2a62cfba75d428b1326ea861aade950", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "82b8e90e6b6441b7164c9725ac1a35f098788096af95c276fac3c5a383d6b56c", + "result": "valid" + }, + { + "tcId": 64, + "comment": "ephemeral key has x-coordinate 2**96 + 1", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000100000000000000000000000115820e7e26670c6b45c1e0caa951eab312754180baa9fcff9f7e7bf46deea7fc", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "8a955b6cf4d518558e59372444d3fd9b78933e2d3229dfdfa6f5f66403290e19", + "result": "valid" + }, + { + "tcId": 65, + "comment": "ephemeral key has x-coordinate that satisfies x**2 + a = -6", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040b7beba34feb647da200bed05fad57c0348d249e2a90c88f31f9948bb65d52077435a6bef91b92ae32cf51d7149cad0353a46513851427c34436536ec7eae483", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "5626bbf79f10827e23fa5aef9a26533f5f4e7472934ed9759b7b3a77cda04b82", + "result": "valid" + }, + { + "tcId": 66, + "comment": "ephemeral key has x-coordinate that satisfies x**2 + a = 2", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f75f450dbbf718a4f6582d7af83953170b3037fb81a450a5ca5acbec74ad6cac89", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "1908ae936f53b9a8a2d09707ae414084090b175365401425479b10b8c3e8d1ba", + "result": "valid" + }, + { + "tcId": 67, + "comment": "ephemeral key has x-coordinate that satisfies x**2 + a = 8", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee37269a64bbcf3a3f227631c7a8ce532c77245a1c0db4343f16aa1d339fd2591a", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "5e13b3dc04e33f18d1286c606cb0191785f694e82e17796145c9e7b49bc2af58", + "result": "valid" + }, + { + "tcId": 68, + "comment": "ephemeral key has x-coordinate that satisfies x**2 = 2**96 + 2", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000439f883f105ac7f09f4e7e4dcc84bc7ff4b3b74f301efaaaf8b638f47720fdaec24f50efd39b8ae7536e8806927eac6fd52210a239fb4129e0bfed333476575ea", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "a995572ad174897ff1971e6d1e39f908448a5878da1e60f3901f57cacd49e5f6", + "result": "valid" + }, + { + "tcId": 69, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 2", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045555555555555555555555555555555555555555555555555555555555555550134a74fc6e7d7acef5bb20e969abb6f026ec0cb04dff34f7916ca64b07fff511", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "cd8427ea93f9fede38a70d0c39dbd96759613ba00f27b9db3971c80aec07e2d6", + "result": "valid" + }, + { + "tcId": 70, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 2", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa769afe397a5709201bda50ce2d31a13fde4076722a857719924009cc28159869", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "766b0752cd895b4b8543d44c9a348868ffff12aed632f8070e731d450d8a8c94", + "result": "valid" + }, + { + "tcId": 71, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 4", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000433333333333333333333333333333333333333333333333333333333333333330434e877eaa71340aa5e57e58a01f0b0aec8d24b5c64aa77ef95fae9b4958c5d", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "09b0aa839893b7ad37cc83160e6f3c5506bbe323497c21505ae9937c75d943c8", + "result": "valid" + }, + { + "tcId": 72, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 4", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccb2e808a8b6c6e5bc068f96348d68171e66159a0ee27073c82fc3f9581a4a1fb28", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "3c2a61121f094d5eecddf7d3b0016c170b90fd3f2fea0b12e31db04ae7c279a2", + "result": "valid" + }, + { + "tcId": 73, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 8", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0c1d854210f797c547bd3b3feccde1ce3e67c61c3400141da2068520e2bae9bf90", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "9a641d5efa8be7dc723aa58e2e52a150c8efced2fa1084041249773c7562c66d", + "result": "valid" + }, + { + "tcId": 74, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 8", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f022bcbf40d658bf3ff02d98aea5ae45d43ed85f6de9268f0eae85210f2fed81c6", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "d32977eca64d223ea90f10f72f810ec64d661833acc4c839591da813ef86f736", + "result": "valid" + }, + { + "tcId": 75, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 16", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff210a46304881329c9807b71b6393ba104b9f27d976065e852429fd664de98eee", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "55137fecb21eb3ebed1b41fb2f7e1ca337009465f855f3f920bc7d0b73c2da32", + "result": "valid" + }, + { + "tcId": 76, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 16", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff007011d6e851e5a53fde41c1f348690c0188f24c105d5cfca5b6ff3c93dbfdef99", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "0bde659ed89281e6c8a5fbdab764d0499b86d19d33f4c978e260bbae587d4057", + "result": "valid" + }, + { + "tcId": 77, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 30", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff4b66003c7482d0f2fd7b1cb2b0b7078cd199f2208fc37eb2ef286ccb2f1224e7", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "3135a6283b97e7537a8bc208a355c2a854b8ee6e4227206730e6d725da044dee", + "result": "valid" + }, + { + "tcId": 78, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 30", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048000fffe0003fff8000fffe0003fff8000fffe0003fff8000fffe0003fff7fff0a2331880cb3f8f9004bf68fc379beb6e3affadcbe81bd4f9bf76e4ac5ab2c37", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "2a3d29ce049fc50b00fab50e7581b84d441d297be6515fbe83dc485bdf32b6dc", + "result": "valid" + }, + { + "tcId": 79, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 32", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffd3b6a2629d598a045be28a1687288cc4d0c389cc6fe627c5cc3aa2ab963db7495", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "03c202a64e60ff5948d29816d68420c64c0518a7522a929381365b1245770a02", + "result": "valid" + }, + { + "tcId": 80, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 32", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffefffe35e39d53d101a6aa4ab434c55a70b03d244b6a2025a18d4d549dea451c031392", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "d07fcf7b89bd1ba24194caf977db68a5503a471a37d374e0917a5fe31d48c99e", + "result": "valid" + }, + { + "tcId": 81, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 51", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048000003ffffff0000007fffffe000000ffffffc000001ffffff8000003fffffd3aa774f4d29fefddd9546ad1f7b2b79cf42634284fbb1d7c702e9fca3fe049af", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "ea9f3a53ab4053df0bae0156767a62ec5ba0de4373ef12cbfb19aa80c6bcd904", + "result": "valid" + }, + { + "tcId": 82, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 51", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047fffffe000000ffffffc000001ffffff8000003ffffff0000007fffffdfffffe23e4bca0984da424a6120a13dc676c777607562d16ed9b8fa94c21fff7151d4e", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "f0557be2b26ddb56d44d2cb852224a291de771418fe148a730a76dadf5882f18", + "result": "valid" + }, + { + "tcId": 83, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 52", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004000003ffffff0000003ffffff0000003ffffff0000003ffffff0000003fffffc2a95c81253ac554846812d2a4415f6edcf954209008d260a806b85aba759ff72", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "c68f07233efd0745d8bcd51a89158717c2dc532f75a9e4de2076e1b830654ec8", + "result": "valid" + }, + { + "tcId": 84, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 52", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffc000000ffffffc000000ffffffc000000ffffffc000000ffffffbfffffe031537fcabe5d5e25165a18b1bd408212cb523efea0fc0fd1eac46e83b0d0b52", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "6eec8a68eb5f9caf2ab3053a3047bbc08412a1d433d79eea65effc5e0cd583bf", + "result": "valid" + }, + { + "tcId": 85, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 60", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff63a88b2e0c8987c6310cf81d0c935f00213f98a3dad2f43c8128fa313a90d55b", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "bbd9d305b99ff3db56f77fea9e89f32260ee7326040067ce05dd15e0dcc13ed8", + "result": "valid" + }, + { + "tcId": 86, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 60", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040000fffffffc0000000fffffffc0000000fffffffc0000000fffffffbffffffd2407bddc5a50b2a7b96a288efb838bf768c6066e60b72f08a9782da2e39bd34f", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "1f81aa3d70f8756b9495fba82921717d4006206a4451d8d59f3c9b8d95b548e8", + "result": "valid" + }, + { + "tcId": 87, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 62", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ff00000001fffffffc00000007fffffff00000001fffffffc00000007ffffffd4af9cc406a46943ffe0fe630bd21f205eefa05355f3a13c9943d58e16e880435", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "66e707faf954d1ec84fe0f68f829beb2fe95058271b636362e3eb5c5d492cbf8", + "result": "valid" + }, + { + "tcId": 88, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 62", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400fffffffe00000003fffffff80000000fffffffe00000003fffffff800000002796cf7bde36dc6b1950001228b7249d3438a35fe5be98661255bf63a879b3a5", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "42dd6d83bbce6afab5045e1393838a97a46161c25ae91db0143e985d29162faa", + "result": "valid" + }, + { + "tcId": 89, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 64", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff73b0886496aed70db371e2e49db640abba547e5e0c2763b73a0a42f84348a6b1", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "ab43917a64c1b010159643c18e2eb06d25eedae5b78d02fa9b3debacbf31b777", + "result": "valid" + }, + { + "tcId": 90, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 64", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ffffffff00000000ffffffff00000000ffffffff00000000fffffffeffffffff0013a9be0cbaaacf4e0f53ee45bc573eaa44dbf48d5fafc26856b44d6d00e2be", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "f39bf49011cb323ee00f77e0344a9b9da1256db92646dda0e342f8c1ad3741c5", + "result": "valid" + }, + { + "tcId": 91, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 112", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ffffffff00000000000000ffffffffffffff00000000000000fffffffffffffe6e563bca873bd591c9663391c826150795e3c42cedd269e68ff0e56dc971d554", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "27860fa0679edd4556f0423a21cc21e1e3f1701da3e62a544974ae94f15f91a0", + "result": "valid" + }, + { + "tcId": 92, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 112", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000ffffffffffffff00000000000000ffffffffffffff000000000000005b5b2ec553be67fd73add4cc2bced4ebe6d04a05b0e926e312037b3951667847", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "2bcfc95bba84524d8093dce1092bc157ca1fa42a37aaca9b0759437f940c3e7d", + "result": "valid" + }, + { + "tcId": 93, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 128", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040000000000000000ffffffffffffffff0000000000000000ffffffffffffffff31cf13671b574e313c35217566f18bd2c5f758c140d24e94e6a4fda7f4c7b12b", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "1a32749dcf047a7e06194ccb34d7c9538a16ddabeeede74bea5f7ef04979f7f7", + "result": "valid" + }, + { + "tcId": 94, + "comment": "ephemeral key has x-coordinate with repeating bit-pattern of size 128", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ffffffffffffffff0000000000000000fffffffffffffffefffffffffffffff53a54141598334650d1f99a12850769f53d34529b07ae591244c6ed702f1aa171", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "119aa477afad550e98db77bfb4e71a4b6ec79ec4fe17b7283f9b8bb7b9fdb5ec", + "result": "valid" + }, + { + "tcId": 95, + "comment": "ephemeral key has an x-coordinate of approx p//3", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000455555555555555555555555555555555555555555555555555555554fffffebc7c976bddab1d1a302cfa176c25434558ec7cac238e739ca9849aa104323b106c", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "21edb700cf62c1bb816a877988ee8c5bc16a8464bcb6454adb8abf8b5cef7ceb", + "result": "valid" + }, + { + "tcId": 96, + "comment": "ephemeral key has an x-coordinate of approx p//5", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000433333333333333333333333333333333333333333333333333333332ffffff3c7b2bf3716a9e336e162966597e5c423bb9d3d0d0c3c02b9e2dc4aabad17bfdcb", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "1ba54571d1d280f5fa2d0c5846ec392c721acd4ba7e4aadc3dc2353957abd80b", + "result": "valid" + }, + { + "tcId": 97, + "comment": "ephemeral key has an x-coordinate of approx p//7", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004249249249249249249249249249249249249249249249249249249246db6dae22817588aa19f910e8bed1f89a6b5ea6cde4800dd9beb28d1336bb46075118144", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "9d422ce42f74aa0272e5530b5dd094225f11d1100fed954ff714a2d471559cef", + "result": "valid" + }, + { + "tcId": 98, + "comment": "ephemeral key has an x-coordinate of approx p//9", + "flags": [ + "EdgeCaseEphemeralKey" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c555554e83c4d16ba6991011cf3f94feeff3f48ad29ed9a22bcef8fac40d9b2af25e2b909", + "private": "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared": "a5ab2cc5bb6881f7e734d7ccc9d448127d9465fd342d81c8381572059b3aa2b7", + "result": "valid" + }, + { + "tcId": 99, + "comment": "edge case for Jacobian and projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000459294e8bc54e76d48b5594f01fe4729566d9b6df6385982fbb533183921f1a124543e4110bf4cd22e1d444d83e24c5ecdb328a98f2f93e8edcb99b07d5d9fafc", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "e976057e8a322dfdb2debd55d8e58802fb54425950b2dbfd00f0813de27105e4", + "result": "valid" + }, + { + "tcId": 100, + "comment": "edge case for Jacobian and projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000429b579690264954985187aaa9ea313d39b5c828e022afce8fd0cb764ed693473ba8cde1b2be1749cf4d5bc0df578009c9650e44b6c385c5ee2621ffffc205cb7", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "09fa5a510558a12110daf75117af1e175f93d7c4d8ba41c5bf3efe95d829ff50", + "result": "valid" + }, + { + "tcId": 101, + "comment": "edge case for Jacobian and projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044150a111e0489cc82d43ba66f404ba0df2b1fa13ffea361442f7854f9abb381465627e96f372fd0400eca42113890cb110c11eda22405bcd295b1caab9d93af7", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "98bc618faef7c4311c3d8fd37b39e9baad780e14f0527fa69a3f4c2b66ac6394", + "result": "valid" + }, + { + "tcId": 102, + "comment": "edge case for Jacobian and projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a74646c798fd5a0af442da69c822cdf1134adba361f90663d626481aa10e0004567160696818286b72f01a3e5e8caca736249160c7ded69dd51913c303a2fa97", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8a0b2ddef3a1108f6ea367ed08079a0ec98494fe46cfad584bdc98e99e6d7f99", + "result": "valid" + }, + { + "tcId": 103, + "comment": "edge case for Jacobian and projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004611c65eecd9e3de528f639e8b6698688db1f4fc8c11650a601fe6daeca5c59665fa45a23400633ba3630244aa6b0144de2ab3b6295e3dfa15f586e40a84053af", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "89b86329f0f13aab07a48d0d3b7afe530ad260a90de6c25ec3da8b6905502551", + "result": "valid" + }, + { + "tcId": 104, + "comment": "edge case for Jacobian and projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b49c6791647937568c7570064856420835d44af1ceddd682967fbd44fc97294cd135651bd7ee3aab957eba10ed4b7a5c40ca00d959ca663080c4eaf0e189bc21", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "751b521de6384a017caafa10419fc35d58f6dbace86f6b533c117e38dab1d689", + "result": "valid" + }, + { + "tcId": 105, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c73c71d856cb949a31c249c1e99b11ffb698cbc1dbf4002e956cdeb655f84045716e98dec10a9905fa1d3a851f4f1fe617356cb56d5643a148eec376237a27f1", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "f282a78942218fac638eeb0eb15098f5aabae15b3ddb7abdd40a8ad3b5540c8e", + "result": "valid" + }, + { + "tcId": 106, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004acabedbe760e9330af3508209ba0081b9ce061327d1ea0b6ffdc577dbaf28e269cd00176358828215d30ade0cff8cdc0856c84fcdb424feb93ce58a2554a9bcd", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "6aeb7004f6cf6b05f30bf481e8b32a1e25fc66d96a4a53165727bb304cc27baa", + "result": "valid" + }, + { + "tcId": 107, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044cc9197bfdef17d33a9ea743bf83747b564d6ad11e6080957a9d3ac44165fa793ce20d13d431071be367e592f8a22f88edee1cd51cadb0845ebea64b11c45708", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "67b5a9926bc58025c8bc2b9504b72c3a8465173d70f5d5ec1580fe88c5a4887b", + "result": "valid" + }, + { + "tcId": 108, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fbf411afc88358dff2ba156ce273d7b15d0ba3980a60a82eb38bfa58995e163d57c62e53070e8e6cb1df4ef509eb2598dbdb07a5ffd71301eaa2892ad1238f4a", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "12182c05568a6b18a98ea19110330146e7dbc49274f324b5edef4eb861f72bec", + "result": "valid" + }, + { + "tcId": 109, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004cd7863adddaf0099647139ce64ca0b39dbd312ccf96c15a62f2c49e628248235999f82afd0f76e744afd0fca2aab36f22ff7ebefd8e541fcb6e972704b8ac521", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "f75920e61e7d05c3cf4107e5e81f3c1be7ffb0637f0ac8b895d87361345d9a87", + "result": "valid" + }, + { + "tcId": 110, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bd4fd857640a6bdf5da42ffc5c2c1755c4c125a99d380a5935eb1c4c3a9c2a3a4760df25ca561724a82e3f9c9d782536db4310d6c9c769f51b733de44a9c02f1", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "373aca70b036b70cf8e46fc9457a8e19c6821be2f2d6c16edadd20d7b30eb3ba", + "result": "valid" + }, + { + "tcId": 111, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000445654b3b66065743ac86854daa77c9e5cf713a402fbd4ada365f4f96bf1717cd63cf23ba035de430a2128dab0d2c7b939d44c66624f6979275cd37cd02370669", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "caec9de4a74d76603c5d5d07de2df0d435bef2b9063b5123305d2fcbd5dbb318", + "result": "valid" + }, + { + "tcId": 112, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004dda793fe7fdea5c7481c756f59fbff48481777a54218d95eaa24e7b86d8a5858fdac18590cd96e193db51c50307d2606674d5b8afcc82d1b672dd8e09719a6ac", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "27980511f433feea84475b82281b1fa6b946c97c646738d5ac3345250f86037d", + "result": "valid" + }, + { + "tcId": 113, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042e043b851fc5a5f12deb76fe94182b99bbce727b476783f9d868ad3ab7ac7a251462b469c2e02491e05a3a4523e09a6be8e5b2d10419cb7760a8503ae4eb7e7b", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "20b27f84ae128f674e144d82bcd1544146bfd0150b0843ea585314f59cc54aae", + "result": "valid" + }, + { + "tcId": 114, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043d8fddf41e52320c8081e0d60f5397993abdfa979c4b5e832ac61bf3cc2e6fd94504fe3207dbd18ebad2b921a52a16a33659939c16fbb9186caf5e2cf3170346", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "92592791ff90b595dd2ae7ec039bf6b7bfeae7f044761f5e7fa86564ebc46b2b", + "result": "valid" + }, + { + "tcId": 115, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000465106fdca0c408738c2316f3ec2238d459157bab2c2855323b95bd271c91dedcd9fc2d685446789829251d293a50d150df5f1fc1a0604e4defaa9a8e3f8c9169", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "8e61b2e072bd1401da12a3f3d8164daedab0bf0ca795bcf56aff81d07caf7281", + "result": "valid" + }, + { + "tcId": 116, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004320c813548183aadb0e7d21a0ffe472bfa9b4ffe815adefd09180a3ae2d15fbcd0ca20611d2232847aa80e7f7691c008ff886dfce550f90c4c19982ed779b466", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "a41170f616c5499e289b4893b3973e1155f66ff354ae6a812bcd0e33bd7dd5cc", + "result": "valid" + }, + { + "tcId": 117, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a0e2b1a92a6afa9fe68424bc63dcad620b7dc844e4571f5404ab9d18bf08545ccba1c1ff49bf7baa9be1fc0ac4bba63b41ba7a374e15fc39b884d80a75b07092", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "b8cbc27d4ea1b25f2292292ae53a3bb954b7ca77ccca5b4dccf1b958b0aad163", + "result": "valid" + }, + { + "tcId": 118, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004dc97139a3dd1411d74616154aa0d6bce787cfafbd8fd060b680b04b422b0d22f6ab50e5c68e027805953bf7c3be40a8f7c9b56c6dbbe86337e6163ada01d9d63", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "4baaee93a752397bf2ad0be72ac82b0ad2417e167bfdfce4904f012d4c33fea6", + "result": "valid" + }, + { + "tcId": 119, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040978d42e1594569589b578266cedb6088a84c9cc9baff0070dc1d934342605e62ce80a966b5ca0344981f4229c7ab622a853bd9bc59b662ecd92df238e4e46ed", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "3b3d86187d05a0012d83be280987dc95b1c0c9b57f253b64530d1d4220aa4abf", + "result": "valid" + }, + { + "tcId": 120, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a8630a7bdb78a970a01b20c3e7b95d25d3eebdc8e94ecfe0f508e4136eca49afa5eb12114b50ac77d68d410cd5ef5107b2e68f08600e5e6938c452d51d6993ba", + "private": "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared": "472d4b34f5be6b499f76b0d9e439e115f6a89b725d9e9e811185a615f14007d0", + "result": "valid" + }, + { + "tcId": 121, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c4ea8ed31ab4a8c994a965efd4770bbb5e26ee54cb7217ffd31fa888c108feca063c415201329dda130f43973f442ad320da0ccf289cd1b71489ca0a7201d5a6", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "fa67f4a9ea34fde196a7dff6bc1a2917b1526d54950335bea2abe22e1edab410", + "result": "valid" + }, + { + "tcId": 122, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000491780d1905316105d6a6aca94a0d4488d134f985f7e29adecb1bc6cd0c211a788035b06e495d1e58b085bfb6720bca84557b670de34587df0d7e3aad5bbc803a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "95c131de0c89e5b17f91e56779c1571de2c8a20794084fa274eccc8eed1d3d65", + "result": "valid" + }, + { + "tcId": 123, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041961a1a4b29671f1d835b313ffeba4d8203d8414cdc0ea11e47d619b47038b1de50a63b89cbc8956a5870c6c4830e2102d5281b9b5dc127b1052fe7b3e11c438", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5bae6d6d23a68f283fe0de46f1d74c0f52e278cb181f55c4353f768ba162aac7", + "result": "valid" + }, + { + "tcId": 124, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000429a9e7f25109a8c4bd80dbea05fbb46aade58797c3b2fa5f00f0f081669ae39d2c78fb1160de6eda50f472ba659d4f1db4ea6e297244b6ae68a051d96e62e75e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b4fe1201a8647be6d6d59f406fa970cc858f5a46a50a6ae9d992c0e23f5e2ad3", + "result": "valid" + }, + { + "tcId": 125, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041617dc03d3eea42e8ea2c5bd034a38c5a3d74165a548074b7b5765ccd8465b7f61089d6dde53430f34cf8285ddbc584d1543fdc70c2333fc315eed4e930ac3a1", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b721ebc7eb1b09438d754ae80302b2a2bf40f866ec507540ab5120b22f868886", + "result": "valid" + }, + { + "tcId": 126, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000420e7a1358436f675f3774d60954b5621145b8f5260b5503636f54878ecaaff8dccaf2fffcb7c7084e325dae5e24bff5a34e37980d1722016dd6667da71f164c4", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b8da5d1bf9419e2b876e708871a9a29574686689bae8d87985d72a4e573dded4", + "result": "valid" + }, + { + "tcId": 127, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042759bf4c336501340cbc67afb4a8f5744f9131d973966a9de50ded60fbe045121b67a9e81e53b064adeddd16a4c030dbb189ccd7019b329d67a527c311723469", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "39aa2bbc4b6f30c268b19909d5070155c39c60649b7a2ebec266bdd18fff8cbf", + "result": "valid" + }, + { + "tcId": 128, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000419b8a10f5021f11e29e18611fa8284b7e9a3f67cf36eec8ecc4d7a5b54803411311a8a4e199d98eb358e19a27e80cda6af142d6091ddaa9370ed610453abc6c8", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e40396a908c2cca4504f4f40be394a12244ae184f6909ec725ce723485bbbb97", + "result": "valid" + }, + { + "tcId": 129, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049ba841f41245ac08955966470425593290b9e1d87bda8f47df19048db8e3d83097f68905f360ced26801872a7ff124c3637b02c4a596b83abafe7bce567ca177", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "13a21dc50cdfaeabd572f2d94dc0f3f768f17f990ee59d7f16ace9bfad8a705c", + "result": "valid" + }, + { + "tcId": 130, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000468af761d053dee64aca5e98f547feb2dfb6f5edb8138011c7f5c33809b4b9e00466dd76cb8ceeb5132862052ad3e08bfea245ef16ca0d00ed0c4b45fb6bd3028", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a82fb3bbdf6d69c7398ee9020fe006d5b28c632f2da357393fe58deb8d27fd08", + "result": "valid" + }, + { + "tcId": 131, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000405dc8b18bc286f203213b1319413dfa4911d6c2e30f3c778c55e4e5f5d9bfdbacd0b3b209e76049895ae80ff63c0225a563228cd99243f628a9dbae70d773c66", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8fa44f09cfddef86aa9007cd4bea6f0bc9b5b2115256303df09f8a20909c5271", + "result": "valid" + }, + { + "tcId": 132, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bacb606384b1930bb4b74ded236d03d3bb1739a51b73f20dc3349ec3b383180a6896ed59fa0b654a9c404b34fee2c767be2383f4b8b171d2359806b04b502d16", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ef762992d22bacaf06aa1e482c0711046b52e0e40de2a21d4e38df0109ad67c0", + "result": "valid" + }, + { + "tcId": 133, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000448ab89b2a312de510a6d3c9ac9e4c4f5b46e04d3f858433b7646e46273d94dce4a0c7da616388f1eb8d55ece64ab695e5405d779c92f3bc2595c27d65def8db9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3b0936f22337ece971ee102178f37bca3cb69b50b8ec9c9b47334c68b5d4320b", + "result": "valid" + }, + { + "tcId": 134, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fd9de304ea5f18dd641510b9809473d39a2373ed5a470ffc5ea7c83093911b4540baabb9d912279aeea44379110abec75ab7994a6183c6294bad27bab5bbf821", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ec571878fb1e3b1f5d4f66b8b080bd4e50410b6eeea4dcd3cedd4622bf876160", + "result": "valid" + }, + { + "tcId": 135, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bf8976a28221000d7f5219fa8d06f9f8ae47be626f89c2bb6c4d0323bf02f8490c78bc948c6bf82a191f1de972e57db35b05918594ccfbe8da19bd46facbda78", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9f3d9de87d9cc5099ff4f56d913b98b5eb1260e2b3a2d7a3c5e01a7e68219d10", + "result": "valid" + }, + { + "tcId": 136, + "comment": "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c3229c9b4f409a6539484152b39535c512a66748972025165fd888c388369fb3298cc41dda36fcb15a0d97cabf757bf0737dae70829f4b9a1d499d9e9911673a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "23adda6571d4ad7e940c21023af3ffedef9d8f64e83cc1cf6e992d1da1451d91", + "result": "valid" + }, + { + "tcId": 137, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046f2c3dd84b44daca936a2edaf43adc8c1bd5f42801231718fce6f5e94d144717a247598c11eaa2c507b0e96dfdd03294cba4472ae8a2128e36f1eabd315aeb25", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "91e70bd8bf85bc6311b2cd7791b7edf00e22f9cb8bfd72571ec9a03bbf716f37", + "result": "valid" + }, + { + "tcId": 138, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a511b09334f032cc33ee4ddbb839304f6bbf1daa4a80de524ca24ebb65a0a92e4ea48243cf7e26deaf4de7779ca71f76d9dc6c8c1b7f44cf190fddbe82c2c940", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a7d2f3e3faa772d7a86026e2f183dbe7a298ae3d1bc3abcea0df3c11cae4ca60", + "result": "valid" + }, + { + "tcId": 139, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047cf4a6ec110db892e45a7b2ab38b411a6c41e86fd21a6455ca1a4c2e2220681309b3e399ae30098bf872c9aed5db69d14cb71149abb05cf5227a620c4b16b740", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c611d27e7cb52e7c56cfa9062e59f3defe7c1e225727b9049384a180bd1688a8", + "result": "valid" + }, + { + "tcId": 140, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000436c7dcd152fb7e53fd16228465ea0c419da29cc6c79fd4266303b3bd06aa0b9036363a959f8c0b400da525ad7674677f829092ae7f7e8dbf88397fcd19047af5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "661f5d36b57af48982e44ff89ae75f849a08b1daed6417a20212bea88c7f2f8a", + "result": "valid" + }, + { + "tcId": 141, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b61d3cd27bfa1269234a777e118f7db10a3844e8c7d1162c099a8099d887dfb849520e9a038f8ba8804d44f22b37452514f0aefea93bab7bdf180db54485aada", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "540e255f6cb58d237990a7437cc7aae770428796deb607bc29fbf0a4d11873c8", + "result": "valid" + }, + { + "tcId": 142, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ac9cbc8bd917192928d9a065fb1f89be4bea850186fd466a7a9014066ce002c51a906c90eee55cb5692f0ac046746ee4bd2205fe5f435d1e71f19a8cb8550f3e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ac6705af9d059cac9977967c0ce514d70dc51d88fde684123a921244933ba8ec", + "result": "valid" + }, + { + "tcId": 143, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c050d058aada9e43767f1f760abdbc421ae220fd01e832ae81c628bfb1277c99d35483fe6aea51dea9c017c326ba7bbd4175687a72dc5c4f449eed0c53a08052", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f7a5b69bc39a976bfa6644a152789c3149352093b1dcc4b6b06f6c4c7c90fdf3", + "result": "valid" + }, + { + "tcId": 144, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004399542882ca4d5fae3282c4edffc3c7eda7c451e46adee4219015e91c8c69cf8b123f8ede48ab76fe2c9218326cb06542a832d0a32b7ac0d485b4629bfaf0d76", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f0587fbd10e332ad297b5e463d4f09d2167c8589c46dc6680c13b044a34485ea", + "result": "valid" + }, + { + "tcId": 145, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bfc304fd88ad8f11801d35286a49505cf349403d8100efe903d078efd5d3a66ebf05d6fe2a14c069902f0d8eb6800460731d48395efac4428ed87b00f3fc6fb0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2fb4991332a5d648df5ca6bbd08575c7553773a97312303440cfe7e43d3a268c", + "result": "valid" + }, + { + "tcId": 146, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046881678d6c6d8ceb01de5d6664a0b57b470f149492e8e7513e121fad849aba1b2ad34db024ccd2694e497f6adf4d3cf5adbf518c768a4628bc2e159d0949f2aa", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "cb65082df5f54cdc668625017cdf45f22f305a8f34ad91fabf36c071496c84cc", + "result": "valid" + }, + { + "tcId": 147, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e38dac9ca4ef5b35da77d846093e0d29c1ca350e72b5a6ce901bed9f472ea199f805fc3202920782f49f4b6e7257a4364dd5451d982f29b62d5d4b8e07a33068", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "6441ac7be81c2fb6472655528f21454d40236a878fbac2ce31e4358ab4ed02cc", + "result": "valid" + }, + { + "tcId": 148, + "comment": "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042d8c6732e3d0e1822193243bb9ec3fc2c7f264e94ee61b295de5b3c10db937f135343453838114a4752a5514bcfb9dce10f83e0190c540fef10675cb42584a05", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0b586c442eaf016f382199729f60240ce50c0f7107c488a423d42794db5f6663", + "result": "valid" + }, + { + "tcId": 149, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000420bec8d2b5aae1f955b7992198bcfe20880494150058cf6151fe14f6071bad3132dc1ce503969b824c5a9e23aeb472255dd23f97d02f68281ad0269818b17e49", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b376d9bc1909eef92953cebc3bd6f2bc0cd6cca620c190141740f62239579334", + "result": "valid" + }, + { + "tcId": 150, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f456946770af5d069d60b279ae519ea18e719abaf5787476873a5e61f969074d47eb27520d72fce10650d312a5431bbd6b3f37cd46755b7a8e1ef1a796f90908", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ae739f624ccb1f0ec964b2d1896d2df83ca1969ad6ca26b334342013d83282aa", + "result": "valid" + }, + { + "tcId": 151, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d1390a944d24f300fdab9bd272bbaca056feb71c0c37468e0327b08504d55f3a80a4b240565aa43be8f3e2089b4788049c5d378b667e987e01aa8a08a4cd2c95", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3c25126ece58ad8e93ebfe6e7547b05b39c6d9858e559fc01ff6b6e50b0a22ac", + "result": "valid" + }, + { + "tcId": 152, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043e61ff2443d10b1e25fb0ce19f57ae39223d33fbb0e5ee2b4740fa19384b7d0e1408119a70aa9b230d9f18269c065c53d4c2619673b49377af4cdd536c931aae", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e47d658df5c1f9599d4e560954ab860e9a6377decb0b56ef3c13dee36185b2f3", + "result": "valid" + }, + { + "tcId": 153, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b06028d729039617f912e86d1d1f44e93e63aa216ab0641813d06c16a3edaee979d21572f9540d7b07b0a6667f7e0a9452f6f9f3671e522e2b497eec138a46ea", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d8279c1ec95189fe63d75d1c6d7fc312e411a3d11e4d671a49fa17fa36c3cee1", + "result": "valid" + }, + { + "tcId": 154, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040a8f74cee50d1e853a38c026f627fe47d81fc11f886268b35379a32ada249bb91d63cf0198e1c926bcb65ce21813e4d72118b7092a5e8bc152909222ac19603a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "077c7a4e606099d781cbe5a89caf7bdf4f448b1c0d7d3097263a045170275a3a", + "result": "valid" + }, + { + "tcId": 155, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040edb7020cf4d6ab14b5a3f8f698d66eff983588846d718b4845d674e7bbfc0edd92a27e40e5ab2e0cd2d0ac1ab679402ce36f16d3ebfc0fd9df817dab17292d9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2025808c609ab0b07924444ea4aa0fa52563858a53221f719c91b15576f49ea2", + "result": "valid" + }, + { + "tcId": 156, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f06c77cac24a6ee51421863a0d1469418f0a6430e062da18f27dd57401c0b612032b7e0591455ca33b4e49e53facf5864410ba046ba5d4fc6bacfea9a0782ff3", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9832405d565c97ba1d6ff46e1d8fe33886222cbaa69963868d12a8be07abac6d", + "result": "valid" + }, + { + "tcId": 157, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004cb2b9df4ddc430df7b0befcb5a826da1589a15bef1b6b25f1201daab5b2fa4ac3801e27d112f0f3276722dcb58b8b4f4844a2e614de49db440b7cc7620812734", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c4bbf44547e8128b9a46ed92ceb07df691e2e91d0b47dac0dc2afd14121e7a80", + "result": "valid" + }, + { + "tcId": 158, + "comment": "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000445206b62e4a3c4404c74ae8695cdb905a8e6a9456da09c72c72eb7712d9d52e81ddc2d56b634e4ab66b798cdb4db86cf94f02208f747304ab3d5aa2bb125e137", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "170a91aa8196df6f0d09ec197fc526996ffcb6792880f01018b3327a096fe638", + "result": "valid" + }, + { + "tcId": 159, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004584d2dc258bd4650e6fa04fe9d3d2a5e768d795945ed2323f844d0a8fa0c6fbd5f96256b9e1b7263fa00fa758cd6be15d9f6157fad66c729ab0dad694564e834", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ed527e31223f175aa786f146b3fe0561a41b1051d5eb32249790481eab1ef381", + "result": "valid" + }, + { + "tcId": 160, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046c5527898ae8067da56ac82caf338c9e7f40ee4489115daf0aba923a8b6e501e430f5970ce9d01d03ec076f8daf685cf4d5a9ccd5eb9e849d43ae2f36f2e80e5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5a74555732d8541d2f73e3a59eb31a131c8d41464a1f2c37531a25f4a6d3bfe4", + "result": "valid" + }, + { + "tcId": 161, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000452cd9924795fe2a251af7cb569f66d9141db894545d798a0db3d30e50f100fe204ea81c808587c90f3f2c94d993c2d0cc4be64dd6aeb9dc81c70d78885b2f776", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f2750c996f22762629a3f808da6eedd7cc72af4fb0bd816c86e636264bf57664", + "result": "valid" + }, + { + "tcId": 162, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bbad8da4c018bdc15a5af8f3da4b384c530ea75560cdfd242bfa3235d8d3595f734cbd866487b83fcb84a4ac74ac548f2535b79b57d02f03a1a37e2791a096e4", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5d2163ca850749991cf782c3852e86b05e6b05ec8662905b60cc7b7e37434fbd", + "result": "valid" + }, + { + "tcId": 163, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004389aa52235043bbd759868898bbe277ab996ea9387bd7098b0072442bd2b42f5b823364e9144a1eef1f10093fda0c30168f3004e2c2ea74fde4978f3aa1a31c0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f8cf2cccdcb53b3d3c6d1990ae16c71ad9d141ca49f8574a72047ce6c2da950b", + "result": "valid" + }, + { + "tcId": 164, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fd1bac144354cfe1cd4c64aa3a2f77f0aefa26cc5141082676370a0f1ec92cd8fee66992d2d2fcb87f90da0a6743378466655519bc782dd7b0ab570f6ed451d8", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ccf6e14d1add6e4b5a4228e5aad0b31fac4b45e2112c1c767e933c6a0c3f2edb", + "result": "valid" + }, + { + "tcId": 165, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000478c926b0ee01c000c25a83631219f08d8b34745d2ea2fdc9ebdc5a2288fa9b0306bc00ab3790508e5705eeabfbaa0744719c9bd7b467ca4a37a06f6fdbe6d86c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "57556459e9d32b75a13776bddc8f547cb64708133e7917b61e3697c392003de7", + "result": "valid" + }, + { + "tcId": 166, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044cae5606bad6013f7f36190d7254cbf0d5a92b338e4a47702a3c97a3371d7ec280d273dd598c20392c540e58bec9b180406f3fa6e6c529a851bcf2b96d8f3809", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e5490cb494bc6ab2108da2cb0b926cd878712f54bfa72b59f702c180c62b0c91", + "result": "valid" + }, + { + "tcId": 167, + "comment": "edge case for computation of x with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000408ccbd74f297fe71ca3115c0b1ef4e0421b99ce91ffcd4b72a530b22993e18e9ba0ae1bdbe1c2836ffe9a61ae5a899f152c90b42823638be4d51dc3afa99e6a0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b3ca753c1e1067b550736a66c0d6b6f47e9394c56bb80b5d4204fbec9e59b490", + "result": "valid" + }, + { + "tcId": 168, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004aaccef834f57e6c5526fe92748cd8cdc1375c2ac71139f5d2587305bd3fdd3cd965dd5374b6a319850c23ebc2ec7a2deb7ff3e428679d4afc9df7e75f2e06e4d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b0cf8c178ad95952520264d0f4a24389bf1b23dc7ac1b65d4e8fe822dcf20d67", + "result": "valid" + }, + { + "tcId": 169, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a585e1ed6e47224a472cf4ed4ff34e6251c62ac682e4b70992d5002f08d9e203e9b7b28895b9db4016e5d94a9f59385c16db738a83b84e6d43ecef820c55d462", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "15e40dc49ed62d35e8c91999b05068f419238a222deba206df47d909d3a1f40f", + "result": "valid" + }, + { + "tcId": 170, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b104d0cc4a987771655105cfc840f195746e112334c54801fd93f4be8b114a1d3cd8cbcf4b274166f82cfe57393042e3534e68df2f4c3dad1b7ce72b47cad256", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e9458064d3bfc444417486ac1334a93c9aa4468031134ee0196ca6e31713956c", + "result": "valid" + }, + { + "tcId": 171, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000482bed3d552098d2fc9e02f1f3cc32f5f31cf6cd101bbb8b42bc6f732badc1976229257d92b241f2031ecaeba10f1ac154d8a3bea309328231272eb6aa01aa65f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f4446e98a63b0598011baaa4f930513218e8370abfbd46f721c8dbf37e170d85", + "result": "valid" + }, + { + "tcId": 172, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045c4fb681213bf39b68e7ca914d2830b12a7a32c96a9c788ad2987c009e08d0a376a02ccf594c28995cfcb285ed5d91dded92921108a0b40928487cd07180ab21", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "dca827687aa24f2fcbcab5c38069f4860dee6698fc23908b06c7dae713a141f9", + "result": "valid" + }, + { + "tcId": 173, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046b29f8c006869ab6be793ea72b970aceebb7a4c4b6fbafecd1e35713a28bf284c76b07dc14f1dc533f1c4ccb0973eb53e53023f0b0f1a8914c7708c2d73d4817", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "19714f1d4aaf8bd61520b647633a8e53099499ac368c3dd6f1b084891619b0c0", + "result": "valid" + }, + { + "tcId": 174, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046e6849c2b07a37c4f36be911b323e4ce70c18b15902612c4fc0fe6d91e7c180de925544363c68035498cbb2236f5c1ecd0e4b2cbb5801a8cac4d0883f651bbd0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d7a2da8de2434e2ad264f9706b30d0657c727606d8285d2179800a970b4faee3", + "result": "valid" + }, + { + "tcId": 175, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000433649a1e74c7ffb5edc3949c58b7a7f4b5348288f621c50fbbdb714fa42aa793cbfd969e077b00ead21082f0980009868f79e430ef1c216394bb0e9eda135e9c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "853d4e01d4dd4c9d6e7820adc16f32ce7bfeec0d578deaf28af9cbb3315e8f1b", + "result": "valid" + }, + { + "tcId": 176, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bf976ef204532bf67443e8b8d9987a683184ec26420329ba268e54e90b480de0beb108df26eda91eb4fd23d26af6f2d78a4281d5ede075c2c715fb1c4f876784", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "35715befcfded16e67fc0dcebe945c6264ca0d91b3663bd3ec0722b585e5d652", + "result": "valid" + }, + { + "tcId": 177, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042c435d9faa598070b4920277506c100de62a7df05c34a39317785d628d74dde3c7f5d0bedf54af1c7d21ff955128002fd5296237384723fef1fb806c2a6d8ea9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2baf108668e82b7fcaf3f5e3272637b426c551d8af0e55f5d74bc317a4474767", + "result": "valid" + }, + { + "tcId": 178, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043819dfaab5537863c8dbf406ac18dd675619c9a7a554620ad8a14492bba425a3d68e8c68181555e22362415c95a31724ebfe8b2bf1764e209eae9e53b3f462a0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bba443b160997aa8b7fb2748911dc2154c0f6b986fbe9a49e0a2934fa5f32954", + "result": "valid" + }, + { + "tcId": 179, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000470ad3a9c9a9db71d420abae84ccdb12768851bac6a82ffd03d89621a50a7c311bfff7c664c211f93768f84b5255d95c7f67887c3305d789d7fcedc2d29989f9a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b4831736601e7387050ba3d401aea241c3506b56a0473886c408b366c8696429", + "result": "valid" + }, + { + "tcId": 180, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000458391361fbc8115c978e82037814d31aa3a88873ed6c74c4aaea9727e300d94542924c67b5cf828be827e581dafcbd16e653e72a4f2d4d0550805387b9417e77", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ecd0c9e1acb90ff8bde88f7757a089cc86cba27f0d15fdf737ab3b8ecf9fd9c8", + "result": "valid" + }, + { + "tcId": 181, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000423a2be684b0b5f04bef5c6ca8a991bf752f5964f6fdf36d7129100daf80f1434b6f3ca2a5e85ce005e1cb6d2b13094c434fdc1c095a3ae5e53f64949ca56691b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "6b9ee618598f33c184cd63cf8930a4db3a2d4ea022d50e63cdfff85734a77ab4", + "result": "valid" + }, + { + "tcId": 182, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004147b8a2fb4f6e85eead81ca0b3f230b8d8cc230de73107d9cabcbc5b39e4e7eadaa44ec1ed0b95f6109223bc480e917419d860f9b9a75f81d6f8ca3ada377533", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d801dc9354cb756e6c27de5a7cc88ed5cb214ac5091b4090624ee8afbcba35f9", + "result": "valid" + }, + { + "tcId": 183, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042b3fe64bb142789e89e1092db46b613012bcfae57759ea908165c0362f804f36c0053faf3266ad7eecedcb24636b99c935f1c8e73168f0eeb3ddfb660801e55b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "03307ea557024686910d2d1d2d2760d82664413b8feec66ae8d2dbf1025f0c45", + "result": "valid" + }, + { + "tcId": 184, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c4ed72445465cdb44f58b0e1af0823226ea79eb2e1bc3f27fb8e4ce7b85f4a30c237e574c59a992406fd517f4d905e03d7a2b0a40ef85aa3c73bd46a1a06a918", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "dc2cd94321643e89dcc92acb0128d886b28cb7d66a0eaa5b96194465708780d6", + "result": "valid" + }, + { + "tcId": 185, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000418ef4e2fadaac1b982a7d2d12e9d5148ecf336b1d3775da2f7df822ad49a1324bd07046a3f8e949e7a0d960fe9d9a1de0f61497cb4e7b2f39aee6844396f997f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b831f4a0fb75927bdd2945c0081f11cce871c9d6dbf83b7895748c3f46375ac7", + "result": "valid" + }, + { + "tcId": 186, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004398ca1a944210a10b1f5732071259528df87d42d3d7b006bc6fd9e1e09f6fa30fed379db3f1bd915db2ba27384ec13715417446ee84fb5fd0a4bf6431cfd3f15", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ed607a9e6d41a4bc0535c5161c98613edac6b519590b481420fb2ba1ed2c35e6", + "result": "valid" + }, + { + "tcId": 187, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d1c182adb101ebe5fec3910f80058e091d1325433d4fd3bbb38eb75bcaf2698a21218f7544ce84dcfe52e817ec0ba6bf84460f49932b3ec5ed27682d337f270d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "64a68fad2378591a18f8f2a4e346faf59da29446ec16b3fb8c37aef2d79faea5", + "result": "valid" + }, + { + "tcId": 188, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043f68c4e412c57da015568e0a9fcc3db499b77e6c0f55050828c50c35493af5e3d0b53fe30b0c6cf42cdf9f4f01d5c9058f8169b241bdea225932f9033f8bc5eb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0fddd50bb27666d4d38e6ec18c8ae1be3d763be7dd11067213e997fa4059c67a", + "result": "valid" + }, + { + "tcId": 189, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000456dd4c2b1d7a1a2d6559b5203fcb8974fa81be7d64cf0ae7a14fd965dfd69cddebe1ca78d5583fda3487040dcd94764f8dc619e8d74aae8d9665f340693c21b3", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9c412023b7a66ebc9579a8d16bfd3109ba085c42f3fd395e07534529ad2340a4", + "result": "valid" + }, + { + "tcId": 190, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e1e5053b6f43b8714a025acfb86a8f51195488099b1f5d63310a6becd7ccb47ef0d16bc0c3234470ffa8d45f582fcb65ff9ccaaa6ae0cd6b572bebaa50c17741", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "28717726dc3674abb4f82b66837e8685ede16cb0cd965824352ac0a2f9d893a7", + "result": "valid" + }, + { + "tcId": 191, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041a46571a1438ca23dc7912a8a7b2245d70c852a6e9f4d385dd608427ec3c41e7fe06e2dedfbaa376a614657ce61701a7db181e5b1f3139045b8424ee54964b7a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2e74661109f0cbc6d587790330d67988658bcfabf1f7498a2b3279212828e207", + "result": "valid" + }, + { + "tcId": 192, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048ce5a3c8bd2544695a005841612a7c5d05beb07cf7bca1027172b030acf7d275fba0c339f74ce36d104fffbd5ae1c9c72588693190ed2b3687433087213b5bdf", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d202df6662ba06d3088363c60e341283f7b6300104d58cf6d707262be6972b59", + "result": "valid" + }, + { + "tcId": 193, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a0abcdb1ef035e186e720606b07fd615532039275ac1b6f22720b756c0f857cf76e465cfdef30602b2e055a303bc6e176dfe972d06cc6f3821780387bd6357c1", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a54a81c18f4b7ab0f3702013678566ce29e91c4142114d62f867a5278f89cfff", + "result": "valid" + }, + { + "tcId": 194, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004859b6beb70671b3e64991bb661180dbbe835f63c0a5878c3f83f0922660a7c093389bf4ce6b5c1c2f801c84c54391d53aa953ead5e51b7757b3508345bb4cdeb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9a954112f52d76709d64739dc75e9ce7a76aa19242b306391fcf25ff92b76901", + "result": "valid" + }, + { + "tcId": 195, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000435510d43f4d1a173a0467d5cb35a4170c3fc407e55b416b4dfce28650f8802afe8ef2adbde8b40a1714286176d674489bf9acb2e4a8353a7dae1a9e97cbb4150", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8763cb235f2780c1bbd35fe6c387d5505f72eb0a77b104c775c2b3b42786d7c9", + "result": "valid" + }, + { + "tcId": 196, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fa4af089c14d6a8be1881135989411607160d141a7a8cb4546f358a797d2aafdbe0086796436344daeec063f4f4a414a8779e72a960892335acdfbfd452f727a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b9309ddc5eb64a4d819a8a332b061a59f163a5f50d4865697e4d123efc9b2b29", + "result": "valid" + }, + { + "tcId": 197, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043cdcaa086427023bbd91b5b2e212be77de5591a1a0c210d54f0482f27c426558f8e1f4fe6e3bf037c0e03d4043c1d9b25436e0803b1a42b6de2e40d99e839c68", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "87e9f5ec4a9091d94ac22a6a71408213f444be094c618d459682e17357631939", + "result": "valid" + }, + { + "tcId": 198, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d7adbe30a5682acf9d398f58da8fd3b583283d9eda74ae067b9b533cd6c0824cfe50d0371c0e7b59043ffad25e17445cfbdfb3fea40e55bc7de19ac5f27c64a2", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c69a00017184a13c713cc0a70e89c60174361d07dea5085fd707f4b5ed3faead", + "result": "valid" + }, + { + "tcId": 199, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004029e1c6eb37c383fb4e27ebb3197688f8d8af755db83b7628e17579cb3f90f058a2bf57857f5ff6331cdcf87440b6e69cc1b6e444ce540b8222b955c98a99955", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c139b75615e1010c920b07d14f6a1980ff4c97a0a9bb8a097aec2a456b6bc4ed", + "result": "valid" + }, + { + "tcId": 200, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043a35de213b2dc33eb348948a22ed5a93600fad071bb017a6a250e6609b13f7cafbec06b663a5f54689d0ee6709fd0da46acfd26038935935f749d6d4bc21060f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "70aab5e96e4991321faf440ca2dea861ba007df08ee46c6f579731ead51636da", + "result": "valid" + }, + { + "tcId": 201, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046b910d9e9943cbeff717ca9546aa5677e06118f5f04a0246b5bab73505775d65c87a4c1fd7bc584c56991119699b90b4b3a568e508eaa83f118332da9152b13a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e2ae03b844b3f279d5cd16bff20ab5cad07e4c984f21cbe73e1997a02bd2c291", + "result": "valid" + }, + { + "tcId": 202, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f102b90ad378725fb7ffe3fc3fe6efb320a728a03ce09a88ee25bab2cf133c04af2cfee528f3913c83504498ca8b3b6deb9e284241b8d01c678ab79ad8091888", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0aab6b19e4205548f929362e72b077f2365667bdd81d93a404343e7a5f84c6ba", + "result": "valid" + }, + { + "tcId": 203, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047f420fcef93b0b9d0a9f86b2c65e18938e17aa84eade2a7a6440adec914cb2f6ec1663baab8af308333399adceff908ee33c8f86b3df9ef93a51520931f851ec", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d96cdd08e6eeeca690989b659024f324e18c2faf5c50958da6985f70826095c5", + "result": "valid" + }, + { + "tcId": 204, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046b83adf58bbf00da4b77b6c4615925cf5a8f7b72997ad96904855490834bcf82224db940bba028dbddaf3cba949dc41b0db795515e34549fac11a183b89d5bb7", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "434bd68e45630ca1b3484517da080e3c3198ddec5ef1f7e9d2e3425df214b90d", + "result": "valid" + }, + { + "tcId": 205, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000404102367dc53576a8385fc58ee2337e2b9af547e69934fe3ec797a84c225df0c621cecc727669f2e558762b65b33b3cf3f228fe9a9c22223ab71e77f904d6aa9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "aea47444c897f7157f336c77b7401979066d6617b59a01988f78f6c9a98feedf", + "result": "valid" + }, + { + "tcId": 206, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004258340105842ebe760c4fde13e31eefd52e51aaef938c4477d148bbac6d37412301f4b4d1bfe0e7046cb1f993a359f9191fd7bca7c53e039fa51db8a117efaa3", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "486cf8959f7d939c4c79a0715ba7bbf0cc3fa7b2a1d60e86ad097c91e5612e24", + "result": "valid" + }, + { + "tcId": 207, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d9a521d8147c1e83df82b9db62b25e6ff1417ddd41aef3ffb182ad23f27822f7b0ad917462cd2a5abce2ec2c4a4f7456ebdb65db10d962056e75f6f8853d2a4c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5a1f0674b1397b6e653ff6e473d641da4fb9e7bc90a73802739a0349148500fa", + "result": "valid" + }, + { + "tcId": 208, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040b58006e371570686658d458f26faa34ccf8b49fba8234ebd7304cbba3ab1b2468787e9c7ea3043e0bf27aa9730a5abe473060b77c53bddc70e201d7f5b1d89c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9a907514a9ecc85f9659b9e97909a38f972b0c9a7c009778b8190438a8ebc00a", + "result": "valid" + }, + { + "tcId": 209, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044ab8f5ac88eecfcb0394f6cfe5528596b6b4c4fdac8247fd62957289133e620e1af51852e11b19d6137852e218fd64d2ebb567f8fa92a1ed43a5e34f5694a94b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "941685fe4de816261157b2fe3d3ac28195d81fac6225fd3103ee60a0c24df472", + "result": "valid" + }, + { + "tcId": 210, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004903201ba08353ba6158c06e66df0b413b771d21acc0832213bd03d589575e67677a90ccf2f3079cd2ac6c59cc0256a612c079b8a91b59ece1efd076f53bf5b04", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b203eb0365a40624a442572e0bad80e1f0c9958e5709512e76b28f4e0bfb2291", + "result": "valid" + }, + { + "tcId": 211, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c8021be2269a2ee83853e4a12bb0680825088d9ac0e56fb505109f4708dd9d5dd802ad690d8e8b817a815de607865afabfbed7650988f925ecf23fe5654d0c9c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e09d25f822471e647064b5b68cd2ae42d6be7b8765cdc026bb7696a524c83f49", + "result": "valid" + }, + { + "tcId": 212, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a53f7c412c11ad6a362bd2be2e7d1f20440297be86594abbcbea2594ddf9372379db08ad87b536939a70582682cb7570263655cc25a2979f845fd68be3d82953", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "97e3c29f69d9032e676933edb152f2438ec7dffb17641442ce9342e138f81667", + "result": "valid" + }, + { + "tcId": 213, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000446feed4e522963192cbd6c6edabd5175d10f93999a585a045a3026b69bb4d528ed7f6abd7b39e40e08e2126991ed410394bfdabea990abb7b2ca5eb9f048fa4f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "cd7874612d68c907b434bd81bf1b1a83cf9429b24cee753cc228ecbdd6657388", + "result": "valid" + }, + { + "tcId": 214, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000467db11ee0b73071bf3b815864a178581ada3d100918365e7120d9bdec9cd9c3325f5eb5a1b66ad104a5c9e43b07afa4b152a75fa22a3e429af41e459e7993e45", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "621ddb1893137c12147e909dff830859dcd73ddb00acdb4097f1d66e14fe366e", + "result": "valid" + }, + { + "tcId": 215, + "comment": "edge case for computation of x with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000414cdc4f16c07d6e6074caa8ecca26a0186347e723dcedf9aff9dc6fc8c3815bf5d64fe2d7e6abc20802a1c158040cebd614deda0347987e0cdcfd41e09618cf5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "19ad362ef44a36342cf9143b88470d5659fca6a3a30c904271f6d6bdc05e9407", + "result": "valid" + }, + { + "tcId": 216, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000424193c3501ffa77ebf1ee62f7c118b28c05a1c0a946f442b208a8305c6a745f8863603299dfdf5d2bda19230007d0e03ae61fe1caeafa584ddad4cea6dc7d76a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "43bd8cf370257bc88f38b0ded68af2f9d93977234a19fbf67abf2e0a4c09c120", + "result": "valid" + }, + { + "tcId": 217, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004081ceab1d3cd5317fc782c9c8dc33399705aba6899c0b804efa96ed4ee944da900adf51cd31b5000f2d175695d48a12213ae1595b98372643ec0eb400ef79d41", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9d920e7a6f61fe4140bbe56f4317e3892d21a80fb480a091a3c16a0a67a7a97d", + "result": "valid" + }, + { + "tcId": 218, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000413e56b207855eabb4b8a27dfe8d1ec89644be7c096f6c2f3a122c9cd0b8b508bb5b7970e3a1411f4ffe3711405ec65ef98db12a2b37d8c18c8d1984134e85492", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0796221792860298f1b4c5aa1561ec5db01ad876c3552bd96b00aa23ef47b71d", + "result": "valid" + }, + { + "tcId": 219, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045cf95e23e681059f008b32df326ffb7795bdf74bb337f77cff5052de7826794b5cb038ec1fdefde51f6c68dc5e12a198a51ce86b92167883687b253415d6d37a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8cec890842617de7789c3c2909e2d38031d5aad957d995bdec622b010ce9e0b7", + "result": "valid" + }, + { + "tcId": 220, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049c49754a4c45d97e5b70d0931b98f60b3a99f51a95497537bd85ede7e9879429dcadfe273a4086c30dde4755667923e58c463e8d94cbb7d56c9e0f4de79e6d21", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "1d4c7c7aa359140edf907c8234ef16b92f201f562c2237aa32adbcbdc0cabd0c", + "result": "valid" + }, + { + "tcId": 221, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fc7fd984dd0dc3c93846f8b41b07296ea854401325f155f1236f2e4414a9b9da473f38a5f84d08c0ac7a1dab8a568eac21066074947449a8c3d16f055a379bff", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b15134b9e91996e228ea7ba6cb4500a117983c8eeb687174657354e59961e521", + "result": "valid" + }, + { + "tcId": 222, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004337e2e260a3565ff81e0be900c8dafb2ce2310688c3eeb6c025cac208b08a18a4484fc5fb01c2d404da99b56a4dc226420dc3e676fd0223ba3a45d43cdcf3562", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "906acb96120ec7684e391100cf0bb747691678eb3e147f53db886ba0fc5aa70d", + "result": "valid" + }, + { + "tcId": 223, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e2b170d1dc4d9e329514a54f10dc81d902f3752c3a6e2f8be5d820fafefa9d8be087dbd390152ebb04c73b8c504b994a768372d3f920a5cedc4242bf834ccc6f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "73dd087b1cb3c5a07acdb9b0a4a02c64b7087ae97836e943439dbfdf41eac833", + "result": "valid" + }, + { + "tcId": 224, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046702ab6b257c24440bf719c02d2161e4e31e22d55ed8ad0f33e5af9568ac4a9abf87accc758577389042f5b650c37db6b0c7682203156de73728a582bed6a6d4", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f73c49f6da537b2ff30ead7538c04726bc74152535d22b6baf92d06adb45e676", + "result": "valid" + }, + { + "tcId": 225, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040cec0aa4de0c143f5d4c3d36de3db4cd72e8fe0fbd336de879a562ac87e628d8e75d0d0ae3d7b4d869e7f6ff564e21efc30a15ff2d4c87618104fbd42ef5e00b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f4a757ceb0ba6cb9618acd8fef68d2c8fe9901fff14177f27b6e6b8c6bd34cb7", + "result": "valid" + }, + { + "tcId": 226, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049276151fb999ff3f7fcf542491fb62479fd1eae93fc2e7d22c38d944867c447ef0e7185e4d55a1c2eafa2cf8d262636d6e4b353fe71ae3d3cce6b158d86cf5fe", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3eb4a634d0090175347613b7eed6d49b9b5944e70acc3ed98474989d30a4c299", + "result": "valid" + }, + { + "tcId": 227, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e657a91abdcb67bffa8f78565ec796b4901f2991c12722d27bca6a0217f2b00c9bb2cf5f6c5780c70fa8f03159bcb0d56096aeecf53ea5e28d1058c3a50d2091", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "520dff4d04085871cff69b3a20a75b8f3b103da0e468365e8c9287c0a7ad7d9e", + "result": "valid" + }, + { + "tcId": 228, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047c051c1eebc76746eb267e8e91a47d8ab81b89bd3b3a9de6f1c3e6b98db81c7b75df088882150b97e20146547ee07b6b5620bcece4d40a53eeed84e5d4779a1f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c80ac13c5d2e6723e848edb023fc17ecae553781a4aac90f2577fae7511711cf", + "result": "valid" + }, + { + "tcId": 229, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d890400f1230fa80d8d4c95173924e9e7b3458f7e54680ab1834e505a2dccb26f714374c9978432830b8e1b82742ca86777f9b8b686b1924ee55e7c572c2b119", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b0c28a9938cf095a4b0ebf3daa6a16e19e3f4199e3475ca3aa58746f651b921e", + "result": "valid" + }, + { + "tcId": 230, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f44866b8ee1b937d182ff79aade41b549b71ff1bfa882a192ec90dc87a51774d5e335f19880e8438b9f205932664512cd6dd53d5a40a7008fc5c98124a7d9554", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "78dbfec6b4aad2d0a99bdde7b90996324c0f7b9d136a6ede5c2995197d0d412a", + "result": "valid" + }, + { + "tcId": 231, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fd298ab944a08702816a7395f84e45ed782968b701838b67fa2528111cd4f4148599867c89174f00ccf30627815e6618bd2845f35819db0754180535bb4d4b2f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "36a2e77f56c3e5b11e35bf4ba5de1885cf0264643cac5d6f7bfb1ae01e39a6c0", + "result": "valid" + }, + { + "tcId": 232, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047b78d59967ed07c83f0ed7f8f0b26388db76b0863b64ac14b7ecbed8e3a1bda24b49dae1adf948860741376c919cfd50ffcf749672f19f78ad565e88f6096df6", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9f4e92d9a959c09eeddd152f6d95ff2c3157446f477fbed214a00621d014f936", + "result": "valid" + }, + { + "tcId": 233, + "comment": "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004791c9017b3a93ca2f2d03fcf18b4230331fdc3de5785e847c9f51d22caf50cdbedc729c92f0a88233a29a2259e7e6265b92a1438c0b5959167fbe2aa4a65a6c0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d0b16561349f182ef2792d0c2dd585601ce4e032754b7628b3d801f187c14fd4", + "result": "valid" + }, + { + "tcId": 234, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004475786ce215a1873e04a0c67642c319a6d24dffb06a4cffbb15a8256d2c811ec5a1bba7f661e38d694d9a11564b511af6c6632a5efc933732642dd5c4928a41b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5fd6d7f0ba317a36434e1a995bed54a42898d940ee5fa4578373e8d4c23f5567", + "result": "valid" + }, + { + "tcId": 235, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004759ae77233b119fb3789059760112f38e8d9e69f431cf0e8f0bbe6a06e23bc5b18d69b80980f53b7e8c76c9b82dc61f05cdc03826c2c9637cc02af2a6db0e4fa", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bbe559b77e83905b08954dc3736a2752d56a5bc366a5fcd84e042a78c8af68d3", + "result": "valid" + }, + { + "tcId": 236, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043af2b8629a3475294ee0d5437321fcd5fa4554c780b6b18b86242d3edf36f551ede37c4ea319d42f8fc3cf97cfe7dd17e85ba6e11ba260ed991c22ee891abc2b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e62429b8eb322d24e4bdb9a72bf6e9c94d82962b26d99f633e1f21709b7eddbe", + "result": "valid" + }, + { + "tcId": 237, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ca2df3b3d7d958b0d46ed6e0ffe3b7488f2e13660951eb821c24246d6c7f2ec2055e780e6a534f9ff469b0ba3c8d38962ac0acdc7b4b3dc057c07ead3f4b7aa0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5822c168aab9bb6ffe00b7c4c7be5551daa8304b8d2c0696e2d77fe50b9d8d8d", + "result": "valid" + }, + { + "tcId": 238, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ef17ac084abad12496df80d80dbe21dfade58e302ac0398002c5349d852528ccef34500266a5dd3fb454828ed85684a62e6eb142f65f5497e64d23148f757976", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bae26fa69da00aa03fd9028fa84d46b92c13d5e555b2e7b3db0d09bb95d41486", + "result": "valid" + }, + { + "tcId": 239, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004624cf7459a3e097f114383a125c7cdec33b947c5bc0a2679d7aae508b5d46479408cac791f2ed71d9bd594bd66f6ce70d928d3b20fe02b5b66cf743b51739a74", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "97ce8c4b6e031776b19fc7c9577cb26f085274a58407267bca35a97692a2e8e6", + "result": "valid" + }, + { + "tcId": 240, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e41ec556bb3f85cef6651a2db1816dab3bc82898871482dbf1cc801407ce4d1dedeafe8c33721250bf75cdb9181e990492d37080e7dab41da1673d62a8b835df", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5eb5722f98aad0622097d944bb120e09e7a122498b20ae2bfff91c8b362daad2", + "result": "valid" + }, + { + "tcId": 241, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b5c3cb146d30fecfd7fed0093dcba01846a28aa50c7fe3c0cf4b8c5aa837d5b0b21b7605cadbc7b6206e5dd4289e1de9cc36bc98094fb18223be636e6d36e0fa", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f5c9b88d48112041334c574f93313670cdecbe0c0b6c2655778df8ff62025d3f", + "result": "valid" + }, + { + "tcId": 242, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b3c62848beb063fc8f285c0da7207e707c71460b8f792ae0890f2362fc8f02109cf80c0e0d75d2f54a6bffe3fef39441ed0cbf29c8397b76a824ff9ecf4c772b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "effa362fce62e271016d50a0e35c031455fca280b80ed2cce87c83e57e3cfd36", + "result": "valid" + }, + { + "tcId": 243, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000407ad8cd055528feb4b3a53d354c7c7cc0616ca3ff787bbb0bf79909606d27e8a70b4d271ebd8363d9ad910cf4d84e52171b5b359792f7ff8a89c4427fb6afa21", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "59b8dcdc6676029109871fc67b466a7fb622225cd6c77bbc21b1b628464798a2", + "result": "valid" + }, + { + "tcId": 244, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047c66fd67b79f88531a0747288726dbeb299dd8e1159612bff2d979fe4bd1060c15c54c5cf40b7a6b36f4400bdbaa2b6dd0669c3b45a55925635287116aaaff1c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "42dd3a8e14dfe9fe2ebf80746989ba66f28e5460116a02bce24c549d117d6b0f", + "result": "valid" + }, + { + "tcId": 245, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000494064698280e7eb6e14dd81efa9f0ab527fe6ceeded60cd4d422162c397d5bad163a63342b44629e57c09bb490118b1daf06bc0bd1de48a98ea7ac3e893e4470", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b0e1025b39c5481a748a0461aa7773a6b342adead4b4587521a1953d4ff0296b", + "result": "valid" + }, + { + "tcId": 246, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b454039384abb191e593463976dea937428b76a2f21f8553a994e0e23a0de3282888d4e22eaa986dfcd20e5a4c9666a2a341eaadcdf86b6e137660c95561566f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9dd7118006ee56fccf307a31a6334be7e19db2deca68fd45b3f4f94f100de6a4", + "result": "valid" + }, + { + "tcId": 247, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d43b704bcda6ed2cd8cacd64a67191da2f68f25a6a983dd79010b1066942730f2eaa0d0933f710917e3223f2feb23388add3fed3a2a7de18af50803b0b20d6c9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "1fb16336393ba603fb2eb701fed0e982ad32964afae7dbbfbc5a8112382e51e3", + "result": "valid" + }, + { + "tcId": 248, + "comment": "edge case for computation of x with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049ea3db44d3c1e09715ec330d3607a06cfdc1b0baf4f570fbad15d63e1a8d190bdae78a1a46ed6fdaa02ea2785c2bad33aace95397b290eb7c26428ef68494abf", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9a6d03a17e68561a105da66d2fb1d9ec9e3ca6c686f65d9da926849d7af4fcb7", + "result": "valid" + }, + { + "tcId": 249, + "comment": "edge case for computation of y with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e4cb3b67d62108687c74b36a081c3adb9fc4e188b5e611727312b70886e81a795edba4df71b9c4b06f7b052b5b48d9e0be855ffcc2f27926524cb22ffbb9e865", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3c03077e0098a845f7c9b22b73eecd495a2d6a0b34d211154ee3898634f823b4", + "result": "valid" + }, + { + "tcId": 250, + "comment": "edge case for computation of y with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046e833dc786039cb081ca12034adfae41e3454cad0976a09612f1af4c390d589f16f499bb679ce63d15bd4b821392e6c3deb9ac2163d0211a68a6167bcb5dd0e2", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b8454bcf8463c2bd59f7538b65f11b9c98c18c13438417cc08a39c8842a0b7ed", + "result": "valid" + }, + { + "tcId": 251, + "comment": "edge case for computation of y with projective coordinates", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000493b0cf66e6c51ec9f5b02589607443bab7b97b18f3dd2c9cc831c0a356b60c21f960bebf79b0c295794237c60576d6a74e5f694d9fccdc2c4a469e00b18115ac", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b4df5f335a0461a38852205ac73bc51512b5c7f6a8305f1a8d4f191cb6fd3b2a", + "result": "valid" + }, + { + "tcId": 252, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000467f4d7cf5b8574fa36ec8d3d4caa369efe0521ff9e25760cf99894c64f064ca34db1597fbd96d7b7e319236e0660b05800ed99099c8c1022d55be3a8fd231e96", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a9de6e92af14bf4eb11d7533bbcb28cf622ec5e52e4a2f4cde4ddc3d21babcee", + "result": "valid" + }, + { + "tcId": 253, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004439638adcda870137436eeb09e27c32637307921974b64b9f73e266d8e95393094cfcf350b98282437974db3e402fd86e3ebdddc5e23fcd07303a0a5cf282ba4", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "edcd8e48df11aa67a90c75614983466d244e4b5473f8ac01a41c146db13c4827", + "result": "valid" + }, + { + "tcId": 254, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bf32693dd77e182d8b2650382832f37f6770090132aa77a7ebc18215e00c44c04642ea3461ff10e2e1800dc392738d7d01174679c9d2e382a80ed4961fe48b6b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2c8dd74792ced281f9cb161d2f64d238cbac2d18f8661b0f5674d79cd5c6edb8", + "result": "valid" + }, + { + "tcId": 255, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d20a02a6d0424820f7c2ed6afd1b7c149f6762bf8ce4dba50ded9792368dceacc574cc6298fa1d96edd178309f7508ce8aabf69fc0c49b85299baf91239e6665", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "503fb9bf4b57b00e0c239b3e8371f24660aa01cbf79f4c499e4fe1a155528ff9", + "result": "valid" + }, + { + "tcId": 256, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004afd321e9ff7b24d856bf14bbc5afef1952744867cae4a9f3e38f6673da908aed714966dfee5af5b7ddfc1779db74987e9e87f532bea76a2cbed717a36c9100e7", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e61ad5f80632382b626f9a77fb7f5db020dbc084c888c6b09993e12fe4d31604", + "result": "valid" + }, + { + "tcId": 257, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004cfd6d84113fc920b44bf6d67cb841691dbae07bd6732e5dec045e60d90b98f7110cbf8c9ffaef36f3d53132b1c10db5672acd5df5b87cb98d19daf87b0de3573", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "51c10b8332b33faf529c58cc2da45a23bbfecc1d4e0aa4ea54fd819b7e31e555", + "result": "valid" + }, + { + "tcId": 258, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f09616827b93b6017d770c75e35b0162c5455ce2380ef2fec54e336dfe94cbbcf3d01b7b102bec4ff0245db8c943c68c23cf1172c65544aa1174e44cd524f049", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "98d67822c318db0653a470a6ed96e7c22a046a2a25664c19539af62ae1d3a96b", + "result": "valid" + }, + { + "tcId": 259, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bfeb62d5cdb7333e0976fad3a259ddb9cb525aeee68327657aed59285352f3476e88bc9799df4d0c142bc632c81d40486fe2376392e0180af93debcb82c639cd", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "7c4648cd808df9a54f992b294a3ece562ba5efbeba7e1760f1f107ed1af8c187", + "result": "valid" + }, + { + "tcId": 260, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046d864a7cb7f8e3a1fe1c8094e3852f8f43cc4ca6a9039512b2ade5f040e3b4237c908ec1cb9fbc1f6d49460ac19f2d4526f66e00db60d207408bd46c95bffff0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "41b89b46f018a3ac884ad921e49fcf5d9677ae84e39e6ea8de844acc337d8481", + "result": "valid" + }, + { + "tcId": 261, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004feb68f41e806a239f62445d23d1b925978a9b696d6f0caa9dc29f40539b073cc2c902affb20066d2c2c920ceb8a453e42cd2454988c332cf0db907bb4fe95943", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d155b0e0e37da1a19af0e85e68e7bb4180aab55b1e95501a1a3ae0cd95404aee", + "result": "valid" + }, + { + "tcId": 262, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000457d04c653325a6cb998f61ce347109eca0efff9a16a734134a69cd1e0b081aceb43aea4f71b1f2802fbe4107d0bfb9f6fbbda464501b87ff73c47103e372f635", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "12bd72e952e6b81255ad79af19310da2e0ef9772003384a1f35753e6beab71d6", + "result": "valid" + }, + { + "tcId": 263, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004605fd33a42d921e01ee7f75806106de72cb5039f65ff31d6ca2e1efd6aa81a1c95789f0923d705fd19d5a8ae18b66687cb29091e17944b37d27f398bd5546bdb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3514b8362ee1e70e846ede7ed57283f5d5891fdb9b0c5605da45dbc5c6f44e53", + "result": "valid" + }, + { + "tcId": 264, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004303ce896aa570cf8f97954ba48fcc25f5f252867f01a9b9edeceaa6bfccedf561134d6290e1649bb028a16c6f54eb06c7e724a947a6248274a4bf6a6aa139096", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f6c829ed9ca3dfdd1f165a204461e1c16620e752216e2b6e3aab6197f3dd2b3b", + "result": "valid" + }, + { + "tcId": 265, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041c2ca67311dc5c454dc830386b7997e50bc67e3d5ff522d3e8a39f144998f884862c975f548a5f55dd8504dab5c9e88f0ed3123688d475b211da5a4d6920dd63", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3719f7afe82c3fa54c0c1260476246441d387970935e4c76965ced96da3a07de", + "result": "valid" + }, + { + "tcId": 266, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045633cbcfdf74327de0883f59e1788eed76bb0b9e0f9e55e2769ec9aa365a30e1d913bd531f4a61c2d07b847d318ee96482d2f8fa7a12aab3b303c10851ce7fcd", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0a368c74c56c61aab02440e64b2699c24cdacb4dfbcdebe0b3cf801e86f1f74f", + "result": "valid" + }, + { + "tcId": 267, + "comment": "edge case for computation of y with projective coordinates in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000419d53e44b058c317fbedbf106c98f31832cdfb84f21add753cf213ba5de9026a614cf7b7b60e759a15a6c7d864eddec6dc253519975df7f3e9bc0c77fd80e510", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "de5b6c29f2f4f17f8ed925f129159410e4557dffc5472944b8862c42bd2b180a", + "result": "valid" + }, + { + "tcId": 268, + "comment": "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041c96cc2b22e5bdb195b2a47187fad5ee6736bd96dcefef20259a551e9847b5e0c5ab052c8836e4f7cc7b65545775d55b0c7b0c7f830c6539915cb624a507dbfe", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8fca30fc5d731f42d37664d52b64e022d98a25065fb1f8bd77853d7f2bbf07e0", + "result": "valid" + }, + { + "tcId": 269, + "comment": "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004733242cc4afb82271034111b81309e156ae4466e7f2fc5fc1042f4f6e3c44f435c6f614d4be18a73170c85a6b68a9614052934e1d612466dd4921989474ff513", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c9431b6deda0c9f92f368f7ca12986f0e07e012422b840c7aa784a0c713b501f", + "result": "valid" + }, + { + "tcId": 270, + "comment": "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041a24b6520af4f028824beece59b603d15d6d15cde0719ad2f7b8e3fcb6c1342c7ed702a30e875b2436db2f2d3687d9580d3bd7b3f8d1280a81071f3ccd6b407d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "672c2339e4c39e36cfe13e2cfe352859e1ef66318fe9f97dd26d9d03a9171f7f", + "result": "valid" + }, + { + "tcId": 271, + "comment": "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044ade6fa13e59117e054ac1bca3ca52f414035493ac2ee7b1a811f1fb52521e8116ad612cd7ab0c21ef78938945d870dac827becb5b873c84225c4aef159ee4bb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8cd11340313b978fa37749f4b367c087fd900f17941002de22ce4029aa550e7f", + "result": "valid" + }, + { + "tcId": 272, + "comment": "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000434b2ac5a3e4916d081d1ed404b5bccfe076aa7f41e29d0362390f7f08458b44c25987b7f7a214323763e1aa1044a8779bbffc5e22be628138a1d80268364698e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "6f1cc2d07f6ee07d0b138b601c94deb20aa234e526fab3ee4adc98707085a73d", + "result": "valid" + }, + { + "tcId": 273, + "comment": "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000458c25f4047782b815b41001dea636c86ef19d67ec056324127225aaf6ff10832761325c4a70307dceb9bf451c7405e42580868e665f3f259995f8c358eb0799d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c2812eb9b456297572e8d870754b48489ea366f351f822759de831726815e582", + "result": "valid" + }, + { + "tcId": 274, + "comment": "edge case for computation of y with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e3d05f1aff72acff70e4d51b4207880ec06b4c269db02753d6d858aa5e6d561e7c756f6b0cd106bb732e5f20c91ddde4f24a3699df1125206fcc47449abb7d1e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9cf1689a015ac3958dc95fc71cb0d103e81b4594684638933a5daaa99fb3b1fa", + "result": "valid" + }, + { + "tcId": 275, + "comment": "edge case for computation of y with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000475638ca9ef9fa252429d21243c778be355bd130c1ef626593ca0c244cf2b6ef253b88766230ce8ded7900956a5291a6967c2a54279844cb07d7c585d87d40661", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2d6049f8e46c67c17ddfc8178dd918b23fd1969e11c959b64ea42e39c9a87dea", + "result": "valid" + }, + { + "tcId": 276, + "comment": "edge case for computation of y with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000444682e437448730f594a820ead232c4443f7e784370bfb031304b85199c4159f7151eceaa0a698d15785cc7a2e812aeda12f9ba4238a7f5e76e930f3905015aa", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9b7f8be262b9cd2751ef8eae2bad7b1ecf07cb76613cfe7088cc9bdef1d04436", + "result": "valid" + }, + { + "tcId": 277, + "comment": "edge case for computation of y with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c98b01fe92feae441d9f4de50d4dfbe9789711d911be6ef7cd9c55f4b3e8cabdd9e3aaf16605b0ab50632df6c00ec8554f36ecf427d31df930d4458fe1cbaf11", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "52980b5980df38f7c2d59e4e307da25655d50c6e030234b241c098c935a5596d", + "result": "valid" + }, + { + "tcId": 278, + "comment": "edge case for computation of y with projective coordinates in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049173ae014b645724587ee26e17bfeb61f91253fe8653dafbda4381da9fa57e9815a9166e1dfc2a81cbe126a2594e51fb98fbee7b3d6588ad86a86431141444f4", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2f1f6990c30136d6f44de8145f191840c4b9efbcf87c39b7995c262bdcdf9d40", + "result": "valid" + }, + { + "tcId": 279, + "comment": "point with coordinate x = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "afe5b60fe3e1dc873b3f3022893a359880e817537beb96b3d48d375766ab59e6", + "result": "valid" + }, + { + "tcId": 280, + "comment": "point with coordinate x = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e4102f16fa7f386e912d3a7f77dcc7dc9f8af54cae117ddba10a3d09620eff8c689c20e12ce8f78412945e1d3acbf9935e4653fb0dce02b14a7d526a114f1387", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "33150538973510827cafdfe9449e7a5a2e1a7946f4e485a00ff219b2cd58d801", + "result": "valid" + }, + { + "tcId": 281, + "comment": "point with coordinate x = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047aa67d0033226fb2b1bf975d4568e1f2299e82f2e459ff0b6ee3c0c57dbd40417c20634644993bd84aa361037ce8bf3fb72286dfdf4482458b076a7a5f46d1dd", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b5523f9382b35ed9e1c4f2b420df9f61e6ac8f6d342213fa4d75458f5bd828d1", + "result": "valid" + }, + { + "tcId": 282, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000480694ba7d6ad6efa8ad5ce0435a1bd225e0288b6fc22a11e7013aa0d4e9a496b316d67d1c70e6c130420f57cb6e0d60cda154c737f0118007cfea5c2d5b4e397", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ad9a53d05315009fb1487369f72fdc33e6dbba1485efaede2951433526d2fd0a", + "result": "valid" + }, + { + "tcId": 283, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000406c66970e539d9ae0f8f67a72f426c100b3b2cf2e276e9b0aea75b4efc98832524eeab2b413ba17db811f740f9fb9fc3c73b5ce51f1e74e7e08bcd8ab48dae83", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a88cca88b59cd86edda202cb4ea1b2d541d5c8c22c062a08f9db496d56257330", + "result": "valid" + }, + { + "tcId": 284, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000441277a6f20d855af6acec53e9923216d74ee2aed18a4140591ebbb0b3455072669bc7f19d64647e74ff00d0c89bbfe508e322b4397ddb8564ed2832eaa5b2d92", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b7f531b4a9ac00952bfcf2cbec41e58b54c4f412f464bcf1f1bf10a24b9b1974", + "result": "valid" + }, + { + "tcId": 285, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004146dee2bcaa5cc0817fe191b6d10def6259df744afdc9e5b0dde523b348aaab445b1546f79b7a6aadfa547bfa416f62b54f7a476d6d888056b9c05c72e0139f1", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "473473518f0e843d1fb5105b16fe88edaa418b396cab7cb5532416d171f2e7bc", + "result": "valid" + }, + { + "tcId": 286, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c48ee90f8fe800664086ed5ba12930cacdfa175a67a2c4398168f626699deb8dd78c35a48042aafbc6c7caf3a68385ddb5d406acee86d96403e75baffece00e3", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c2563f49e623b139a83c4cb71cb73deb06458385658bf8796bac0c2ed12c8a67", + "result": "valid" + }, + { + "tcId": 287, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004737d92f5dad51d58261a77e755678ab02b107912041c5d295f5829cbd10cd8c59b55dd084f84937c27565a9075fe108745e17001666743db551436e691ea818d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "28c247ae91fdac1b29896415fec60f4252feed9c9ffa0216d31350d708646d89", + "result": "valid" + }, + { + "tcId": 288, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000459efed747303891baab0e1dfdc32d69906e0fc6815b056dae0eda2080957a3ebf205fd299c63e549d24c153935d950141c3dc2699afe8731a46304e203cac15d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "76e9e6f1339bff54b82a45980745526ff9249e942b1f836aab719fd959fc8099", + "result": "valid" + }, + { + "tcId": 289, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048ef9a7997b717fdbc5d2a7f9a67f705e5dee4c82ca383b7ee2d07c24850396d072c98f7dc1658f9dc3c434a9fddc2f986cc0e3e3ef409827537617ee67105f2b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0de82177c80f4e35f3b7a300e89ac288f30e01a8658933c16b8c90605e35d6c7", + "result": "valid" + }, + { + "tcId": 290, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000404569ec9fb3d6bcedc059e7fd04ab7d3f6bac730b1b75a11749e4346458f9296a051c84d558dbd2957c15907477776af660ac01582c001dc1f868ebfc6b3b264", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f41de3a77597835fa904d1f05411368e6e878abd0485477d162b2c764ef045ac", + "result": "valid" + }, + { + "tcId": 291, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044b298a3eba6a09fcd8415976e0faea997fd519ffd3363bd20107752123e101466abb70c013ba2389c371be19dd3296f0600e64f05755e15cf89320ac7ffb25d6", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c4dbe3b94e729b1e0ae34ffb0f6b0d95d7e619ab3943aa3836cf1e721a470a9e", + "result": "valid" + }, + { + "tcId": 292, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000418bde07952d7be8914d2b2544c65a3debdddd9e7ce8a9c46a03d124acfb8548b01a4a175a2a81af98e6028770d055e22f1016df15462b65f55a2d4850cc415e5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "83b31061f1b70148870a9282a4641cc8428943a3b10e0301955f5960c386fb04", + "result": "valid" + }, + { + "tcId": 293, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004002beb755f694a09f60bce5b34dc347c5c3aa236de9007bcdd0707e9bc8071694f443b0045999f2f5899ca793424a9b423b0ec0a3edcbbf4afb9e66526cf89b2", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5f74c066595fe9ea283274964ae83fba1a73ef9d29d24e6604a4aa0881fe390d", + "result": "valid" + }, + { + "tcId": 294, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004957e5bcd11fc450bffcefe636c0b73f10fe8585e04c6c7aa7fa0b603d24162d99e553e940956aa04a237a0c2570a0c7bc3712172b8f78c7b470a042ae31f3223", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c672601d951bdb550ea9cc58d2031337db39a3799de21af4e5c23e2fd7f537da", + "result": "valid" + }, + { + "tcId": 295, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c43b1b4099da70f8d33fbb61b68d9b0e9c7aedd4f4761c6722996666974e298e978c02ea7899cdd46a47405ac0d89fd6a4d66718a4502438ad45463260976841", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b2c2c00532d468d25374ae2e6ec9bc52bcb2e8df20ad1a40719b7d91746daeab", + "result": "valid" + }, + { + "tcId": 296, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004deb85f604be1930dbac6629cb96210f6fbc87ce2b260b66cc7d661861806afe1120bbcf8356dcfbf1de4bbb7d2066c3dddfbaf330af754c57859137a9cc4a68e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e5fe7c96371878cf86db4210a487d7d33ac4bcc45b8df2152e82aa7228a991e2", + "result": "valid" + }, + { + "tcId": 297, + "comment": "point with coordinate x = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000427899fe24811adc869d49ac451cb210631d19aff8971ac7c3dd2fe826262507fd9ddffef4cc9cd81bdd3eab8acdd5c287a8934f82dfc255dded1ac1f1100aa17", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "1bb9a501ab9d215230cd1072042b3c8271aec3b2c1da10d1a8c810fceaed47a4", + "result": "valid" + }, + { + "tcId": 298, + "comment": "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044301f54b3592d1ea2a40989c94261d2b1d1fe297ed6ed64125ee241de05d004bc79014f156e9b7bfb36b8ad2d66d55f3a753829a9ddb86055bb9166dd3aff457", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "fdc15a26abbade3416e1201a6d737128a2f897f0d88108645453a1b3ddd05688", + "result": "valid" + }, + { + "tcId": 299, + "comment": "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000436b0f66bf5f9fd4b2df9cdae2af873a075c55497d7fec4737a7c9643c2c76fe5da9f7287b3cd4e5f05b9a1a4f64e8a8d96c316e452594d02a4592a2107ece90b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e36348e3a464bc518384806c548e156edd994cb6946473c265a24914d5559f1c", + "result": "valid" + }, + { + "tcId": 300, + "comment": "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000482abb58afb62d261878bdee12664df1499b824f1d60fb02811642cb02f4aff5d30719835d96f32dc03c49d815ffa21285733137f507ce316cec65ca562ce2ad0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "7d65684bdce4ac95db002fba350dc89d0d0fc9e12260d01868543f2a6c8c5b8d", + "result": "valid" + }, + { + "tcId": 301, + "comment": "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047de7b7cf5c5ff4240daf31a50ac6cf6b169aad07d2c5936c73b83ee3987e22a1940c1bd78e4be6692585c99dc92b47671e2ccbcf12a9a9854c6607f98213c108", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "6ec6ba2374ab0a9ae663f3f73671158aaabac3ac689d6c2702ebdf4186597a85", + "result": "valid" + }, + { + "tcId": 302, + "comment": "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000406fa93527294c8533aa401ce4e6c8aeb05a6921bc48798a8e20a0f84a5085af4ec4828f8394d22de43043117b8595fb113245f7285cb35439389e8547a105039", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "6d6e87787d0a947ecfbf7962142fde8ff9b590e472c0c46bbc5d39020e4f78a7", + "result": "valid" + }, + { + "tcId": 303, + "comment": "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048a4f625210b448dc846ad2399b31cd1bc3f1788c7bed69cc1cb7aac8ab28d5393007c6f11f3e248de651c6622de308ee5576be84ef1ed8ed91fd244f14fc2053", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "56ea4382f8e1abfcb211989f500676449abcebfe2cd2204dd8923deb530a6c7b", + "result": "valid" + }, + { + "tcId": 304, + "comment": "point with coordinate x = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004885e452cbb0e4b2a9768b7596c153198a922dabbb8d0ca1dc3faf4f097f09113be9aaa630918d5056053ecf7388f448b912d9ccfbed80d7ca23c0e7991a34901", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2c362c27b3107ea8a042c05cc50c4a8ddaae8cdc33d058492951a03f8d8f8194", + "result": "valid" + }, + { + "tcId": 305, + "comment": "point with coordinate x = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e226df1fcf7c137a41c920ff74d6204faa2093eeffc4a9ee0a23fb2e994041c3457107442cc4b3af631c4dfb5f53e2c5608bed04ff6653b771f7cd4670f81034", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0188da289ce8974a4f44520960fae8b353750aca789272e9f90d1215bacdd870", + "result": "valid" + }, + { + "tcId": 306, + "comment": "point with coordinate x = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f53ead9575eebba3b0eb0d033acb7e99388e8590b4ad2db5ea4f6bd9bde16995b5f3ab15f973ca9e3aa9dfe2914eebbd2e11010b455513907908800396fb9d1a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f78bd7ff899c81b866be17c0a94bec592838d78d1f0c0cf532829b6c464c28ac", + "result": "valid" + }, + { + "tcId": 307, + "comment": "point with coordinate x = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004882773ec7e10605c8f9e2e3b8700943be26bcc4c9d1fedf2bdcfb36994f23c7f8e5d05b2fdd2954b6188736ebe3f5646602a58d978b716b5304ea56777691db3", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "99f6151fba28067eac73354920fcc1fa17fea63225a583323cb6c3d4054ecaca", + "result": "valid" + }, + { + "tcId": 308, + "comment": "point with coordinate x = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a60b6458256b38d4644451b490bd357feade7bb6b8453c1fc89794d5a45f768d81eee90548a59e5d2cecd72d4b0b5e6574d65a9d837c7c590d1d125ee37c4d51", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "68ca39de0cec2297529f56876bc3de7be370f300e87c2b09cdbb5120382d6977", + "result": "valid" + }, + { + "tcId": 309, + "comment": "point with coordinate x = 2", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000000000000266fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "1af254af90c16dbd217f3356f7fef9ad532d4902a6d67218e3188a9e840fc929", + "result": "valid" + }, + { + "tcId": 310, + "comment": "point with coordinate x = 2", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000452d9a44bf0bc729e5f3ffc8a73a4da332e2962b22013391b60eb66de6e1b83431eb0d9c6e92a424bc24ab23caf99e3cda830263689653626f8be91590fb75cbd", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9e232223afd0d57a7b150f65700ac60a78bae2aafc0cf9d1a820452ca1e57a14", + "result": "valid" + }, + { + "tcId": 311, + "comment": "point with coordinate x = 2", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000478a99dfcb7df4d9277f97b5e24e979f48a8aa8983ef9dd86765dccc33d8ade9f9857dccce2a7ff0ac41b255eb8df45df61b4db58fb5e997614bf0d5ab217dd90", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ec2f7542cc1df665764c5b9bff751208d668be9f3d61cd6c33b35ed0f4fe5a17", + "result": "valid" + }, + { + "tcId": 312, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041162424aa9fa0d42bf60e06a16b7e7ea45ac0e2f07f1e36735bd0d98c70b8850693f2ac128f47f213322c5f8872dde9261affe614e3f364a792d17b0e8421840", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b095e9c2f933a00053a95758dc20fe1e72a798462f90fd67fafbbd68d761dd67", + "result": "valid" + }, + { + "tcId": 313, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000430d2d42a85385b64817d0900bc8c984716934529056da032d5fde844915d669b0e5ef40d566f5b23992132c4ae588017ebd160e5dbf4804f936cb0f257a93446", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "95484c5554b543f8eb2fc218cc46ffe648a3bfac41e6dfafca1ba11f8c53ed6e", + "result": "valid" + }, + { + "tcId": 314, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a77a259a55ed98d643e1a3e13804c95e543c1557e6141e4ed47dcf13b941a6fa8bfa5f879ab14aeba7b2ac06e5a719c86f4a2ed391160380aa3b6f74141cd354", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f22ebb6843281b54b22a9ff1a91485c7db8f95db4bf8a1131f892b3bfce56662", + "result": "valid" + }, + { + "tcId": 315, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f89454593dba5720164d17bc1ca32f10ddd1a7d37b7bf02e5ec0d59794f4d63d34268de3f6a2c108514a52702f7e67d27829fa0340b3c4710651291483c8b213", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "99623d9f447b66cb322488ea463b3e40d5620f4df78f89c62fe0ba8b90ff386e", + "result": "valid" + }, + { + "tcId": 316, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b00befcb868eeb5d558ef2ec2ec679dc082ec15a57c5899311178424674b8f50588742728a6384a180506b8739a79c4ce95e1055c0d0eab2254ca55b18a3e7b2", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d611afb4046c9f4b2887b7dd4d45b80e9584eca93f5a855dc30e529eedbf5017", + "result": "valid" + }, + { + "tcId": 317, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b3e2f9c7f9f068c5da8882fd581e7112e538aa01feb5f017433c00fc8a828fccc56a3f692e3b237b7caf49869009e6743e35ec5aed19d814cfc13869f78eb895", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0438085ab0104fb47c696be5c08f95e319ed5507ab781fe1cdccd6ddb34bda67", + "result": "valid" + }, + { + "tcId": 318, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e5dae9779e0c168e60b842508e253d2ac80e7e504daed9fac077b9b449c368b57bd8661bbbccef478f050f4ffec8aa47ed7f98e89514d9083facf0a7f2f7b70f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "326dbabffe17c6efc710bdb8d04d16c8624c083d48bfa6e4411d221264d8277f", + "result": "valid" + }, + { + "tcId": 319, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004420e10bb81b379d728879fe600e6f1bf2b85d8023848a040c7654a9734da1ac4cbee561571a616b094a38436e02c6d7b54b4279a234193a828e86e21e6b71d16", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f47a91e29ebe69baab6b340bb64a6dc34fca7546fd6eba53f5bbe41f6178c7c6", + "result": "valid" + }, + { + "tcId": 320, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048dbf1ba87597004af552317225916abf3d71dff90fe9e61f9d2863a6de218d4a0897e334000139b0849d772757b150e5d86b55d7a00a744bccbb7cb8d1a6b07b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "cf83319c735348dd13c44b055f67a292f7afc5d9d2bd0706c966ad765368d422", + "result": "valid" + }, + { + "tcId": 321, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041accb85b612d32d58459caec0bb6768f05ce8094e3862422a7c12340dd31bd7397e0377d33ccdce8bd872f898be6cbcf7274b3beefb5dd7cadddf027d0c02c2e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "41ee7801ccb702f2f633d1d0ec20d7c427936886df89ad33d19dbb56f66a2656", + "result": "valid" + }, + { + "tcId": 322, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000414eef41b67c17b1d4a040554287cd6a9e6b3080335ea4e16821dbd643ec67dba6d67cadcbd1a3f0227b7caf2c0604d2b3507aeb96ed98c32e2350fe295ed8998", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "af828d6bc21ad6b4570b5f68a6208d3a2f46edca69b1980fe5046792c68cab80", + "result": "valid" + }, + { + "tcId": 323, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a99af5dec3c995080ddcc15d7994daff266aa53f181fba4bcdd504d206bfca2f3739588f071e4192b615361ec81735fe2ef2923c4056c432f4c2782e5d722215", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "4ebf7f174cdb3fda94f99698317ffef5f4d4fb933f3292f1aaa782c354ba03e7", + "result": "valid" + }, + { + "tcId": 324, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a355d8d17d50f6428e0af345921662587e2b6249eed1e326abb7c8605036b1db1fd72efaca9082bb6fab44359fa7f6ef8a45d036852832e2ade9d41f28219144", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "1649f83c47a6640a94b773ab4309bd6964109433e3f3ee5b024d1915ef5139de", + "result": "valid" + }, + { + "tcId": 325, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fa53e5b58d55ebf517d8db07b021d80918d1f260f9e0b3d00bd47b24a91ae6ab85ab2adcc31b98caaec2681a841d50bc0eda875561fab70c979463ffb6a1d74c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f434c3ffe109528456c23d6cfe51ec0b10be606d7a26775fe2ff0a9b18f92f39", + "result": "valid" + }, + { + "tcId": 326, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000433fe37949375debd9734f54b7036b7a978bc8fc4ae3fe927a521f940d9e35dd38f81a9160c05df04e34290db40c3e045b832373941ca85b433854e43caed323d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bd02b9dfc8ef760708950bd972f2dc244893b61b6b46c3b19be1b2da7b034ac5", + "result": "valid" + }, + { + "tcId": 327, + "comment": "point with coordinate x = 2 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b9ba8445067d0e81bd32dd99e6b4ea3d442d063a8eb9873518ee3bb18c053706099964b6889105784d9d6d9d9aa79c76b6a3d3376315953afdcb5a7439e7c706", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "412269bfc15d8b1fd7f25de33b1515ea67f2194e73ba06c85ef99bb42722f95d", + "result": "valid" + }, + { + "tcId": 328, + "comment": "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000478b248634270a7a6640bd0c64595dc4e98adfe6bdb8112593a4173e36d4a9b4969a1f3d19b325898e36459c41eba1de99229b0ba2cf1337461c84391d9aea1fc", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0ad7556a621074a771bf129163d09a2e9d2e174f2b8a4b6973e89ea138c9a603", + "result": "valid" + }, + { + "tcId": 329, + "comment": "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c788884ac868593db241f5b3ea7013810d3ce28a02680a96ff357b261fad611bef353b0e82c1c68c471ff1ed5c4749e168e7af8591a5e6dab599b96620de0ede", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "76acc74dd60872ab29e1bcb99dd46365c7c7f792619c901c7ba5c68378b233f5", + "result": "valid" + }, + { + "tcId": 330, + "comment": "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041864e373ac60c23543fea9e1f237950a8169e07c817db69d500e5592d1df9d5a10da4651efccc46d37e7eae16c36ac86a9a86b88ad08751a8dcd15060019704b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "50e23b94fcc33d93dbcd71e955e195fe0bf6ac9b04b15f001e53b5dc7bad158e", + "result": "valid" + }, + { + "tcId": 331, + "comment": "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004dd7308d2a6757f924dc979066e75ee6fa52b03393d2892f59788effa553b690d1fef00c1c22ba80b95d529782dbef55a63046179fb4ef00fdccf5b62ce55c136", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3324bf2fb3486b1104fffa35ef38975faffba1ebe42c54399206face505448c7", + "result": "valid" + }, + { + "tcId": 332, + "comment": "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004575d51be2bddf5bf1ab42431ba7e3b5f2947bc574df9f60a448b8db5ca28c92cd836f55c556440a7df125de6599b21ae68f15d5b9f422d6eec88ab2f65406bf9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "235fd3e7216c92f73860f0ac0121b4264ff89d80bc75d59dd455298597c5f2ec", + "result": "valid" + }, + { + "tcId": 333, + "comment": "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c7422a80aebdb518bd2daba691d39a25ea2fe49a35cdfb2a0f94bdfbadc6629ae55ac7c400afd2976b7c3b24f7126807a5a0afb931cfa5c6ada1f4ff984ea5a7", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0bf758de27052319dac39b324a6ea55e928603a3ef9049ad147f8ca35f55b656", + "result": "valid" + }, + { + "tcId": 334, + "comment": "point with coordinate x = 2 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ad4062216f84ffd66e326497bcbcab982283493392ec0f739cef8cd7eaf3453414c5a289a846e28bf2042ea5dc7b15e252f48d3cf980e7c4751cc35493a1c328", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "312eeaaee397224fc17dec7191ce69cef40e8fb373516c2b1edada0336c99c13", + "result": "valid" + }, + { + "tcId": 335, + "comment": "point with coordinate x = 2 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ccacd1bf7c7f4ea9c7e59bd802804a9d335262716ac288c6eefd7a7135349a4f7b8612e2bdbd43b3fc4fa6941ac15a8f37e34fe7810a0c0d43c05afafb6480ef", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "aa1691858e6a1a06c6df57ce10a4c730974c06d1e0106d1a31b51b915cd6b60e", + "result": "valid" + }, + { + "tcId": 336, + "comment": "point with coordinate x = 2 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049aa7f1f93474fa370c4df3805bd2839328895880dce197a06cf9052e6ab7a6938c9a208b335bfda6b01321f029a0d83c8bb96561208481f7af6c6cf1d2657843", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5786d6ea09ffb21a63adb020b117096484ef995e8c4a72afa479cba95c959920", + "result": "valid" + }, + { + "tcId": 337, + "comment": "point with coordinate x = 2 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000483b7affcec11685d15614e2d53c1e73504e3d98344bbd5fc0ad86dc4c36704323a7f73a09533d1a1076aa9c4af22a6bab92f3f0d766798db7aa4183c037f86e6", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ae0c7845b82995263c51e13e297412d17b650aa83dce4f55a069dbee671c16b8", + "result": "valid" + }, + { + "tcId": 338, + "comment": "point with coordinate x = 2 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004aeebdd971cf4e988fabd8070c75c64aab90a83a36735fecfb385605979c008ae8c39888f0daf74f98cebbb08f6b91a5193f684a56761b9f2b63d87d3f60491ed", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e5e764a38b73816f6e11e7cf298b2be54d11249c615f0a71498a0a821b5736bb", + "result": "valid" + }, + { + "tcId": 339, + "comment": "point with coordinate x = 3", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000032f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "6aa7e74a7a838efa9607f3587d4117f1914c57fa924b441c27fb7a7c31fbaac4", + "result": "valid" + }, + { + "tcId": 340, + "comment": "point with coordinate x = 3", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e38eec4c1a4d81a5d994b0d7780305af651892cbf07f3a07628f4e2473a8ab754bda96622462880d3536d390132a85db6147f814c62efb580a6f529598b0dd1e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "391b624f28eb398156666dbec1d635f8ff1753eb86297973a1c2831b1091e2df", + "result": "valid" + }, + { + "tcId": 341, + "comment": "point with coordinate x = 3", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000410f02d496e9a8758c831389892a45ed009282ea1eb201ab8caf09e6f2de9fa4acc126becc204c41a94aff4f2ead7552ec23fc68f0005147625a95622b521090d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e3f39d071b743c8041454d1dacba93dc9f3f12a5ae1bfbebaa59fc4cefee6b82", + "result": "valid" + }, + { + "tcId": 342, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044c859aff342c56a9508b859ab1509edcabf66e044e2026cc293474389b3d58c16bc06cf99dd6d8249c5d24386a55a97214ea0cda270ad9470986c3a3d023cb07", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "09d0d1b92af1e7111d223bf5efcdfa6df2622ab3cf161af0ebbf06ad00c09b6e", + "result": "valid" + }, + { + "tcId": 343, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d1eb4f7c680a247a14f3d67f85cdb1c4c6f13d44821fc456c9247a606622afec4952cf05ff06f06d7030e88904737096cbf8dd90e478a3b5dfed2ee487a0835c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a738727e0f5b20448009d1029ca727f2380d2c6e152a6e2da8ea50531ce39499", + "result": "valid" + }, + { + "tcId": 344, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043bf79d6c1a20d85115e973079707f5131eed2f83be5683c34d0fb3eee1ae40dfd2ea4f1b735cf62341835a5721c25daa0dc1a3886ab75ef653f472d8f3aa1e97", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a314e4ee9e303d970b4e9f0cdc262657d5c5192f055466b9d09d9c888d6b7256", + "result": "valid" + }, + { + "tcId": 345, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b1f808286a42eeee85d585e54dc28aba2aebfb956805f5c01127bcdf435154cb5b178fda5896d9e7508661fee7ee55fa9623610b3d9f4a59156b76d8877b4ef1", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8f4e1bf8e5182a1fbcdeac924df1ba2f937162d48a206783c48132cb582c07db", + "result": "valid" + }, + { + "tcId": 346, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a21e80d09e11acbccbc909de6c9f1159addbb5dd477211b90a370f8c7548e60d1d7aacb6e455bcdc230331d79ad9464a77b702c858400900cb4488cb6c28bd61", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "16682c862cf53755b3c28adf7de052d5cf0e81e5d8acb346702a392bc6b2b1d5", + "result": "valid" + }, + { + "tcId": 347, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045055a8c45e81385f4144c7b6fb32119395a94dbd07665ed7bc1cce1e62dc47c8b6d50a39a55d3b8e996624fb6ec2f2960c7c2bc0bc94b2a63d65096fd99ca41a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "cc33e840b5354bf6e088047e76dc168f15c0c1aa946731600f52d6f1c9299b27", + "result": "valid" + }, + { + "tcId": 348, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004af522fc0a61440173945b914d6404b1940b547a6f768550280fe28bd331c9c661d282429f2911298f9c5b82f87c7f5044706748c19035689b216d64474bf5ad0", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d7b4f5e2dd1ebecfc92318d92085271be482fe65a03e83b2e358a397a597449b", + "result": "valid" + }, + { + "tcId": 349, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ec1a88652de714d21fddb54db4a3423521aead5828b843bdde9a42cf4a8bf124a69568c664e2d9317ac732c98c435548dcec0eeb8ab31027ee5f1693ccd97c68", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "1d88ed8e4579a4c62fed95eafe1528f8d5056041fc41f3ef063605ddc980ee09", + "result": "valid" + }, + { + "tcId": 350, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000448e4c9cc88a601eb639f81ffa679540bf1d7bcbe876a955e73bfade055384160bae130243ef5fd328f65278e00cad6001327ab42fdf3b9654aad6f260542b02b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a6698578650dadb452d677c3983e6b809152d7d2d8fba349cec686e72e6f8693", + "result": "valid" + }, + { + "tcId": 351, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e861379f1c1b07540155bbfef4a69a84be81b1441d43e7850c7ac1005a804238bb33c7981d383a06d1b795552a7b31f49145fba937876fdc9f0d138aa5b3f322", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8e42c38902b25fa138b95f4f280b684c09e1212c4f06a2bc2c2b2b8790112034", + "result": "valid" + }, + { + "tcId": 352, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b4489cd499168bd48cd2c31167edad246c63859bf8b48398617a7a0556341e3c0b0f66f665038baa29db8c296d4f2ae07b9ab9193bfc00981d7df0599ce0648d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a19f1165d31c1695359929deebcd24846ccb9a3c2a38c10bdc7c855bf8a32df7", + "result": "valid" + }, + { + "tcId": 353, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004884e74885ea450f5aab0cc8f06c006630e8b183a06bda509322fcd97ba5d2d2b00e1373d533bd5920427d106b7f33eeb53d21b5cf46ca0151e91859e811a39cb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0a87935c036de666b7619f14ec58f9f78698cc23a667616f84c177f34661ebe2", + "result": "valid" + }, + { + "tcId": 354, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c50224a8cf3a19da6133e746d00217285df85589ed334b54d95b005b8f033f7df7bc6a5ddc59d033f0c66bed57149a160f25723117a2fcd413aff8c9ada43bf9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "90accd1c3af1cd782ea1e864a307aaef6a01fd3a6305a0adae37e76844b9ce10", + "result": "valid" + }, + { + "tcId": 355, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c66a917fc435c9f41c47428e718a3017b3c5c992b4d94a663602f73fd825d043a03cb9f58174cffb359e2f541cfb5e551c50fd811b82362eadb216a4cfd0f8c3", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e164d88fcbd1ccdd654de0415bfbd2a171590713015f4a1755504e62f7a03870", + "result": "valid" + }, + { + "tcId": 356, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004f55a451e6e0d8f7600c7bf7c05741c5e5985b8ffe4eab62d4ffc04aedb725a66e942cf486efcf3b85488cf3cd4fb0248b820703b938ce77a074a2f9286af03bf", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d4b6d4251ac1f8a0b0c75bbac3517a13ea0c857b5499b03d153be663a8715480", + "result": "valid" + }, + { + "tcId": 357, + "comment": "point with coordinate x = 3 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a96aa25bee8c8cb6f6aaf40be98ca047da245e8d4cae28fc892a0369b299cba3ef5f54bb59f4ad58a84332a00d89a1cf3d56c4e6ec9c3a467a4a2a04ad3bce97", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f5270d0c4119f1ef467a37501688b4bf4a516e5f58a0f5a40f23ae70ee813c26", + "result": "valid" + }, + { + "tcId": 358, + "comment": "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000449f572fa8cdf6750adabc3ab0e46bf23dd7ad7114bf319f35afa6a2ccbe2e7d343c44f018f8efc9f52691b274a8c89283d13ce93d1b58aea11d62c88599c309c", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "1763eb5bd3677de88e98aad84038838422d6e55605a14761788cf305672eb670", + "result": "valid" + }, + { + "tcId": 359, + "comment": "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b36f6b02bf1d213d9abcfc98c25fc81ab3b98cb13d678da871310aa093ab7b58a50b134818321a48ffc1ef9f8624e371ddf078d8983fda6c4eb27dfb255174e9", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "98c95ef9fded241da09392573144daf44b0332518f458167e09d672011ea4618", + "result": "valid" + }, + { + "tcId": 360, + "comment": "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000474f57ff3da8d60ec0b382e6866be4502f695688384b405e2179aab61066196d7d24064185d68de95bd72b219c0c0a93879324f299fb19214b33a3ed2f1bf4823", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b0fe8fc6abe853b1ea6aa4f4b4490bcd94ffd3532c1d7cce36d059ac8f29cd67", + "result": "valid" + }, + { + "tcId": 361, + "comment": "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004924fe3439d35427e2ad9b1f6e67877ed3441d74bdd0eb9f82ae360434bc20624537e3400007cd2d140f2caa0f7b61c7118abb9ac5c766ecab3f8f72ea5d96cdf", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "4fdc7cc04b2459f73c856023e892699b9018baca1b8e3b040ec74324607c97c5", + "result": "valid" + }, + { + "tcId": 362, + "comment": "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fb0e48a3815a2b80e9e725036a239757e9c5987850a941c5f5d2b89b776aac683adb5481fcd85f0013feb20505ebbaff27edf8474a7cf4d985ec567365ecbc1d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "561138979956fe6a1aeae06277456c7e5e7e7d643910e247fb248dd7435691a0", + "result": "valid" + }, + { + "tcId": 363, + "comment": "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e669915ee160694e8559d7965f7cff945c1cb076f194ec9894b1a38b10726fb0389675e3155b069b3862da3d1112179a04accbe7dbb70b3cc48bedb7591d2eac", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "06c06abb603bff68f356ce496c17fcd0662fa040eb0cd45a98112e6c1eea11db", + "result": "valid" + }, + { + "tcId": 364, + "comment": "point with coordinate x = 3 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b760dfff4c5c200aec18b930b18df34297bb421b96017ef902139fe6b12349f6ccb8cf83d2837c7520300f197b491c0368470ee86f74ca0381682bb6ad80344f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "319297f77a75381b65d73107e826eea0e69d85985db4568fea21d12dda696921", + "result": "valid" + }, + { + "tcId": 365, + "comment": "point with coordinate x = 3 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b0e4de914fe71b61636e61391528efac8b6c11edcd41c9766af8693dbb6e41f2517293725552f22dd6e1db7c2c243f80c10713f6aa48fc5e395bd9ec51f1e9c5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c3ef6eb91aad69456ede5174b0e5e3d6863c024aef3185d2258946362903e576", + "result": "valid" + }, + { + "tcId": 366, + "comment": "point with coordinate x = 3 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048eb6ee2ee9e061acb9312ad015b1954ea47ca304a2cebb77f3bf6c78678c1149d93fc6e80561f3110fd0e95fdc0ce8da2c3f32f7f581f9b666d74900b3760b9f", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a18b1fba4d496419ede70cc23ceed674526f34299e5b09c0ee2dd1669693fef9", + "result": "valid" + }, + { + "tcId": 367, + "comment": "point with coordinate x = 3 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000490121021546a96e7879d53e7b85c21f4047df49b9ad85020104f216d010f520d1bba6e765742395b4c894fd0eaaf87275d1c77494c01cce882de2805d1922c0b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9fc7fff3bb4d6e5a4d52eb0e3c513a3c9fa56014c030449546cda744aa126f6e", + "result": "valid" + }, + { + "tcId": 368, + "comment": "point with coordinate x = 3 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000464c1712e3e9ef440c7ea8faf0540d2e6a05adccbd53a7fb24ff16a9502a818f747cfafd2209430eb7794f5da91d6c5e2db505ba287bc6ef397bf7f30c747536a", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "61cb2fb99b695ecbaf91a95e6e0c7e24633bc7613ebf518c6f1c8161dc75ea5f", + "result": "valid" + }, + { + "tcId": 369, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004cbb0deab125754f1fdb2038b0434ed9cb3fb53ab735391129994a535d925f6730000000000000000000000000000000000000000000000000000000000000001", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "af306c993dee0dcfc441ebe53360b569e21f186052db8197f4a124fa77b98148", + "result": "valid" + }, + { + "tcId": 370, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000424800deac3fe4c765b6dec80ea299d771ada4f30e4e156b3acb720dba37394715fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "aa7fc9fe60445eac2451ec24c1a44909842fa14025f2a1d3dd7f31019f962be5", + "result": "valid" + }, + { + "tcId": 371, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048f33652f5bda2c32953ebf2d2eca95e05b17c8ab7d99601bee445df844d46a369cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "082a43a8417782a795c8d4c70f43edcabbc245a8820ac01be90c1acf0343ba91", + "result": "valid" + }, + { + "tcId": 372, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004146d3b65add9f54ccca28533c88e2cbc63f7443e1658783ab41f8ef97c2a10b50000000000000000000000000000000000000000000000000000000000000001", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "70810b4780a63c860427d3a0269f6c9d3c2ea33494c50e58a20b9480034bc7a0", + "result": "valid" + }, + { + "tcId": 373, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b0344418a4504c07e7921ed9f00714b5d390e5cb5e793bb1465f73174f6c26fe5fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a7d34ee25fbb354f8638d31850dab41e4b086886f7ed3f2d6e035bceb8cab8a0", + "result": "valid" + }, + { + "tcId": 374, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048a98c1bc6be75c5796be4b29dd885c3485e75e37b4ccac9b37251e67175ff0d69cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3f09cbc12ed1701f59dd5aa83daef5e6676adf7fd235c53f69aeb5d5b67799e0", + "result": "valid" + }, + { + "tcId": 375, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff5070000000000000000000000000000000000000000000000000000000000000001", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e04e881f416bb5aa3796407aa5ffddf8e1b2446b185f700f6953468384faaf76", + "result": "valid" + }, + { + "tcId": 376, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042b4badfc97b16781bcfff4a525cf4dd31194cb03bca56d9b0ce96c0c0d2040c05fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "adace71f40006c04557540c2ed8102d830c7f638e2201efeb47d732da79f13d9", + "result": "valid" + }, + { + "tcId": 377, + "comment": "point with coordinate y = 1", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e633d914383e7775d402f5a8f3ad0deb1f00d91ccd99f348da96839ea3cb9d529cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b8cbf0968fb70d391059d090b30d1c4edcd2dad7abbf7aa4ad452f5a4644a7be", + "result": "valid" + }, + { + "tcId": 378, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d1c1b509c9ddb76221a066a22a3c333fee5e1d2d1a4babde4a1d33ec247a7ea30162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "07257245da4bc26696e245531c7a97c2b529f1ca2d8c051626520e6b83d7faf2", + "result": "valid" + }, + { + "tcId": 379, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004755d8845e7b4fd270353f6999e97242224015527bf3f94cc2c693d1b6ba12298604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d6aa401b9ce17ecf7dd7b0861dfeb36bb1749d12533991e66c0d942281ae13ab", + "result": "valid" + }, + { + "tcId": 380, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c6f9fc8644ba5c9ea9beb12ce2cb911c5487e8b1be91d5a168318f4ae44d66807bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f43bfe4eccc24ebf6e36c5bcaca47b770c17bcb59ea788b15c74ae6c9dd055a1", + "result": "valid" + }, + { + "tcId": 381, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d3179fce5781d0c49ce8480a811f6f08e3f123d9f6010fbf619b5d868a8ea833ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "009bc3abb3cf0aca214f0e8db5088d520b3d4aadb1d44c4a2be7f031461c9420", + "result": "valid" + }, + { + "tcId": 382, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049e098095463c91ac7107a920ccb276d45e1f7240ef2b93b957ee09393d32e001503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8bcb07a3d0fa82af60c88a8d67810ebca0ea27548384e96d3483310212219312", + "result": "valid" + }, + { + "tcId": 383, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bf3034a9935182da362570315011544ac2ce8a9c22777c2fc767ac9c5c0daeebcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a09ddc7cfe023acd9571ef0754010289c804678c043f900f2691dd801b942ed4", + "result": "valid" + }, + { + "tcId": 384, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004709c7179c2bb27ce3985ba42feb870f069dacead9294c80557be882fb57790481e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "da98054d51ac9615e9d4f5ceda1f1bad40302ac11603431efec13ab50e32fcf2", + "result": "valid" + }, + { + "tcId": 385, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004264c00a2d92514a6dbe655de3c71a5740cec4fcb251aa48ca6745dbea6f5f7cfc1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d60795d8f310b155726534b8be3d0b8a7bc2ced468c6e64c8b9ae087b33ee00b", + "result": "valid" + }, + { + "tcId": 386, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a12124606bcbbb33cecec7fc8d78b3897192ca851560c539e47dd276c63bd3c2f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "675fef8f5680bf76220e91362613944099046b0ba07e5824e93f3e3cc2cc2758", + "result": "valid" + }, + { + "tcId": 387, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004244b7afe7f31289f9d6aaeb7f70d29a7b49a228c7bb202764aba94daaaa3332270c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "76b439f8ea7b42f11cd59e6d91b2d2a72577c185386b6af6639be8e3864a7f27", + "result": "valid" + }, + { + "tcId": 388, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042ac29db2ebc4fa9473b42bd335a60226579cc186b2c676a3b01bc60e589616165aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "56e63fa788121d5efa0ce3caf4605af18d48c631496cdfa862c43ecf5e5fc127", + "result": "valid" + }, + { + "tcId": 389, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e62aee5205a8063e3ae401d53e9343001e55eb5f4e4d6b70e2b84159cf3157e64ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "cff3b5e19ed67e5111dd76e310a1f11d7f99a93fbe9cc5c6f3384086cacd1142", + "result": "valid" + }, + { + "tcId": 390, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000431dce6de741f10267f2e8f3d572a4f49be5fe52ff7bff3c3b4646f38076c06752702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e29483884a74fb84f4601654885a0f574691394f064ea6937a846175ef081fc5", + "result": "valid" + }, + { + "tcId": 391, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046518cd66b1d841e689d5dc6674c7cc7d964574d1490fff7906bd373494791599104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9c6a4bcb2fc086aca8726d850fa79920214af4c151acea0fcf12a769ad1f3574", + "result": "valid" + }, + { + "tcId": 392, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004952a88ce31ad4cb086978e6c5621c3d8023b2c11418d6fd0dcef8de72123efc15d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "34b7abc3f3e36e37e2d5728a870a293a16403146ca67ff91cbabeee2bb2e038b", + "result": "valid" + }, + { + "tcId": 393, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042a43f33573b619719099cf54f6cccb28d16df3992239fadf79c7acb9c64f7af0f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9bd1284f1bcb1934d483834cae41a77db28cd9553869384755b6983f4f3848a0", + "result": "valid" + }, + { + "tcId": 394, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041b1b0c75408785e84727b0e55e4ba20d0f2599c4ed08482dc1f3b5df545691380162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "167e3db6a912ac6117644525911fc8872ed33b8e0bbd50073dd3c17a744e61e0", + "result": "valid" + }, + { + "tcId": 395, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200044dd1283bccd36cc3402f3a81e2e9b0d6a2b2b1debbbd44ffc1f179bd49cf0a7e604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "7c3020e279cb5af14184b4653cc87c1ddd7f49cd31cd371ae813681dd6617d0e", + "result": "valid" + }, + { + "tcId": 396, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a499dbf732e438be0eb084b9e6ad879dd7a2904bbb004b40027969a171f2d4267bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "acfdff566b8b55318869fa646f789f8036d40b90f0fc520ae2a5a27544f962c0", + "result": "valid" + }, + { + "tcId": 397, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004adcf0ffba9cb6ef0c8031c4291a434b18d78f42e45e62ba01fbe91f9273f0ad1ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5c6b01cff4e6ce81a630238b5db3662e77fb88bffdde61443a7d8554ba001ef2", + "result": "valid" + }, + { + "tcId": 398, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000421712725d9806acf54d3a6c82bf93c0fe249268ca9f42eceac19e93a5eab8056503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e7281d12b74b06eecb273ec3e0d8fe663e9ec1d5a50c2b6c68ec8b3693f23c4c", + "result": "valid" + }, + { + "tcId": 399, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041e02176824bd31eabdce03a9403c7d3c2ac631f9b0e88d9a924701c1b2f29b85cf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "80643ed8b9052a2e746a26d9178fe2ccff35edbb81f60cd78004fb8d5f143aae", + "result": "valid" + }, + { + "tcId": 400, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000463e7a1af36d6b540a49276aac3fec9cb45ed6bab167c06b0419a77b91399f6181e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "75873ac544ad69d3ddc5c9cffe384d275e9da2949d6982da4b990f8bf2b76474", + "result": "valid" + }, + { + "tcId": 401, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041e265ab5b7f7199470e532653d2a7b9a8b728970b838137c9692ed0692897b2ac1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "355c9faca29cf7cc968853ee29ffe62d1127fcc1dc57e9ddaf0e0f447146064e", + "result": "valid" + }, + { + "tcId": 402, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000454d2a4394c109fcbd3cb9886fec3add51ba4d2e44e1d5676e4b98f0c13655fc5f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "fc175a5ef18595b69e45be2cda8ae00d9c8bdbefbcf7f692f91cefdc560e4722", + "result": "valid" + }, + { + "tcId": 403, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000493f1459207fb09c6f0a88c398ac80d1052a4cd33e7eef5687da99ab97c6024b770c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "46559146a93aae904dbcaaaa07e6cd1bb450f1b37c83929a994b45792333d5f6", + "result": "valid" + }, + { + "tcId": 404, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200041fa049a1892b679857c6dff08af19db70cbc99b6f2d7bc51a341fe79d1647f4a5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c64b07119054a37961c0a177158256081b38b0087b307e0cad7e30d790ceb0ce", + "result": "valid" + }, + { + "tcId": 405, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000484e0b192d60abf531e828e887d366d869e1033a16e9c7f1167458c8134c10fba4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bea8cfc0bee8571ccf0c525654ef26d1fc782bb22deccf67ea4ea0803dc15daf", + "result": "valid" + }, + { + "tcId": 406, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042f9707c67118724111efbbbbf06b623ab2ffd9259ddc354fcaaf81ba01f6fa7b2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "60451da4adfe5bb393109069efdc84415ec8a2c429955cbf22a4340f8fc48936", + "result": "valid" + }, + { + "tcId": 407, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ac1fbbe42293a9f9ae104ee2da0b0a9b3464d5d8b1e854df19d3c4456af8f9a6104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d68e746f3d43feac5fd4898de943dc38205af7e2631ed732079bbfc8ab52511c", + "result": "valid" + }, + { + "tcId": 408, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bae10cf93ff7b72d6ed98519602e9f03aa40303fa0674fb3ddee7d2db1c92bb25d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "28daeaadc609386d770dff4c7120b2a87cab3e21fdb8a6e4dc1240a51d12e55c", + "result": "valid" + }, + { + "tcId": 409, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004edb4288cf5567673d50a1cd9e6bea45317823f30383f60d9bc3b9ee42ac29871f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bb4110b734c8ef8a08bb6011acb35cbda9ae8e2ef6c4d0862576a68792667bb9", + "result": "valid" + }, + { + "tcId": 410, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000413233e80f59ac2b59737e87877782ab3027c490df8ac0bf3f3ef1633872eec540162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e25c50037ca1913851b9758752659fb61c02d2a7c6b6aae29bda301907d99f5d", + "result": "valid" + }, + { + "tcId": 411, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043cd14f7e4b779615bc7ccee47e7f2b07394bf8f98503263411a549264a8fcf19604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "ad259f01e953263f40a39b14a538d076710c19207af936feabdf03bda7f067a5", + "result": "valid" + }, + { + "tcId": 412, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004946c278288616aa34790ca193686e745d3d58702866ddf1e95550711a9bfbdb87bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5ec6025ac7b25c0f095f3fdee3e2e508bd1437b9705c2543c0e5af1c1d363ffd", + "result": "valid" + }, + { + "tcId": 413, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047f195035feb2c04a9b149bb2ed3c5c458e95e7f7c418c4a07ea6107e4e32455addf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a2f93a84574a26b43880cde6ed440c7f7cc72c92504d5271999a8a78ffe3491d", + "result": "valid" + }, + { + "tcId": 414, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000440855844e04303843a24b01707544d1bbf97673266e03d77fbf80d8b64219bd8503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8d0cdb4977ba7661d41036aeb7a5f2dd207716d5d76eeb26629043c559ec2900", + "result": "valid" + }, + { + "tcId": 415, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000422cdb3ee47f14b3b0c0c8c256fb22e79126b436a2c9ff635a65151a0f0ffb1bfcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "defde4aa48f89b03f623ea1f946f1aa938c5aab879ca6319596926f085578edc", + "result": "valid" + }, + { + "tcId": 416, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042b7becd7066e22f121e7cf123d48c5445037c5a756ef314a66a7001636ee75cf1e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "afe0bfed69a600163865406127a8972b613232aa4c933a06b5a5b5bcff1596f8", + "result": "valid" + }, + { + "tcId": 417, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bb8da4a76ee3d1c4b33477bc8663def167a126c422ad47f6c2f8b539c6808936c1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f49bca7a6a5256ddf712775917c30e4873153469bae12fd5c5571031db7b1205", + "result": "valid" + }, + { + "tcId": 418, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040a0c37664823a5005d659f7c73c39ea172c862969c81e44f36c89e7c265ec8a8f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9c88b611b7f9aad33fabb09cff618bb1ca6fb904a289b1481da3d1e4e72589e4", + "result": "valid" + }, + { + "tcId": 419, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000447c33f6f78d3cd9971ecc50e7e2ac947f8c1103f9c5f0821379bd06ad8fca45670c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "42f634c06c4a0e7e956db6e86666603d26374cc74b11026f0318d1a25681a712", + "result": "valid" + }, + { + "tcId": 420, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b59d18ab8b0f9dd33484f43c3f6860229ba6a4c25a61cd0aaca23b76d60566cf5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "e2ceb946e7993f27a4327abdf61d4f06577e89c63b62a24aefbd905710d18669", + "result": "valid" + }, + { + "tcId": 421, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000494f4601b244d3a6ea6996fa244364f794399e0ff4316157db6023222fc0d90be4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "71637a5da2412a921f1636c69a6ee81083ee2b0e13766ad122791ef6f771896d", + "result": "valid" + }, + { + "tcId": 422, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200049e8c115b1ac87d986ee1b506b86a4e7b8ea041aa6a63d6ec80ec0f0cf69cfb3f2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bd265ed3078ca8c7788f594187c96c675aa623ecd01bfcad62d76a7881334f63", + "result": "valid" + }, + { + "tcId": 423, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004eec776b52b94141fc819d4b6b12d28e73555b5560507aba7df6f0484008de91f104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8d073fc592fb7aa6f7b908ed07148aa7be5a135c4b343ebe295198cba78e71ce", + "result": "valid" + }, + { + "tcId": 424, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004aff46a388e5afc220a8eec7a49af9d245384a3af1e0b407b4521f4e92d12dceb5d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a26d698e4613595aa61c8e2907d5241d6d14909737df59895841d07727bf1348", + "result": "valid" + }, + { + "tcId": 425, + "comment": "point with coordinate y = 1 in left to right addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e807e43d96f3701a9a5c13d122749084170fcd36a586a446c9fcb4600eede4fdf4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a8edc6f9af6bf74122c11ca1a50afbc4a3c4987bd0d1f73284d2c1371e613405", + "result": "valid" + }, + { + "tcId": 426, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004798868a56916d341e7d6f96359ae3658836e221459f4f7b7b63694de18a5e9247713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "17963de078996eb8503c7cc3e1a2d5147d7f0bfb251a020b4392033063587c8d", + "result": "valid" + }, + { + "tcId": 427, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ff419909d8a8ce0a9416051f4e256208c1dc035581a53312d566137e22104e9877421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "062799a19545d31b3ed72253bcde59762aa6104a88ac5e2fb68926b0f7146698", + "result": "valid" + }, + { + "tcId": 428, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200048b48119d7089d3b95cd2eaf8c85584fa8f5e56c4c4ccee7037d74cdbf88e571714c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9f42dd8fce13f8103b3b2bc15e61242e6820fe1325a20ef460fe64d9eb12b231", + "result": "valid" + }, + { + "tcId": 429, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e2888119379b5b2151bd788505def1d6bd786329431caf39705d9cbf96a42ea43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "d1b204e52d1fac6d504132c76ca233c87e377dcc79c893c970ddbb9f87b27fa0", + "result": "valid" + }, + { + "tcId": 430, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200046dcc3971bd20913d59a91f20d912f56d07e7f014206bef4a653ddfe5d12842c39b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c8d6bd28c1e65ae7c7a5debe67a7dfaf92b429ede368efc9da7d578a539b7054", + "result": "valid" + }, + { + "tcId": 431, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200047ebea45854569a1f7ea6b95b82d6befefbf6296ebc87c810b6cba93c0c1220b23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0d1f905cc74720bde67ae84f582728588c75444c273dae4106fa20d1d6946430", + "result": "valid" + }, + { + "tcId": 432, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ceab5937900d34fa88378d371f4acaa7c6a2028b6143213413f16ba2dc7147877713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3f014e309192588fa83e47d4ac9685d2041204e2eaf633a1312812e51ae74cbd", + "result": "valid" + }, + { + "tcId": 433, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004a4ffea5e25f75e4f689c81084a35c1220e8e6b914c482f4a2e8f93cffca6964777421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "68b404d556c82004c6c4bba4518ec00b1d4f1161cafe6c89aeb8494a9ba09db5", + "result": "valid" + }, + { + "tcId": 434, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004de8809ea0ecce1d24a0431429510383a6f6e5a1c51cea32d830c6c353042603e14c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c331ade7a457df7f12a2f5c43d7ea9486c1563b81cd8a0f23f923c1a9fa612e3", + "result": "valid" + }, + { + "tcId": 435, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004566209f174d6bf79720b70edb27e51350beeb2b0bcd083bbae7214f71cf824d43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "17b5c7a311eea9d2ab7571f8b9f848d4705997cf3eaf9bdcbe0e34a670f81f45", + "result": "valid" + }, + { + "tcId": 436, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004cc3181c0127137536ceec94fd45996657df72e0f97c44b9dad14763ce506e9dc9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "2f0e4eccbc4518ace558e06604f9bff4787f5b019437b52195ecb6b82191a6ae", + "result": "valid" + }, + { + "tcId": 437, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d7052a1eeafc0e78d79e7f26003aa0a409287cf476007df28d281b142be1a0e23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "7494d864cb6ea9c5d982d40a5f103700d02dc982637753cfc7d8afe1beafff70", + "result": "valid" + }, + { + "tcId": 438, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004b7cc3e2306dbf7c38ff179658706feffb5efdb6044c7e71435d7ff7d0ae8c7b37713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "a96873eef5d438b807853b6771c6a5197e6eef21efefca538b45e9e981c032e5", + "result": "valid" + }, + { + "tcId": 439, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200045bbe7c98015fd3a6034d79d867a4dcd52f95911932129da2fc0a58afe149137f77421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9124618913f20cdffa642207f192e67eb80ade53ac5535469abe90036d4af7e2", + "result": "valid" + }, + { + "tcId": 440, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004962fe47880a94a745928e3c4a29a42cb01334f1ee9646e62451c46ecd72f410914c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9d8b74888d942870b221de7a642032892bc99e34bd8550195f6f5f097547334a", + "result": "valid" + }, + { + "tcId": 441, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c71574f5538de5653c37168d47a2bcf43698ea260012cd0ae1304e474c63a4e63bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "16983377c0f1a9c004495b3fd9658363116eea644787d059d1140fb907555d4a", + "result": "valid" + }, + { + "tcId": 442, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c60244ce306e376f3968178f5293742d7a20e1dc47cfc517edada9db49d0cbbf9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "081af40a81d48c6b530140db935e605bf4cc7b10885f5b148f95f1bc8ad2e52d", + "result": "valid" + }, + { + "tcId": 443, + "comment": "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004aa3c3188c0ad5767a9bac77e7ceea05cfae1599ccd77b9fcbc0c3badc80c36ca3f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "7e4b973e6d4a357c400243a648c8a0a6a35cf231754afdef312d2f4b6abb988f", + "result": "valid" + }, + { + "tcId": 444, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200042cce8ddfe4827dc030ddf38f998b3f2ed5e0621d0b3805666daf48c8c31e75e5198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0f0235da2a06c8d408c27151f3f15342ed8c1945aaf84ed14993786d6ac5f570", + "result": "valid" + }, + { + "tcId": 445, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000414bfc3e5a46b69881a9a346d95894418614ed91476a1ddce48676b7cbab9ba02f334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "5622c2fbe8af5ad6cef72a01be186e554847576106f8979772fa56114d1160ab", + "result": "valid" + }, + { + "tcId": 446, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bd442fa5a2a8d72e13e44fd2222c85a006f03375e0211b272f555052b03db750be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "bb95e0d0fbaad86c5bd87b95946c77ff1d65322a175ccf16419102c0a17f5a72", + "result": "valid" + }, + { + "tcId": 447, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040d7a3ff49bda6a587ed07691450425aa02d253ba573a16ad86c61af412dd3c770b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "4510683c7bfa251f0cb56bba7e0ab74d90f5e2ca01e91e7ca99312ccff2d90b6", + "result": "valid" + }, + { + "tcId": 448, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bdea5d2a3adde7df2e839ff63f62534b3f27cb191bb54dfa1d39cbff713ba9ed307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "025485142ca1ced752289f772130fc10c75a4508c46bffdef9290ad3e7baf9ca", + "result": "valid" + }, + { + "tcId": 449, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004d4c063e3c036f47c92f6f5470a26a835e1a24505b14d1b29279062a16cf6f489198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "9067932150724965aa479c1ef1be55544bed9fa94500a3b67887ed91ae3b81e5", + "result": "valid" + }, + { + "tcId": 450, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200043cb9f07997756859e9b9a85b681fa50ee20357f535c1b311c4637d16b76b9ebff334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "f8084a89adccdc3aef89e5091a0f07d6160a66cb9575241100c1d39bf0549ae2", + "result": "valid" + }, + { + "tcId": 451, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004793412ff636c08a2d0f6d60cc608e9a9098349a2501f91c95f692010bc1238b2be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "4462558c89902117051cb2c599ad66f00887b54cae3da9c04d317a5b2afb463b", + "result": "valid" + }, + { + "tcId": 452, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004bd1eb0849e2e6a13d54b76518f11ba8775c2d7634d85152534bc7c3af4161efa0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "30b4741a64f87d28ec0029bd196b5a74555f2c9a976a46d628572474466a631d", + "result": "valid" + }, + { + "tcId": 453, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004624b3b4ba993a8b938125689f6cf757392ee390d14a90fea6db944b5a8deb8d0307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "3afc04ac92117e50b0913b09dbbb4e6c780c051500201fad512b79080bff39e2", + "result": "valid" + }, + { + "tcId": 454, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fe710e3c5b468dc33c2b17295c4e189b487d58dd437adf706ac05493cfea8df0198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "609637048586edc64cf5f28f1a505768c686471110070d783de499ffe6fe84da", + "result": "valid" + }, + { + "tcId": 455, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004ae864ba0c41f2e1dfbac2337025716d8bcadcef6539c6f1ff335176b8ddaa36ef334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "b1d4f27a6983c8ee417ef0f527d889d4a1ae41d3639244578c43d650c299fcd1", + "result": "valid" + }, + { + "tcId": 456, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004c987bd5af9eb202f1b24da2117ca90b6ef8c82e7cfbf530f71418f9a93b0085cbe345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "0007c9a27ac5067c9f0ad1a4d1e62110da1318893a658729713d82e333855b82", + "result": "valid" + }, + { + "tcId": 457, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000435670f86c5f72b93abe4131d2bea1fce876ad4e25b40d42d447d68cff90ca0be0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "8a3b23a91f0d5db8074a6a886889ee3e19aaf09b66ac9aad2e15c8bdba68085c", + "result": "valid" + }, + { + "tcId": 458, + "comment": "point with coordinate y = 1 in right to left addition chain", + "flags": [ + "EdgeCaseDoubling" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004dfca678a1b8e6f67996a097fc9ce37412de9fbd9cfa1a21b750cef48e5e595a1307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private": "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared": "c2af763f414cb2d7fd46257f0313b582c099b5e23b73e073b5ab7c230c45c883", + "result": "valid" + }, + { + "tcId": 459, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "03", + "shared": "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", + "result": "valid" + }, + { + "tcId": 460, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "shared": "5841acd3cff2d62861bbe11084738006d68ccf35acae615ee9524726e93d0da5", + "result": "valid" + }, + { + "tcId": 461, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "0100000000000000000000000000000000000000000000000000000000000000", + "shared": "4348e4cba371ead03982018abc9aacecaebfd636dda82e609fd298947f907de8", + "result": "valid" + }, + { + "tcId": 462, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "shared": "e56221c2b0dc33b98b90dfd3239a2c0cb1e4ad0399a3aaef3f9d47fb103daef0", + "result": "valid" + }, + { + "tcId": 463, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "008000000000000000000000000000000000000000000000000000000000000000", + "shared": "5b34a29b1c4ddcb2101162d34bed9f0702361fe5af505df315eff7befd0e4719", + "result": "valid" + }, + { + "tcId": 464, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03abfd25e8cd0364141", + "shared": "cece521b8b5a32bbee38936ba7d645824f238e561701a386fb888e010db54b2f", + "result": "valid" + }, + { + "tcId": 465, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfc25e8cd0364141", + "shared": "829521b79d71f5011e079756b851a0d5c83557866189a6258c1e78a1700c6904", + "result": "valid" + }, + { + "tcId": 466, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfca5e8cd0364141", + "shared": "8c5934793505a6a1f84d41283341680c4923f1f4d562989a11cc626fea5eda5a", + "result": "valid" + }, + { + "tcId": 467, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8bd0364141", + "shared": "356caee7e7eee031a15e54c3a5c4e72f9c74bb287ce601619ef85eb96c289452", + "result": "valid" + }, + { + "tcId": 468, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c3", + "shared": "09c7337df6c2b35edf3a21382511cc5add1a71a84cbf8d3396a5be548d92fa67", + "result": "valid" + }, + { + "tcId": 469, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364103", + "shared": "d16caedd25793666f9e26f5331382106f54095b3d20d40c745b68ca76c0e6983", + "result": "valid" + }, + { + "tcId": 470, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364123", + "shared": "b8ae1e21d8b34ce4caffed7167a26868ec80a7d4a6a98b639d4d05cd226504de", + "result": "valid" + }, + { + "tcId": 471, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364133", + "shared": "02776315fe147a36a4b0987492b6503acdea60f926450e5eddb9f88fc82178d3", + "result": "valid" + }, + { + "tcId": 472, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413b", + "shared": "3988c9c7050a28794934e5bd67629b556d97a4858d22812835f4a37dca351943", + "result": "valid" + }, + { + "tcId": 473, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "shared": "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", + "result": "valid" + }, + { + "tcId": 474, + "comment": "edge case private key", + "flags": [ + "AdditionChain" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private": "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f", + "shared": "4b52257d8b3ba387797fdf7a752f195ddc4f7d76263de61d0d52a5ec14a36cbf", + "result": "valid" + }, + { + "tcId": 475, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 476, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 477, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 478, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 479, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 480, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 481, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 482, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 483, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000000", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 484, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000001", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 485, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 486, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 487, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 488, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 489, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 490, + "comment": "point is not on curve", + "flags": [ + "InvalidCurveAttack" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 491, + "comment": "", + "flags": [ + "InvalidEncoding" + ], + "public": "3015301006072a8648ce3d020106052b8104000a030100", + "private": "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 492, + "comment": "public key has invalid point of order 2 on secp256r1. The point of the public key is a valid on secp256k1.", + "flags": [ + "WrongCurve" + ], + "public": "3059301306072a8648ce3d020106082a8648ce3d03010703420004ffffffff00000001000000000000000000000000ffffffffffffffffffffffff32d98e0d77dd0e543770ec994c0ae837e7bb36eb1d910b58a14a2a08dc182f83", + "private": "3b25129f3410ec89cc6dc539fd7601873ba6abf72a6d023f1aa9041765430ee6", + "shared": "1d3fc2b2e48b3e96c6323380fadb467825e69f5b9078a9e02173b477bc232cc1", + "result": "invalid" + }, + { + "tcId": 493, + "comment": "public key has invalid point of order 2 on FRP256v1. The point of the public key is a valid on secp256k1.", + "flags": [ + "WrongCurve" + ], + "public": "305b301506072a8648ce3d0201060a2a817a01815f6582000103420004f1fd178c0b3ad58f10126de8ce42435b3961adbcabc8ca6de8fcf353d86e9c03247e9edb2a633201dfc68fbd34556690db38ef76732f8a9052ee40d84e2ec35b", + "private": "485dea32cd245db99d88e1852587c161b81abeabb151ad3fc1e4dd2f591e9936", + "shared": "0a373d77057a50e3aad60b1e51bc017523dc2bdfef1c07cf4ed8393839224d0a", + "result": "invalid" + }, + { + "tcId": 494, + "comment": "public point not on curve", + "flags": [ + "ModifiedPublicPoint", + "InvalidPublic" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e4", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 495, + "comment": "public point = (0,0)", + "flags": [ + "ModifiedPublicPoint", + "InvalidPublic" + ], + "public": "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 496, + "comment": "order = -115792089237316195423570985008687907852837564279074904382605163141518161494337", + "flags": [ + "WrongOrder", + "InvalidPublic", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80221ff000000000000000000000000000000014551231950b75fc4402da1732fc9bebf0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "invalid" + }, + { + "tcId": 497, + "comment": "order = 0", + "flags": [ + "WrongOrder", + "InvalidPublic", + "UnnamedCurve" + ], + "public": "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201000201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "invalid" + }, + { + "tcId": 498, + "comment": "order = 1", + "flags": [ + "WrongOrder", + "UnusedParam", + "UnnamedCurve" + ], + "public": "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201010201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "acceptable" + }, + { + "tcId": 499, + "comment": "order = 26959946667150639794667015087019630673536463705607434823784316690060", + "flags": [ + "WrongOrder", + "UnusedParam", + "UnnamedCurve" + ], + "public": "3082012f3081e806072a8648ce3d02013081dc020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8021d00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8c0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "acceptable" + }, + { + "tcId": 500, + "comment": "generator = (0,0)", + "flags": [ + "ModifiedGenerator", + "UnusedParam", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "acceptable" + }, + { + "tcId": 501, + "comment": "generator not on curve", + "flags": [ + "ModifiedGenerator", + "UnusedParam", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4ba022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "acceptable" + }, + { + "tcId": 502, + "comment": "cofactor = -1", + "flags": [ + "NegativeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "invalid" + }, + { + "tcId": 503, + "comment": "no cofactor", + "flags": [ + "NoCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public": "308201303081e906072a8648ce3d02013081dd020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "invalid" + }, + { + "tcId": 504, + "comment": "cofactor = 2", + "flags": [ + "ModifiedCofactor", + "UnusedParam", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201020342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "acceptable" + }, + { + "tcId": 505, + "comment": "cofactor = n", + "flags": [ + "LargeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public": "308201553082010d06072a8648ce3d020130820100020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "invalid" + }, + { + "tcId": 506, + "comment": "no cofactor", + "flags": [ + "NoCofactor", + "UnusedParam", + "UnnamedCurve" + ], + "public": "308201303081e906072a8648ce3d02013081dd020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "acceptable" + }, + { + "tcId": 507, + "comment": "modified prime", + "flags": [ + "ModifiedPrime", + "InvalidPublic", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fb524ac7055bebf603a4e216abaa6a9ef8eb2bbea2cd820e59d46d8501f6268b304404200000000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000000070441040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101034200040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "c5956b8cf7244e3c0457658a214210b358205cab12374d523ecf57895cecfeb0", + "result": "invalid" + }, + { + "tcId": 508, + "comment": "using secp224r1", + "flags": [ + "ModifiedGroup", + "InvalidPublic" + ], + "public": "304e301006072a8648ce3d020106052b81040021033a0004074f56dc2ea648ef89c3b72e23bbd2da36f60243e4d2067b70604af1c2165cec2f86603d60c8a611d5b84ba3d91dfe1a480825bcc4af3bcf", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 509, + "comment": "using secp256r1", + "flags": [ + "ModifiedGroup", + "InvalidPublic" + ], + "public": "3059301306072a8648ce3d020106082a8648ce3d03010703420004cbf6606595a3ee50f9fceaa2798c2740c82540516b4e5a7d361ff24e9dd15364e5408b2e679f9d5310d1f6893b36ce16b4a507509175fcb52aea53b781556b39", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 510, + "comment": "a = 0", + "flags": [ + "ModifiedCurveParameter", + "UnusedParam", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result": "acceptable" + }, + { + "tcId": 511, + "comment": "public key of order 3", + "flags": [ + "WeakPublicKey", + "InvalidPublic", + "UnnamedCurve" + ], + "public": "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f304404209234b518bfe789f01e2389571299e39b4596c63a14d598659341dd313c65e08a04209d569a9efeeb4362b094d096024cba7b53d51dbc33818c8cdf37b9315d2e7bab044104fb6075d26c3501c014e48c79b3463cd768378c390d7e6eeb379717d490c4e63487fbca88e6867877e98f43ec02f4a0f45ef0f94310d8ee3d70a10280ce2ae6b3022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414102010103420004fb6075d26c3501c014e48c79b3463cd768378c390d7e6eeb379717d490c4e63478043577197987881670bc13fd0b5f0ba10f06bcef2711c28f5efd7e31d5157c", + "private": "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared": "", + "result": "invalid" + }, + { + "tcId": 512, + "comment": "Public key uses wrong curve: secp224r1", + "flags": [ + "WrongCurve" + ], + "public": "304e301006072a8648ce3d020106052b81040021033a000450eb062b54940a455719d523e1ec106525dda34c2fd95ace62b9b16d315d323f089173d10c45dceff155942431750c00ca36f463828e9fab", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 513, + "comment": "Public key uses wrong curve: secp256r1", + "flags": [ + "WrongCurve" + ], + "public": "3059301306072a8648ce3d020106082a8648ce3d0301070342000406372852584037722a7f9bfaad5661acb623162d45f70a552c617f4080e873aa43609275dff6dcaaa122a745d0f154681f9c7726867b43e7523b7f5ab5ea963e", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 514, + "comment": "Public key uses wrong curve: secp384r1", + "flags": [ + "WrongCurve" + ], + "public": "3076301006072a8648ce3d020106052b81040022036200040ef5804731d918f037506ee00b8602b877c7d509ffa2c0847a86e7a2d358ba7c981c2a74b22401ac615307a6deb275402fa6c8218c3374f8a91752d2eff6bd14ad8cae596d2f37dae8aeec085760edf4fda9a7cf70253898a54183469072a561", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 515, + "comment": "Public key uses wrong curve: secp521r1", + "flags": [ + "WrongCurve" + ], + "public": "30819b301006072a8648ce3d020106052b81040023038186000400921da57110db26c7838a69d574fc98588c5c07a792cb379f46664cc773c1e1f6fa16148667748ede232d1a1f1cea7f152c5d586172acbeaa48416bcbd70bb27f0f01b4477e1ae74bf4f093184a9f26f103712ccf6ceb45a0505b191606d897edaf872b37f0f90a933000a80fc3207048323c16883a3d67a90aa78bcc9c5e58d784b9b9", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 516, + "comment": "Public key uses wrong curve: secp224k1", + "flags": [ + "WrongCurve" + ], + "public": "304e301006072a8648ce3d020106052b81040020033a000456dd09f8a8c19039286b6aa79d099ff3e35ff74400437d2072fd9faa7f2901db79d793f55268980f7d395055330a91b46bf4a62c3a528230", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 517, + "comment": "Public key uses wrong curve: brainpoolP224r1", + "flags": [ + "WrongCurve" + ], + "public": "3052301406072a8648ce3d020106092b2403030208010105033a00042c9fdd1914cacdb28e39e6fc24b4c3c666cc0d438acc4529a6cc297a2d0fdecb3028d9e4d84c711db352379c080c78659969bdc5d3218901", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 518, + "comment": "Public key uses wrong curve: brainpoolP256r1", + "flags": [ + "WrongCurve" + ], + "public": "305a301406072a8648ce3d020106092b240303020801010703420004120e4db849e5d960741c7d221aa80fe6e4fcd578191b7f845a68a6fcb8647719a6fffb6165d8ec39389eecc530839c321b2e9040027fba5d9cb9311df7cd3d4d", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 519, + "comment": "Public key uses wrong curve: brainpoolP320r1", + "flags": [ + "WrongCurve" + ], + "public": "306a301406072a8648ce3d020106092b2403030208010109035200040efb1c104938f59a931fe6bf69f7ead4036d2336075a708e66b020e1bc5bb6d9cdc86d4e8fa181d7c7ea1af28353044e8cec12eec75a6dd87a5dc902024d93f8c8d9bf43b453fd919151f9bd7bb955c7", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 520, + "comment": "Public key uses wrong curve: brainpoolP384r1", + "flags": [ + "WrongCurve" + ], + "public": "307a301406072a8648ce3d020106092b240303020801010b036200043e96d75b79214e69a4550e25375478bdc9c2a9d0178a77b5700bd5f12e3ce142f50c93dc1ee7268456d7eae2d44b718d6f159e896ae14fbe3aba397801a95e2bb6a9a761e865b289dd9db64aa07c794cedf77328543b94c9b54ce0cf04c60ac8", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 521, + "comment": "Public key uses wrong curve: brainpoolP512r1", + "flags": [ + "WrongCurve" + ], + "public": "30819b301406072a8648ce3d020106092b240303020801010d03818200044f191130740f1b75ae13402960eb22ea801db80ed51a461e06a7b3ba60c9bddd132a6465bbee8afd70cfb4495efbda4f1567b958e6e305bfcb4ac8f05172688e0f2f175aa12425be3ab7271b42f258639e868677d1163c12e641229f1e6427761c9e294de51db564151b21a051d2f7a13661852799557a556a5f3c51d36d083a", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 522, + "comment": "Public key uses wrong curve: brainpoolP224t1", + "flags": [ + "WrongCurve" + ], + "public": "3052301406072a8648ce3d020106092b2403030208010106033a00044964b948cefa39cd769e3480d4840a3c58e966161be80df02d9aab33b4a318a32f30130224edcefe0dd64342404e594aa334995b179f641f", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 523, + "comment": "Public key uses wrong curve: brainpoolP256t1", + "flags": [ + "WrongCurve" + ], + "public": "305a301406072a8648ce3d020106092b24030302080101080342000411157979c08bcd175d34572209a85f3f5d602e35bdc3b553b0f19307672b31ba69d0556bce48c43e2e7e6177055221a4c4b7eb17ee9708f49216de76d6e92ab8", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 524, + "comment": "Public key uses wrong curve: brainpoolP320t1", + "flags": [ + "WrongCurve" + ], + "public": "306a301406072a8648ce3d020106092b240303020801010a035200048bb517e198930eba57293419876a8793f711de37c27f200e6fb2c2b13e9fabd4fbc42ad61751ca583031ba76cbc6d745d115addc74eab63bf415c4fa20dbbecae98ac3c3da1a041705cf8959e2ccf453", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 525, + "comment": "Public key uses wrong curve: brainpoolP384t1", + "flags": [ + "WrongCurve" + ], + "public": "307a301406072a8648ce3d020106092b240303020801010c036200045eb38d0261b744b03abef4ae7c17bc886b5b426bd910958f8a49ef62053048f869541b7a05d244315fc9cd74271ec3d518d94114b6006017f4ed5e3c06322baa1c75809a1057ba6fa46d1e1a9927a262e627940d5da538b5a3d1d794d9c866a4", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 526, + "comment": "Public key uses wrong curve: brainpoolP512t1", + "flags": [ + "WrongCurve" + ], + "public": "30819b301406072a8648ce3d020106092b240303020801010e0381820004035fc238e57d980beae0215fb89108f9c6c4afda5d920f9d0583ee7d65f8778ecfff24a31d4f32deb6ea5f7e3adb6affb9327a5e62e09cba07c88b119fd104a83b7811e958e393971a5c9417412070b9f18b03be37e81e0bca5d3ff0873ed1f3113ed0fc57a0344321fb4d6c43f2f6e630a3d3883efe4c21df3e0f0b1208226b", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 527, + "comment": "Public key uses wrong curve: FRP256v1", + "flags": [ + "WrongCurve" + ], + "public": "305b301506072a8648ce3d0201060a2a817a01815f6582000103420004375e9438d4ab14e298a75eab1e2d51a9248c8ee0bbb24397cbd4651517faedd26d4ded568d2348a473aa5a7570107dc6fc60a2ce0c4143446b5b09ab3fcc7bb4", + "private": "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared": "", + "result": "invalid" + }, + { + "tcId": 528, + "comment": "invalid public key", + "flags": [ + "InvalidCompressedPublic", + "CompressedPoint" + ], + "public": "3036301006072a8648ce3d020106052b8104000a03220002977cb7fb9a0ec5b208e811d6a0795eb78d7642e3cac42a801bcc8fc0f06472d4", + "private": "00d09182a4d0c94ba85f82eff9fc1bddb0b07d3f2af8632fc1c73a3604e8f0b335", + "shared": "", + "result": "invalid" + }, + { + "tcId": 529, + "comment": "public key is a low order point on twist", + "flags": [ + "WrongCurve", + "CompressedPoint" + ], + "public": "3036301006072a8648ce3d020106052b8104000a032200020000000000000000000000000000000000000000000000000000000000000000", + "private": "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb300", + "shared": "", + "result": "invalid" + }, + { + "tcId": 530, + "comment": "public key is a low order point on twist", + "flags": [ + "WrongCurve", + "CompressedPoint" + ], + "public": "3036301006072a8648ce3d020106052b8104000a032200030000000000000000000000000000000000000000000000000000000000000000", + "private": "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb2ff", + "shared": "", + "result": "invalid" + }, + { + "tcId": 531, + "comment": "length of sequence uses long form encoding", + "flags": [ + "InvalidAsn" + ], + "public": "308156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 532, + "comment": "length of sequence uses long form encoding", + "flags": [ + "InvalidAsn" + ], + "public": "305730811006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 533, + "comment": "length of sequence contains a leading 0", + "flags": [ + "InvalidAsn" + ], + "public": "30820056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 534, + "comment": "length of sequence contains a leading 0", + "flags": [ + "InvalidAsn" + ], + "public": "30583082001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 535, + "comment": "length of sequence uses 87 instead of 86", + "flags": [ + "InvalidAsn" + ], + "public": "3057301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 536, + "comment": "length of sequence uses 85 instead of 86", + "flags": [ + "InvalidAsn" + ], + "public": "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 537, + "comment": "uint32 overflow in length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30850100000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 538, + "comment": "uint32 overflow in length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305b3085010000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 539, + "comment": "uint64 overflow in length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3089010000000000000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 540, + "comment": "uint64 overflow in length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305f308901000000000000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 541, + "comment": "length of sequence = 2**31 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "30847fffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 542, + "comment": "length of sequence = 2**31 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a30847fffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 543, + "comment": "length of sequence = 2**32 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "3084ffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 544, + "comment": "length of sequence = 2**32 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a3084ffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 545, + "comment": "length of sequence = 2**40 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "3085ffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 546, + "comment": "length of sequence = 2**40 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305b3085ffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 547, + "comment": "length of sequence = 2**64 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "3088ffffffffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 548, + "comment": "length of sequence = 2**64 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305e3088ffffffffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 549, + "comment": "incorrect length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30ff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 550, + "comment": "incorrect length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305630ff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 551, + "comment": "replaced sequence by an indefinite length tag without termination", + "flags": [ + "InvalidAsn" + ], + "public": "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 552, + "comment": "replaced sequence by an indefinite length tag without termination", + "flags": [ + "InvalidAsn" + ], + "public": "3056308006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 553, + "comment": "removing sequence", + "flags": [ + "InvalidAsn" + ], + "public": "", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 554, + "comment": "removing sequence", + "flags": [ + "InvalidAsn" + ], + "public": "304403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 555, + "comment": "lonely sequence tag", + "flags": [ + "InvalidAsn" + ], + "public": "30", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 556, + "comment": "lonely sequence tag", + "flags": [ + "InvalidAsn" + ], + "public": "30453003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 557, + "comment": "appending 0's to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 558, + "comment": "appending 0's to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 559, + "comment": "prepending 0's to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30580000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 560, + "comment": "prepending 0's to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30583012000006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 561, + "comment": "appending unused 0's to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 562, + "comment": "appending unused 0's to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 563, + "comment": "appending null value to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 564, + "comment": "appending null value to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d020106052b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 565, + "comment": "prepending garbage to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305b4981773056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 566, + "comment": "prepending garbage to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305a25003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 567, + "comment": "prepending garbage to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305b3015498177301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 568, + "comment": "prepending garbage to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305a30142500301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 569, + "comment": "appending garbage to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 570, + "comment": "appending garbage to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305e3012301006072a8648ce3d020106052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 571, + "comment": "including undefined tags", + "flags": [ + "InvalidAsn" + ], + "public": "305eaa00bb00cd003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 572, + "comment": "including undefined tags", + "flags": [ + "InvalidAsn" + ], + "public": "305e3018aa00bb00cd00301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 573, + "comment": "including undefined tags", + "flags": [ + "InvalidAsn" + ], + "public": "305e3018260faa00bb00cd0006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 574, + "comment": "including undefined tags", + "flags": [ + "InvalidAsn" + ], + "public": "305e301806072a8648ce3d0201260daa00bb00cd0006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 575, + "comment": "including undefined tags", + "flags": [ + "InvalidAsn" + ], + "public": "305e301006072a8648ce3d020106052b8104000a234aaa00bb00cd0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 576, + "comment": "truncated length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3081", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 577, + "comment": "truncated length of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3046308103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 578, + "comment": "including undefined tags to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305caa02aabb3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 579, + "comment": "including undefined tags to sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305c3016aa02aabb301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 580, + "comment": "Replacing sequence with NULL", + "flags": [ + "InvalidAsn" + ], + "public": "0500", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 581, + "comment": "Replacing sequence with NULL", + "flags": [ + "InvalidAsn" + ], + "public": "3046050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 582, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "2e56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 583, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "2f56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 584, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 585, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3256301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 586, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "ff56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 587, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30562e1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 588, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30562f1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 589, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3056311006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 590, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3056321006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 591, + "comment": "changing tag value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3056ff1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 592, + "comment": "dropping value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 593, + "comment": "dropping value of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3046300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 594, + "comment": "truncated sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 595, + "comment": "truncated sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30551006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 596, + "comment": "truncated sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3055300f06072a8648ce3d020106052b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 597, + "comment": "truncated sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3055300f072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 598, + "comment": "sequence of size 4183 to check for overflows", + "flags": [ + "InvalidAsn" + ], + "public": "30821057301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 599, + "comment": "indefinite length", + "flags": [ + "InvalidAsn" + ], + "public": "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 600, + "comment": "indefinite length", + "flags": [ + "InvalidAsn" + ], + "public": "3058308006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 601, + "comment": "indefinite length with truncated delimiter", + "flags": [ + "InvalidAsn" + ], + "public": "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326700", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 602, + "comment": "indefinite length with truncated delimiter", + "flags": [ + "InvalidAsn" + ], + "public": "3057308006072a8648ce3d020106052b8104000a0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 603, + "comment": "indefinite length with additional element", + "flags": [ + "InvalidAsn" + ], + "public": "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326705000000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 604, + "comment": "indefinite length with additional element", + "flags": [ + "InvalidAsn" + ], + "public": "305a308006072a8648ce3d020106052b8104000a0500000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 605, + "comment": "indefinite length with truncated element", + "flags": [ + "InvalidAsn" + ], + "public": "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267060811220000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 606, + "comment": "indefinite length with truncated element", + "flags": [ + "InvalidAsn" + ], + "public": "305c308006072a8648ce3d020106052b8104000a06081122000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 607, + "comment": "indefinite length with garbage", + "flags": [ + "InvalidAsn" + ], + "public": "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000fe02beef", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 608, + "comment": "indefinite length with garbage", + "flags": [ + "InvalidAsn" + ], + "public": "305c308006072a8648ce3d020106052b8104000a0000fe02beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 609, + "comment": "indefinite length with nonempty EOC", + "flags": [ + "InvalidAsn" + ], + "public": "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670002beef", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 610, + "comment": "indefinite length with nonempty EOC", + "flags": [ + "InvalidAsn" + ], + "public": "305a308006072a8648ce3d020106052b8104000a0002beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 611, + "comment": "prepend empty sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30583000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 612, + "comment": "prepend empty sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30583012300006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 613, + "comment": "append empty sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32673000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 614, + "comment": "append empty sequence", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d020106052b8104000a300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 615, + "comment": "append garbage with high tag number", + "flags": [ + "InvalidAsn" + ], + "public": "3059301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267bf7f00", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 616, + "comment": "append garbage with high tag number", + "flags": [ + "InvalidAsn" + ], + "public": "3059301306072a8648ce3d020106052b8104000abf7f0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 617, + "comment": "append null with explicit tag", + "flags": [ + "InvalidAsn" + ], + "public": "305a301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267a0020500", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 618, + "comment": "append null with explicit tag", + "flags": [ + "InvalidAsn" + ], + "public": "305a301406072a8648ce3d020106052b8104000aa002050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 619, + "comment": "append null with implicit tag", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267a000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 620, + "comment": "append null with implicit tag", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d020106052b8104000aa00003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 621, + "comment": "sequence of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 622, + "comment": "sequence of sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30583012301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 623, + "comment": "truncated sequence: removed last 1 elements", + "flags": [ + "InvalidAsn" + ], + "public": "3012301006072a8648ce3d020106052b8104000a", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 624, + "comment": "truncated sequence: removed last 1 elements", + "flags": [ + "InvalidAsn" + ], + "public": "304f300906072a8648ce3d020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 625, + "comment": "repeating element in sequence", + "flags": [ + "InvalidAsn" + ], + "public": "30819a301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 626, + "comment": "repeating element in sequence", + "flags": [ + "InvalidAsn" + ], + "public": "305d301706072a8648ce3d020106052b8104000a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 627, + "comment": "length of sequence uses 17 instead of 16", + "flags": [ + "InvalidAsn" + ], + "public": "3056301106072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 628, + "comment": "length of sequence uses 15 instead of 16", + "flags": [ + "InvalidAsn" + ], + "public": "3056300f06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 629, + "comment": "sequence of size 4113 to check for overflows", + "flags": [ + "InvalidAsn" + ], + "public": "308210593082101106072a8648ce3d020106052b8104000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 630, + "comment": "length of oid uses long form encoding", + "flags": [ + "InvalidAsn" + ], + "public": "305730110681072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 631, + "comment": "length of oid uses long form encoding", + "flags": [ + "InvalidAsn" + ], + "public": "3057301106072a8648ce3d02010681052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 632, + "comment": "length of oid contains a leading 0", + "flags": [ + "InvalidAsn" + ], + "public": "30583012068200072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 633, + "comment": "length of oid contains a leading 0", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d0201068200052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 634, + "comment": "length of oid uses 8 instead of 7", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006082a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 635, + "comment": "length of oid uses 6 instead of 7", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006062a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 636, + "comment": "uint32 overflow in length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "305b3015068501000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 637, + "comment": "uint32 overflow in length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "305b301506072a8648ce3d0201068501000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 638, + "comment": "uint64 overflow in length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "305f301906890100000000000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 639, + "comment": "uint64 overflow in length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "305f301906072a8648ce3d020106890100000000000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 640, + "comment": "length of oid = 2**31 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a301406847fffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 641, + "comment": "length of oid = 2**31 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a301406072a8648ce3d020106847fffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 642, + "comment": "length of oid = 2**32 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a30140684ffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 643, + "comment": "length of oid = 2**32 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a301406072a8648ce3d02010684ffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 644, + "comment": "length of oid = 2**40 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305b30150685ffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 645, + "comment": "length of oid = 2**40 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305b301506072a8648ce3d02010685ffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 646, + "comment": "length of oid = 2**64 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305e30180688ffffffffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 647, + "comment": "length of oid = 2**64 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305e301806072a8648ce3d02010688ffffffffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 648, + "comment": "incorrect length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006ff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 649, + "comment": "incorrect length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106ff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 650, + "comment": "replaced oid by an indefinite length tag without termination", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006802a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 651, + "comment": "replaced oid by an indefinite length tag without termination", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106802b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 652, + "comment": "removing oid", + "flags": [ + "InvalidAsn" + ], + "public": "304d300706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 653, + "comment": "lonely oid tag", + "flags": [ + "InvalidAsn" + ], + "public": "304e30080606052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 654, + "comment": "lonely oid tag", + "flags": [ + "InvalidAsn" + ], + "public": "3050300a06072a8648ce3d02010603420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 655, + "comment": "appending 0's to oid", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206092a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 656, + "comment": "appending 0's to oid", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d020106072b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 657, + "comment": "prepending 0's to oid", + "flags": [ + "InvalidAsn" + ], + "public": "30583012060900002a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 658, + "comment": "prepending 0's to oid", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d0201060700002b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 659, + "comment": "appending unused 0's to oid", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 660, + "comment": "appending null value to oid", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206092a8648ce3d0201050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 661, + "comment": "appending null value to oid", + "flags": [ + "InvalidAsn" + ], + "public": "3058301206072a8648ce3d020106072b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 662, + "comment": "prepending garbage to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305b3015260c49817706072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 663, + "comment": "prepending garbage to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305a3014260b250006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 664, + "comment": "prepending garbage to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305b301506072a8648ce3d0201260a49817706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 665, + "comment": "prepending garbage to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305a301406072a8648ce3d02012609250006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 666, + "comment": "appending garbage to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305e3018260906072a8648ce3d02010004deadbeef06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 667, + "comment": "appending garbage to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305e301806072a8648ce3d0201260706052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 668, + "comment": "truncated length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "304f3009068106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 669, + "comment": "truncated length of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3051300b06072a8648ce3d0201068103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 670, + "comment": "including undefined tags to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305c3016260daa02aabb06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 671, + "comment": "including undefined tags to oid", + "flags": [ + "InvalidAsn" + ], + "public": "305c301606072a8648ce3d0201260baa02aabb06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 672, + "comment": "Replacing oid with NULL", + "flags": [ + "InvalidAsn" + ], + "public": "304f3009050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 673, + "comment": "Replacing oid with NULL", + "flags": [ + "InvalidAsn" + ], + "public": "3051300b06072a8648ce3d0201050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 674, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301004072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 675, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301005072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 676, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301007072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 677, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301008072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 678, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "30563010ff072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 679, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020104052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 680, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020105052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 681, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020107052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 682, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020108052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 683, + "comment": "changing tag value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d0201ff052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 684, + "comment": "dropping value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "304f3009060006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 685, + "comment": "dropping value of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3051300b06072a8648ce3d0201060003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 686, + "comment": "modifying first byte of oid", + "flags": [ + "InvalidAsn" + ], + "public": "305630100607288648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 687, + "comment": "modifying first byte of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d02010605298104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 688, + "comment": "modifying last byte of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d028106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 689, + "comment": "modifying last byte of oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104008a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 690, + "comment": "truncated oid", + "flags": [ + "InvalidAsn" + ], + "public": "3055300f06062a8648ce3d0206052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 691, + "comment": "truncated oid", + "flags": [ + "InvalidAsn" + ], + "public": "3055300f06068648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 692, + "comment": "truncated oid", + "flags": [ + "InvalidAsn" + ], + "public": "3055300f06072a8648ce3d020106042b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 693, + "comment": "truncated oid", + "flags": [ + "InvalidAsn" + ], + "public": "3055300f06072a8648ce3d020106048104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 694, + "comment": "oid of size 4104 to check for overflows", + "flags": [ + "InvalidAsn" + ], + "public": "3082105b30821013068210082a8648ce3d0201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 695, + "comment": "wrong oid", + "flags": [ + "InvalidAsn" + ], + "public": "3054300e06052b0e03021a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 696, + "comment": "wrong oid", + "flags": [ + "InvalidAsn" + ], + "public": "30583012060960864801650304020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 697, + "comment": "wrong oid", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b0e03021a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 698, + "comment": "wrong oid", + "flags": [ + "InvalidAsn" + ], + "public": "305a301406072a8648ce3d0201060960864801650304020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 699, + "comment": "longer oid", + "flags": [ + "InvalidAsn" + ], + "public": "3057301106082a8648ce3d02010106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 700, + "comment": "longer oid", + "flags": [ + "InvalidAsn" + ], + "public": "3057301106072a8648ce3d020106062b8104000a0103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 701, + "comment": "oid with modified node", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d021106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 702, + "comment": "oid with modified node", + "flags": [ + "InvalidAsn" + ], + "public": "305a3014060b2a8648ce3d02888080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 703, + "comment": "oid with modified node", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104001a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 704, + "comment": "oid with modified node", + "flags": [ + "InvalidAsn" + ], + "public": "305a301406072a8648ce3d020106092b810400888080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 705, + "comment": "large integer in oid", + "flags": [ + "InvalidAsn" + ], + "public": "305f301906102a8648ce3d028280808080808080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 706, + "comment": "large integer in oid", + "flags": [ + "InvalidAsn" + ], + "public": "305f301906072a8648ce3d0201060e2b8104008280808080808080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 707, + "comment": "oid with invalid node", + "flags": [ + "InvalidAsn" + ], + "public": "3057301106082a8648ce3d0201e006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 708, + "comment": "oid with invalid node", + "flags": [ + "InvalidAsn" + ], + "public": "3057301106082a808648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 709, + "comment": "oid with invalid node", + "flags": [ + "InvalidAsn" + ], + "public": "3057301106072a8648ce3d020106062b8104000ae003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 710, + "comment": "oid with invalid node", + "flags": [ + "InvalidAsn" + ], + "public": "3057301106072a8648ce3d020106062b808104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 711, + "comment": "oid with 263 nodes", + "flags": [ + "InvalidAsn" + ], + "public": "3082015b30820113068201082a8648ce3d0201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 712, + "comment": "length of oid uses 6 instead of 5", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106062b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 713, + "comment": "length of oid uses 4 instead of 5", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106042b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 714, + "comment": "oid of size 4102 to check for overflows", + "flags": [ + "InvalidAsn" + ], + "public": "3082105b3082101306072a8648ce3d0201068210062b8104000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 715, + "comment": "oid with 262 nodes", + "flags": [ + "InvalidAsn" + ], + "public": "3082015b3082011306072a8648ce3d0201068201062b8104000a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 716, + "comment": "length of bit string uses long form encoding", + "flags": [ + "InvalidAsn" + ], + "public": "3057301006072a8648ce3d020106052b8104000a0381420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 717, + "comment": "length of bit string contains a leading 0", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a038200420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 718, + "comment": "length of bit string uses 67 instead of 66", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03430004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 719, + "comment": "length of bit string uses 65 instead of 66", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 720, + "comment": "uint32 overflow in length of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "305b301006072a8648ce3d020106052b8104000a038501000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 721, + "comment": "uint64 overflow in length of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "305f301006072a8648ce3d020106052b8104000a03890100000000000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 722, + "comment": "length of bit string = 2**31 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a301006072a8648ce3d020106052b8104000a03847fffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 723, + "comment": "length of bit string = 2**32 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305a301006072a8648ce3d020106052b8104000a0384ffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 724, + "comment": "length of bit string = 2**40 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305b301006072a8648ce3d020106052b8104000a0385ffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 725, + "comment": "length of bit string = 2**64 - 1", + "flags": [ + "InvalidAsn" + ], + "public": "305e301006072a8648ce3d020106052b8104000a0388ffffffffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 726, + "comment": "incorrect length of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03ff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 727, + "comment": "replaced bit string by an indefinite length tag without termination", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03800004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 728, + "comment": "lonely bit string tag", + "flags": [ + "InvalidAsn" + ], + "public": "3013301006072a8648ce3d020106052b8104000a03", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 729, + "comment": "appending 0's to bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 730, + "comment": "prepending 0's to bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a034400000004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 731, + "comment": "appending null value to bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 732, + "comment": "prepending garbage to bit string", + "flags": [ + "InvalidAsn" + ], + "public": "305b301006072a8648ce3d020106052b8104000a234749817703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 733, + "comment": "prepending garbage to bit string", + "flags": [ + "InvalidAsn" + ], + "public": "305a301006072a8648ce3d020106052b8104000a2346250003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 734, + "comment": "appending garbage to bit string", + "flags": [ + "InvalidAsn" + ], + "public": "305e301006072a8648ce3d020106052b8104000a234403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 735, + "comment": "truncated length of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3014301006072a8648ce3d020106052b8104000a0381", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 736, + "comment": "including undefined tags to bit string", + "flags": [ + "InvalidAsn" + ], + "public": "305c301006072a8648ce3d020106052b8104000a2348aa02aabb03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 737, + "comment": "Replacing bit string with NULL", + "flags": [ + "InvalidAsn" + ], + "public": "3014301006072a8648ce3d020106052b8104000a0500", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 738, + "comment": "changing tag value of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a01420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 739, + "comment": "changing tag value of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a02420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 740, + "comment": "changing tag value of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a04420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 741, + "comment": "changing tag value of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a05420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 742, + "comment": "changing tag value of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000aff420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 743, + "comment": "dropping value of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3014301006072a8648ce3d020106052b8104000a0300", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 744, + "comment": "modifying first byte of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420204e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 745, + "comment": "modifying last byte of bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32e7", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 746, + "comment": "truncated bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3055301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 747, + "comment": "truncated bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3055301006072a8648ce3d020106052b8104000a034104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 748, + "comment": "bit string of size 4163 to check for overflows", + "flags": [ + "InvalidAsn" + ], + "public": "30821059301006072a8648ce3d020106052b8104000a038210430004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 749, + "comment": "declaring bits as unused in bit string", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03420104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 750, + "comment": "unused bits in bit string", + "flags": [ + "InvalidAsn" + ], + "public": "305a301006072a8648ce3d020106052b8104000a03462004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326701020304", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 751, + "comment": "unused bits in empty bit-string", + "flags": [ + "InvalidAsn" + ], + "public": "3015301006072a8648ce3d020106052b8104000a030103", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + }, + { + "tcId": 752, + "comment": "128 unused bits", + "flags": [ + "InvalidAsn" + ], + "public": "3056301006072a8648ce3d020106052b8104000a03428004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private": "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared": "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result": "acceptable" + } + ] + } + ] +}