Skip to content

fix: check bls12-381 point in subgroup#253

Open
lightsing wants to merge 1 commit into
scroll-tech:masterfrom
DogeOS69:scroll/fix/bls12-381-subgroup
Open

fix: check bls12-381 point in subgroup#253
lightsing wants to merge 1 commit into
scroll-tech:masterfrom
DogeOS69:scroll/fix/bls12-381-subgroup

Conversation

@lightsing

Copy link
Copy Markdown
Contributor

Summary

Adds a BLS12-381 G1 subgroup-membership check for the KZG commitment and proof points consumed by the batch circuit's EIP-4844 point-evaluation. This is the G1 counterpart to #247, which added the equivalent check on the G2 /
extension-field side.

Without this check, a point that lies on the curve but outside the prime-order subgroup G1 would be accepted, which breaks the soundness of the pairing-based KZG verification.

Background

EIP-4844 blob consistency is proven in-circuit via a KZG pairing check (verify_kzg_proof). The commitment and proof are G1 points supplied through the witness. On-curve validation alone is insufficient: E(Fp) has order h · r, where r is the G1 subgroup order and h the cofactor, so a crafted witness could supply an on-curve point in the h-torsion (or a mixed point) that is not in G1. Pairing checks are only sound for subgroup elements, so membership must be enforced.

Change

  • New is_in_g1_subgroup(p: &G1Affine) -> bool (blob_consistency/openvm.rs), using the GLV endomorphism (Bowe's fast subgroup test):
    • φ(x, y) = (β·x, y) acts as [-x²] on G1, so for any P ∈ G1:
      [x²]P == -φ(P) == (β·Pₓ, -P_y).
    • Implemented as a single ~128-bit scalar multiplication (msm([x²], [P])) plus one Fp multiply and a coordinate comparison — much cheaper in-circuit than cofactor clearing or a full λ-multiplication.
  • Enforced where untrusted points enter, for both the openvm (build_intrinsic_point) and halo2curves (build_point) constructors (witness.rs). build_point is on the in-circuit V7 path (BatchInfo::fromBatchInfoBuilderV7::build), so an off-subgroup point causes the builder to fail and no valid proof can be produced.
  • A #[cfg(feature = "host")] assertion cross-checks the result against halo2curves' independent is_torsion_free() during host-side witness generation.

Constants (openvm.rs):

  • BETA — nontrivial cube root of unity in Fp (the root for which φ acts as [-x²] on G1).
  • X_SQUARE, where x = -0xd201000000010000 is the BLS seed (BLS_X).

Tests

  • test_betaBETA ≠ 1, BETA³ = 1, BETA² + BETA + 1 = 0 (mod p).
  • test_x_squareX_SQUARE == BLS_X² (mod r).
  • test_g1_generator_is_in_subgroup — positive case: the G1 generator is accepted. (Guards against picking the wrong cube root, which would still satisfy test_beta.)
  • test_point_on_curve_but_not_in_subgroup — negative case: a random on-curve, non-torsion-free point is rejected, cross-checked against is_torsion_free().

cargo test -p scroll-zkvm-types-batch passes with and without --features host.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants