Conversation
5dc7e70 to
047a8f1
Compare
65bf209 to
05b0f8c
Compare
For an odd mapping f (f(-u) = -f u) into a finite abelian group of odd order, prove the value multiplicity is negation-symmetric (IsOdd.mult_neg) and that for every nontrivial character ψ, ∑ u, ψ (f u) = ∑ Q, (mult f Q - 1) · ψ Q (charSum_eq) resting only on group orthogonality (AddChar.sum_eq_zero_of_ne_one). So the character sum depends only on how often f hits each group element, not on which of ±P a given input lands on: the y-sign convention of simplified-SWU-style mappings cancels exactly, and the one quantity left needing a Weil bound is the deviation of those counts from covering each element once. Also IsOdd.map_zero (an odd mapping into an odd-order group fixes 0), the odd-order doubling-injectivity fact via Mathlib's addOrderOf API. "Mapping" is RFC 9380's term for these functions; the naming survey records why it is preferred over the papers' "encoding". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tedness Add CompElliptic/Hashing/WellDistributed.lean. `WeilBounded f C` states the Weil bound in squared, exact-arithmetic form (‖∑ u, ψ (f u)‖² ≤ C²·#F, avoiding Real.sqrt), and `WeilBounded.deviation` restates it through `charSum_eq` as a bound on the covering-multiplicity deviation. The module docstring records why this bound cannot be reduced to the target curve's order: it is Hasse–Weil for the (genus-8) covering curve, not for E; it must hold uniformly over ~#G character twists rather than as one point count; and the prime-order-witness-plus-fibre-bound method that pins #E is special to near-prime-order elliptic curves and does not transfer to a genus-8 curve. So the Weil bound (Riemann hypothesis for curves) is the sole external input; everything upstream is the orthogonality-only reduction of CharacterSum. Register both Hashing modules in the root aggregator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a References block to WellDistributed.lean: Weil 1948 for the Riemann hypothesis for curves, and Farashahi–Fouque–Shparlinski–Tibouchi–Voloch (eprint 2010/539; Math. Comp. 82 (2013)) for the character-sum form intended to discharge `WeilBounded` (their Lemma 1), its covering-morphism workhorse (Theorem 3), and the simplified-SWU instantiation (Theorem 6, with its field-size ≡ 3 (mod 4) hypothesis noted). Point CharacterSum.lean's mention of the bound at that block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add TwoTermUniformity.lean, the payoff of the WeilBounded hypothesis: the
two-term hash output distribution (pairCount) is close to uniform. The
chain mirrors the DFT pipeline — dual-group orthogonality via the
double-dual embedding (Pontryagin duality supplies the dual's size), the
Fourier expansion of the pair count (a self-convolution squares the
spectrum), Parseval (the exact second moment, consuming no Weil bound),
then the deviation bounds: the summed squared deviation from uniform is at
most #G·(#G − 1)·(C²·#F)², and by Cauchy–Schwarz the squared L¹ deviation
is at most (#G − 1)·C⁴/#F² in probability form, giving statistical
distance about C²/√q ≈ 2^{-116} at the deployed sizes. Register the module
in the root aggregator.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add SignedLift.lean, the generic layer behind the sign convention. IsSignFunction captures the one property the analysis uses (negation flips the label of every nonzero element); sgn0 on ZMod p is proved to be a sign function for odd p. signedLift selects between the two points over an even abscissa map by matching the root's sign to the input's, and signedLift_neg proves the lift odd for every nonzero input. The zero exception is made explicit rather than assumed away: the deployed mapping is not odd at 0 (oddness there would force a 2-torsion value on an odd-order curve), so zeroRepaired sends 0 to the identity, isOdd_zeroRepaired shows the repair is odd everywhere, and sum_apply_sub_of_eq_except gives the exact one-input cost of the repair to any character sum — the O(1) term of the paper analysis, as an identity. Register the module in the root aggregator. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Begin the deployed hash-to-curve mapping, mirrored from protocol spec §5.4.9.8 (which takes precedence over RFC 9380 by its own declaration). sqrtRatio divides, takes the Tonelli-Shanks square root when the ratio is a square, and otherwise a root of the ratio times a fixed nonsquare lam; the Bool reports which case occurred. Its three spec lemmas: the Bool is exactly squareness of the ratio; each branch returns a genuine root of its target — in particular the fallback default in the nonsquare branch is dead code, because a nonsquare times a nonsquare is a square (isSquare_mul_of_not_isSquare, via multiplicativity of the quadratic character). The spec permits an arbitrary root and an arbitrary nonsquare; fixing them is licensed by its output-independence note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SswuParams bundles the curve (with A·B ≠ 0), the mapping's nonsquare Z, the sqrt_ratio data (Tonelli–Shanks and the nonsquare lam), the precomputed θ with θ²·lam = Z, the sign function, and RFC 9380's criterion 4 on Z. mapXY computes the spec's thirteen steps verbatim with the spec's own intermediate names. onCurve_mapXY proves the output is always an affine curve point: the sign-matching step squares away; the square branch is the definition of U; in the nonsquare branch θ²·lam = Z reduces y2's factors to exactly Zuu³ and the SSWU identity Zuu³·U = g(x2num/xdiv)·xdiv³ closes the generic case, while criterion 4 makes the exceptional ta = 0 case unreachable there — the ratio is a square, so sqrt_ratio took the square branch. map packages the SWPoint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The generic half of the isogeny layer. ThreeIsogeny bundles the kernel abscissa, the normalizing scalar, and the codomain coefficients that Vélu's formulae dictate, and derives the affine rational maps from them, so a concrete instance only has to check that its published coefficients match the derivation. The on-curve proof reduces to one polynomial identity modulo the degree-3 division polynomial, discharged by linear_combination with a cofactor computed in Sage (the script is recorded next to the proof). Rational points never meet the kernel fibre because the kernel ordinate is irrational, and the map commutes with negation. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
IsoPasta.lean states each isogeny two ways. Pallas.iso and Vesta.iso are the Vélu derivations: the kernel abscissa and normalizing scalar recovered from the published coefficients, with obligations that are numeral checks. Both kernel ordinates satisfy y₀² = 5, so kernel irrationality is exactly five_not_isSquare. Pallas.iso_map and Vesta.iso_map are the specified maps. Their constants CP_1..CP_13 and CV_1..CV_13 quote the hex list of protocol spec §5.4.9.8 verbatim, which agrees with the decimal constants of hashtocurve.sage. iso_map_eq proves each map equal to its derivation, by one decide per coefficient assembled with linear_combination. The general ThreeIsogeny theorems therefore apply to the deployed constants, and onCurve_iso_map states the on-curve consequence directly. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
iso-Pallas has order PALLAS_SCALAR_CARD and iso-Vesta has order PALLAS_BASE_CARD, by the same witness routes as their targets: a prime-order witness point, its native_decide torsion certificate, and the elementary fibre bound. The witnesses are at x = 1 and x = 4. The one new ingredient is iso-Vesta's 2-torsion exclusion. Its curve cubic has a linear term, so the cube-residue argument does not apply, but none is needed: a y = 0 point of iso-Vesta would map to a y = 0 point of Vesta under the isogeny (ThreeIsogeny.no_y_zero_of_codomain), and Vesta has none. The census gains the two witness certificates and the two orders under +native, and the isogeny layer's headline general theorems under the standard-axioms tier. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Mirror Vesta's neg_five_not_isCube and no_onCurve_y_zero for the Pallas base field: a 2-torsion point needs y = 0, hence x³ = -5, and -5 is not a cube. As on the Vesta side, the cube-residue power is evaluated by reduce_mod_char and re-checked by the kernel. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Injectivity consumes no homomorphism property. An abscissa collision would make the second abscissa a rational root of a quadratic whose discriminant is the squared difference of the abscissas of the two kernel translates, and that is 16·y₀²·y₁² up to a square factor — so a collision exhibits the nonsquare y₀² as a square, contradicting kernel_irrational (abscissa_inj; the identity's cofactors are computed in Sage, script recorded next to the proof). Equal images over one abscissa force equal ordinates, because the alternative makes the image rational 2-torsion (map_injective). ThreeIsogeny.map packages the affine map as a function on curve points, and counting upgrades injectivity to bijectivity when the two groups have equal order (map_bijective). Pallas.iso_map_bijective and Vesta.iso_map_bijective instantiate this with the iso-curve orders; both join the census's native tier. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
map_zero: the identity's sentinel pair (0, 0) is not on the domain curve, so map takes its else branch. Also add Silverman to the references; Galbraith §25.1 notes that an isogeny is automatically a group homomorphism. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
chord_x_certificate and tangent_x_certificate prove the two polynomial identities behind map_add: the abscissa of the image of a sum agrees with the abscissa the codomain group law computes from the images. Both are single linear_combination calls. The statements use kernel-centred coordinates (and, for the chord, symmetric variables), which shrink the certificates enough to elaborate in under a minute; the module doc explains the coordinates and the vocabulary. The cofactors are computed by scripts/gen_velu_certificates.sage, which verifies the emitted identity by exact expansion before writing the Lean text. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Four lemmas in the certificate's centred-symmetric coordinates, with their cofactors lifted over the two line-substituted curve relations and psi3: - chord_psi3_bridge: the certificate's hp input. - chord_ns_semantics, chord_ws_semantics: the atom semantics, relating the certificate's polynomials to the true-coefficient quotients. - chord_final_correction: the correction tying the slope-free cleared target to the certificate's goal (the ws² gap vanishes identically). Each carries one dd saturation factor from the Vieta elimination and 2-powers from clearing. The layout lint is now comment-aware. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The doubling analogues of the chord set, in kernel-centred coordinates over the tangent-line curve membership (hT1), the tangency relation (hT2), and psi3: - tangent_psi3_bridge: the certificate's hp input. - tangent_k_semantics, tangent_t_semantics: the atom semantics for the numerator parts of the codomain doubling slope. - tangent_correction: the k² correction tying the slope-free cleared target to the certificate's goal (the t² gap vanishes identically). The tangency relation is linear in A, so the Vieta elimination is clean and no saturation factors appear. The support template is shared between the chord and tangent emissions. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
chord_x_compat and tangent_x_compat: the image of a sum's third point has exactly the abscissa the codomain group law computes from the images, for the chord and doubling branches. They live in the new Isogenies/Homomorphism.lean, which holds the homomorphism layer; the parameters are pinned by defining equations so the point-level layer can instantiate them against add's branches. Each proof derives the generated support lemmas' hypotheses from the curve and line facts, applies the certificate at semantic atoms, and finishes through a scaled slope-free key equation — with integral coefficients throughout, since ring cannot cancel 2-power numerals over a field of unknown characteristic. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
… hash_to_field `ThreeIsogeny.mapHashOutputsToCurve` maps two field elements -intended to be outputs of `hash_to_field`- to the isogeny's domain curve, adds there, and applies the isogeny once. This is the same optimization that the protocol specification and `hashtocurve.sage` use, justified by `iso_map` being a homomorphism, as noted in RFC 9380 section 6.6.3. `mapHashOutputsToCurve_eq` shows that this agrees with mapping each point across the isogeny and adding on the codomain, the order zcash-test-vectors and pasta_curves use. The RFC intentionally provides no name for the primitive provided by `mapHashOutputsToCurve` - it is cryptographically hazardous unless composed with `hash_to_field`, as the name reflects. We expose it with the aim (deferred to #25) of proving that it is concretely indifferentiable from a random oracle when composed with `hash_to_field` as a RO. `mapToCurve` keeps its name: RFC 9380's `map_to_curve` does map a single field element across the isogeny to the target curve. `Pallas`/`Vesta.mapHashOutputsToCurve` instantiate this primitive over `sswu.map`, with the hypothesis-free `mapHashOutputsToCurve_eq` via `iso_map_add`. The composed test fixtures are restated as `mapHashOutputsToCurve` pins. The census records the two equalities under `+native`, witnessed by the Tonelli-Shanks instances. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
sparse pass, ACK! can follow-up with a deeper analysis |
|
Deeper pass at I did not find a core implementation-correctness bug in the deployed SSWU/isogeny path, or a Lean/kernel soundness hole. The formulas and constants match the protocol and pinned I did find these scope/specification gaps:
The upstream So my scope verdict is: sound as deployed mapping plus conditional groundwork, but not yet an end-to-end proof of deployed random-oracle security. with the help of claude |
|
still can't believe it implemented this so well... |
Fable claimed that proving As the comments in For the assurance we need to justify that the hash-to-curve is well-distributed, we only need to know that we've correctly stated the Weil bound. That is something for which we can just check the relevant literature (and I will). |
can we document this somewhere? these kinds of techniques are useful to have in the backpocket and externalize. |
SSWUParams recorded the two Z criteria the on-curve proof consumes (Z nonsquare, criterion 1, and crit4), but not Z ≠ -1 (criterion 2) or irreducibility of g(X) - Z (criterion 3), so the record admitted instances that RFC 9380 does not (over GF(7), y² = x³ + x + 3 with Z = -1). Add crit2 and crit3 fields and discharge them for the deployed Pasta parameters. crit3 is stated as root-freeness of the cubic, which is equivalent to the RFC's irreducibility condition. It is discharged by a new lemma, Fields.cubic_no_root_of_resolvent_noncube: Cardano's method run backwards as a certificate. A square root s of the resolvent discriminant (27s² = 27q² + 4A³) together with a non-cube resolvent root w (2w = -q + s) rules out all roots of x³ + Ax + q at once, entirely within F. The per-curve s and w were computed in Sagemath; the arithmetic side conditions are checked by decide, and the non-cube certificates by one fast modular exponentiation each (not_exists_pow_eq_of_pow_ne_one, as for neg_five_not_isCube). Criteria 2 and 3 turn out to be patent-avoidance constraints, not mathematical requirements: they entered in draft 5 of the RFC (cfrg/draft-irtf-cfrg-hash-to-curve#172) to keep the mapping outside US patents 8,718,276 and 8,712,038 (Icart et al., expiring June 2030). The module documentation now records this provenance, which is why no proof consumes them. Addresses point 1 of the review at #19 (comment). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
SSWUParams recorded the two Z criteria the on-curve proof consumes (Z nonsquare, criterion 1, and crit4), but not Z ≠ -1 (criterion 2) or irreducibility of g(X) - Z (criterion 3), so the record admitted instances that RFC 9380 does not (over GF(7), y² = x³ + x + 3 with Z = -1). Add crit2 and crit3 fields and discharge them for the deployed Pasta parameters. crit3 is stated as root-freeness of the cubic, which is equivalent to the RFC's irreducibility condition. It is discharged by a new lemma, Fields.cubic_no_root_of_resolvent_noncube: Cardano's method run backwards as a certificate. A square root s of the resolvent discriminant (27s² = 27q² + 4A³) together with a non-cube resolvent root w (2w = -q + s) rules out all roots of x³ + Ax + q at once, entirely within F. The per-curve s and w were computed in Sagemath; the arithmetic side conditions are checked by decide, and the non-cube certificates by one fast modular exponentiation each (not_exists_pow_eq_of_pow_ne_one, as for neg_five_not_isCube). Criteria 2 and 3 turn out to be patent-avoidance constraints, not mathematical requirements: they entered in draft 5 of the RFC (cfrg/draft-irtf-cfrg-hash-to-curve#172) to keep the mapping outside US patents 8,718,276 and 8,712,038 (Icart et al., expiring June 2030). The module documentation now records this provenance, which is why no proof consumes them. Addresses point 1 of the review at #19 (comment). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ings The character-sum analysis works with the literally-odd zeroRepaired mapToCurve, but SignedLift priced the repair only generically — a lemma about mappings agreeing except at one input, never applied to the deployed mappings. Restate it as the repair's own cost: charSum_sub_zeroRepaired (the deployed and repaired character sums differ by exactly ψ (f 0) - 1), with norm_charSum_sub_zeroRepaired bounding the shift by 2 in norm. Both are instantiated at the deployed mapToCurve for each curve, which is the composition the analysis consumes. The census records the norm forms with the same native leaves as the isOdd theorems. Addresses the transport half of point 2 of the review at #19 (comment). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Three clarifications from review. Well-distributedness is one ingredient of indifferentiability from a random oracle — the efficient preimage simulator is tracked in issue #25, and hash_to_field stays abstract, modelled as a random oracle. The "routine but unwritten redo" note now says what it means: FFSTV's Theorem 6 covers fields ≡ 3 (mod 4) — that paper is explicit about its scope — while the Pasta base fields are ≡ 1 (mod 4), and the redo of the genus computation for the deployed generalized variant does not seem to be covered in the literature. That is separate from WeilBounded being an external input to the formalization. The ≈ 2^-116 statistical-distance figures now state their reliance on the WeilBounded hypothesis, which is established mathematics but enters the development as an unformalized input. Addresses point 3 and the documentation half of point 2 of the review at #19 (comment). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
Thanks — all three points led to changes. Point 1 is addressed in b718fac and its follow-ups: Digging into why the RFC has criteria 2 and 3 at all turned up something worth recording: they are patent-avoidance constraints, not mathematical requirements. They entered in draft 5 (cfrg/draft-irtf-cfrg-hash-to-curve#172) to keep the mapping outside US patents 8,718,276 and 8,712,038 (Icart et al., expiring June 2030). The original simplified SWU of Brier et al., and Wahby–Boneh's own Point 2: you were right that the zero-repaired-to-deployed transport was not composed — that lemma existed only generically. The deployed and repaired character sums differ by exactly Point 3: agreed, and reworded — statistical regularity is now described as an ingredient of indifferentiability, with the efficient preimage simulator tracked in #25. One boundary note: the Posted with the assistance of Claude Fable 5 |
868146a to
4cbb825
Compare
Split an overlong sentence in the PastaSSWU parameter summary, giving lam's provenance its own sentence. Break up the zero-exception paragraph in SignedLift, and fix a stale reference there: the repair-pricing lemma is now `charSum_sub_zeroRepaired`, but the module doc still named its predecessor `sum_apply_sub_of_eq_except`. Rewrap paragraphs in TwoTermUniformity, ThreeIsogeny, and Homomorphism. Add ``` fences around sage scripts in ThreeIsogeny. Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Regenerate CompElliptic/Isogenies/VeluCertificates.lean with scripts/gen_velu_certificates.sage and fail if it differs from the committed file, mirroring the field-file generators job. Sage is pinned to 10.9 from conda-forge — the version whose bundled Singular produced the committed cofactors — because lift output can differ between Singular versions even when both are valid. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
It's documented in |
The deployed "Simplified SWU" hash-to-curve mappings used by Zcash's$\mathsf{GroupHash}$ for Pallas and Vesta, mirrored from protocol spec §5.4.9.8 — and the groundwork for their analysis.
The distribution of such a mapping is controlled by its character sums, and this PR isolates which part of that analysis is elementary and which part rests on top of deeper number theory. ("Mapping" is RFC 9380's term for these functions;
design/naming-survey.mdrecords why it is preferred over the papers' "encoding".)Hashing/CharacterSum.lean— the elementary coreA mapping is odd when negating the input negates the output (
f (-u) = -f u). For any odd mapping into a finite abelian group of odd order, this module proves:f 0 = 0(IsOdd.map_zero); the value multiplicity is negation-symmetric (IsOdd.mult_neg); and for every nontrivial character,∑ u, ψ (f u) = ∑ Q, (mult f Q − 1) · ψ Q(charSum_eq). The only nontrivial input is orthogonality (AddChar.sum_eq_zero_of_ne_one). The point of the identity: the sign convention drops out of the character sum entirely, leaving the sign-free covering-multiplicity deviation as the one object needing a bound.Hashing/WellDistributed.lean— the deep input, quarantinedWeilBounded f Cstates the Weil bound in squared exact-arithmetic form (‖∑ u, ψ (f u)‖² ≤ C²·#F, avoidingReal.sqrt), andWeilBounded.deviationtransports it throughcharSum_eqto the multiplicity deviation. The module docstring records why this bound cannot be reduced to the target curve's order — it is Hasse–Weil for the mapping's genus-8 covering curve, needed uniformly over roughly#Gcharacter twists, and the prime-order-witness-plus-fibre-bound method ofCurveOrderis special to near-prime-order elliptic curves. Weil 1948 and Farashahi–Fouque–Shparlinski–Tibouchi–Voloch (eprint 2010/539) are cited for the forms intended to discharge it. FFSTV's Theorem 6 covers fields≡ 3 (mod 4). The redo of its genus computation for the deployed generalized variant (the Pasta fields are≡ 1 (mod 4)) does not seem to be covered in the literature.Hashing/TwoTermUniformity.lean— the payoff of theWeilBoundedhypothesispairCount f Qcounts the input pairs withf u₀ + f u₁ = Q— the two-term output distribution. The chain mirrors the pipeline of a Discrete Fourier Transform:sum_addChar_apply, by Pontryagin duality — evaluation at a point is itself a character of the character group);card_mul_pairCount— a self-convolution squares the spectrum);card_mul_sum_sq_pairCount— the exact second moment, consuming no Weil bound);WeilBounded: the summed squared deviation from uniform is at most#G·(#G − 1)·(C²·#F)²(sum_sq_dev_le). By Cauchy–Schwarz the squared L¹ probability deviation is then at most(#G − 1)·C⁴/#F²(sq_sum_abs_prob_dev_le) — statistical distance aboutC²/√q ≈ 2^{-116}at the deployed sizes, withC ≈ 52the constant expected from FFSTV.Hashing/SignedLift.lean— the sign convention, structurallysignedLiftis the shape of RFC 9380's "ifsgn0 u ≠ sgn0 y, sety = -y" step: select between the two points over an even abscissa by matching the root's sign to the input's.signedLift_negproves the lift odd at every nonzero input, requiring the root chooser to be even only up to sign, which is what the deployed algorithm satisfies (its nonsquare branch carries a bare factor ofu). The zero exception is explicit rather than assumed away: the deployed mapping is not odd atu = 0(oddness there would force 2-torsion on an odd-order curve),zeroRepaired/isOdd_zeroRepairedgive the literally-odd variant, andcharSum_sub_zeroRepairedprices the repair exactly: the character sums differ byψ (f 0) − 1, at most2in norm (norm_charSum_sub_zeroRepaired). That shift is the analysis'sO(1)term, as an identity.Hashing/SimplifiedSWU.lean— the deployed mapping, from the specsqrtRatiocomes with its three lemmas: theBoolcomponent is exactly squareness of the ratio; each branch returns a genuine root of its target; and the fallback default is a dead case, because a nonsquare times a nonsquare is a square (isSquare_mul_of_not_isSquare, via the quadratic character).SSWUParamsbundles the curve (withA·B ≠ 0), the nonsquareZ, the Tonelli–Shanks data, the nonsquarelam, the precomputedθwithθ²·lam = Z, the sign function, and RFC 9380's four criteria onZ; the on-curve proof consumes criteria 1 and 4.SSWUParams.mapXYis the spec's thirteen steps verbatim, with the spec's own intermediate names.onCurve_mapXYproves every output is an affine curve point: the sign-matching step squares away; the square branch is the definition ofU; and the nonsquare branch closes byθ²·lam = Ztogether with the SSWU identityZuu³·U = g(x2num/xdiv)·xdiv³. Criterion 4 makes the exceptionalta = 0case unreachable in that branch.Isogenies/ThreeIsogeny.lean— Vélu's formulae, symbolicallyThe deployed mapping reaches Pallas and Vesta through auxiliary curves, each 3-isogenous to its target, because simplified SWU needs
A ≠ 0and the Pasta curves haveA = 0. This module formalizes the method behind the specified isogeny maps, rather than checking their coefficients as two curve-sized literal identities.ThreeIsogenytakes a kernel abscissa and a normalizing scalar, and derives the rational maps and the codomain from Vélu's formulae — the method by which Sage'srational_maps()produced the maps that the specification adopted. The on-curve proof is a single polynomial identity modulo the degree-3 division polynomial, discharged bylinear_combinationwith a cofactor computed in Sage (the script is recorded next to the proof). Rational points never meet the kernel fibre, because the kernel ordinate is irrational; and the map commutes with negation, which the analysis will consume as oddness. Cited: Vélu (1971), and Galbraith's "Mathematics of Public Key Cryptography", Theorem 25.1.6.Curves/IsoPasta.lean— the derived and specified isogeniesEach deployed isogeny is stated twice —as derived using Vélu's formulae, and as the explicit mapping given in the protocol specification— and the statements proved equal.
Pallas.isoandVesta.isoare the Vélu derivations: the kernel abscissax₀ = -b₁/2and the scalars, recovered from the specified coefficients, with every obligation a numeral check — and both kernel ordinates satisfyy₀² = 5, so kernel irrationality is exactlyfive_not_isSquare.Pallas.iso_mapandVesta.iso_mapquote the protocol specification's hex constants verbatim, asCP_1, ..., CP_13andCV_1, ..., CV_13—checked against the decimal constants ofhashtocurve.sage— andiso_map_eqproves each equal to its derivation (onedecideper coefficient, assembled bylinear_combination).onCurve_iso_mapis the payoff: points of the iso-curves land on their targets.Curves/PastaOrder.lean— the iso-curve ordersiso-Pallas and iso-Vesta have the same orders as their targets, pinned by the same witness route: a prime-order witness point (at
x = 1andx = 4), itsnative_decidetorsion certificate, and the elementary fibre bound. The one new ingredient is iso-Vesta's 2-torsion exclusion: its curve cubic has a linear term, so Vesta's cube-residue argument does not apply — and none is needed, because ay = 0point of iso-Vesta would map to ay = 0point of Vesta under the isogeny (ThreeIsogeny.no_y_zero_of_codomain), and Vesta has none. The census gains the two certificates and the two orders under+native, and the isogeny layer's headline theorems under the standard tier.Isogenies/ThreeIsogeny.lean, continued — bijectivity on rational points, by countingInjectivity consumes no homomorphism property: an abscissa collision would make the second abscissa a rational root of a quadratic whose discriminant is the squared difference of the abscissas of the two kernel translates —
16·y₀²·y₁²up to a square factor — so a collision exhibits the nonsquarey₀²as a square, contradictingkernel_irrational(abscissa_inj, with Sage-computed cofactors recorded next to the proof). Equal images over one abscissa force equal ordinates, because the alternative makes the image rational 2-torsion (map_injective; the codomain-side exclusion for Pallas is the newPallas.no_onCurve_y_zero, mirroring Vesta's).ThreeIsogeny.mappackages the affine map as a function on curve points, and counting upgrades injectivity to bijectivity when the two groups have equal order (map_bijective);Pallas.iso_map_bijectiveandVesta.iso_map_bijectiveinstantiate this with the iso-curve orders.Isogenies/VeluCertificates.lean— the homomorphism identities, as certificatesThe homomorphism property of the isogeny reduces to two polynomial identities: the abscissa of the image of a sum agrees with the abscissa the codomain group law computes from the images, once for the chord case (distinct abscissas) and once for the tangent case (doubling). This module proves both, each as a single
linear_combinationcertificate, generic over any commutative ring. The statements are phrased in kernel-centred coordinates —the translation putting the kernel abscissa at the origin, under which Vélu's numerators are short and the division-polynomial relation collapses to the two-termp² = 12·x₀·g₀— and, for the chord, in symmetric variables for the two summands. Together these shrink the chord certificate roughly sevenfold, which is the difference between an infeasible elaboration and one that finishes in under a minute. The module doc explains the coordinates and defines the working vocabulary (certificate, cofactor, atom, mass). The cofactors are computed byscripts/gen_velu_certificates.sage, which re-verifies the emitted identity by exact polynomial expansion before writing the Lean text, and Lean'sringnormalization re-checks the same identity on every build — so no Gröbner-basis output is trusted. CI also re-runs the generator and fails if the regenerated file differs from the committed one, with Sage pinned to the version whose bundled Singular produced the committed cofactors (liftoutput can differ between versions even when both are valid).ThreeIsogeny.map_zero(the identity maps to the identity) lands alongside, with references for the standard fact that an isogeny is automatically a group homomorphism (Galbraith §25.1; Silverman, Theorem III.4.8). The generated section also carries the support lemmas the wrapper proofs consume: the ψ₃ instances, the atom semantics, and the final corrections, in the same coordinates, each verified the same way.Isogenies/Homomorphism.lean— the homomorphism property, provedThreeIsogeny.mapis a group homomorphism on rational points (map_add). That an isogeny is automatically a group homomorphism is standard (Galbraith §25.1; Silverman, Theorem III.4.8), but Mathlib has no isogeny theory to supply it, and this development does not rely on the general theorem: the property is proved directly for the maps in use. The proof is layered.chord_x_compatandtangent_x_compatconsume the certificates through the generated support lemmas —with the Vieta eliminations' saturation factors and the 2-power clearings cancelled in the wrappers— and say that the image of a sum's third point has exactly the abscissa the codomain group law computes from the two image points. The point level assembles the branches ofadd(map_add_x), upgrades abscissa agreement to agreement up to sign (map_add_pm; on-curve points sharing an abscissa are equal or negatives), and resolves the sign by group algebra: the ambiguous cases force 2-torsion on the codomain, which the existing no-y = 0hypothesis excludes.Pallas.iso_map_addandVesta.iso_map_addinstantiate it with every hypothesis discharged by the 2-torsion exclusions, so the homomorphism facts sit in the census's standard tier, consuming nonative_decide.Fields/Sqrt.lean— a validrootOfUnityis a nonsquareTonelliShanks.rootOfUnity_not_isSquare: the root of unity of a valid instance has full 2-power order, so its Euler power factors as(rootOfUnity^(2^(twoAdicity-1)))^oddPart = (-1)^oddPart = -1, whereas Euler's criterion gives1for a nonzero square. This discharges the nonsquare obligation of any deployment that reusesrootOfUnityas an auxiliary nonsquare —as the deployed parameters below do— with no per-field computation.Hashing/PastaSSWU.lean— the deployed parametersPallas.sswuandVesta.sswuinstantiateSSWUParamswith the deployed parameters:Z = -13, paritysgn0, and the square-root split overlam := rootOfUnity, matchingpasta_curves'ROOT_OF_UNITYso that intermediate values can be compared directly. Theθvalues are quoted frompasta_curves'THETAconstants (revision-pinned in the module doc);θ_specpins each to±THETA, anddecide-checkedexamples equate the hex literals to the reference's little-endianfrom_rawlimbs, verbatim. The criterion-4 obligations are discharged by computed square-root witnesses, with the divisions cleared byfield_simpbeforedecide(modular inversion under kernel evaluation is infeasible, while the division-free identities elaborate in a few hundred heartbeats).Hashing/PastaSSWU.lean— pinned test fixturesSixteen
native_decidefixtures pin the instances against the references. Per field,mapXYis pinned athashtocurve.sage's self-test inputs (u = 0exercises the exceptionalta = 0branch) and at the twohash_to_fieldoutputs of its hash-to-curve test vector, which take oppositeIsSquarebranches. The composed construction (mapHashOutputsToCurve) is pinned against thezcash-test-vectorsgroup-hash vector for Pallas; againsthashtocurve.sage's Vesta vector, whose shape is what azcash-test-vectorsVesta vector is expected to take (zcash/zcash-test-vectors#132); and against the Halo 2 fixed-generator derivation for Vesta, at indices0and2^11 - 1plusWandU. One further example checks the Vesta vector's Jacobian-to-affine conversion, with the script's printed output quoted verbatim, so the pinned point can be compared directly against it. Filed alongside: zcash/pasta#6 and zcash/zips#1349 for small reference bugs surfaced by this work, and #24 to track a direct comparison against the Rustpasta_curvesimplementation.Hashing/SignedLift.leanandHashing/SimplifiedSWU.lean, continued — the mapping is oddsignedLiftnow takes a candidate point mapF → SWPoint Eand re-derives each output's sign from the input's, so validity rides insideSWPointand oddness needs a single hypothesis:signedLift_negconsumesm (-u) = ±(m u). On the SSWU side,mapXYis split intomapXYUpToSign—the spec's steps up to the candidate ordinate, written once— and the sign-matching step, so their composition is step-for-step the spec's list.candidateMappackages the candidate as a curve point (valid_pre),map_eq_signedLiftfactors the mapping throughsignedLift, andmap_neggives oddness away from0; the zero exception is exactly the onezeroRepairedprices.Hashing/PastaSSWU.lean, continued — the composedmap_to_curvemapToCurve—simplified SWU, then the isogeny— is the deployedmap_to_curvefor each curve.mapToCurve_negcomposesSSWUParams.map_negwithThreeIsogeny.map_neg, andisOdd_zeroRepaired_mapToCurveis the literally-odd form the character-sum analysis consumes.charSum_mapToCurve_sub_zeroRepairedand its norm form instantiate the repair pricing at the deployed mapping, so conclusions about the repaired variant carry back at an exactO(1)cost. The census records theisOddand transport theorems under+native, witnessed by the Tonelli–Shanks instances — their only native leaves.mapHashOutputsToCurveis the deployed construction afterhash_to_field: add on the iso-curve, apply the isogeny once, as the spec andhashtocurve.sagedo. The name is deliberately nothash_to_curve— RFC 9380's includeshash_to_field, and the RFC intentionally leaves this composition unnamed, since it is cryptographically hazardous unless composed withhash_to_field. RFC 9380 §6.6.3 licenses the one-evaluation order by exactly the homomorphism this PR proves;mapHashOutputsToCurve_eqconsumesmap_add/iso_map_addto agree with the per-point order thatzcash-test-vectorsandpasta_curvesuse, and the composed fixtures pinmapHashOutputsToCurveitself.Hashing/SimplifiedSWU.leanandFields/Residue.lean, continued — all four RFC criteria certifiedSSWUParamsinitially recorded only the twoZcriteria the on-curve proof consumes, so it admitted instances that RFC 9380 does not (overGF(7),y² = x³ + x + 3withZ = -1). The record now carries all four:crit2(Z ≠ -1) andcrit3(g(X) - Zhas no roots, which for a cubic is the RFC's irreducibility condition).crit3is discharged by a new lemma,cubic_no_root_of_resolvent_noncube: Cardano's method run backwards as a certificate — a square rootsof the resolvent discriminant together with a non-cube resolvent rootwrules out all roots ofx³ + A·x + qat once, entirely withinF. The per-curvesandwwere computed in Sagemath; the arithmetic side conditions are checked bydecide, and the non-cube certificates by one fast modular exponentiation each (not_exists_pow_eq_of_pow_ne_one). Criteria 2 and 3 turn out to be patent-avoidance constraints rather than mathematical requirements — they entered in draft 5 of the RFC to keep the mapping outside US patents 8,718,276 and 8,712,038 (Icart et al., expiring June 2030) — and theSimplifiedSWUmodule documentation now records that provenance, which is why no proof consumes them.Deferred
hash_to_field(·, 2)(Brier et al.'s Theorem 1 with its explicit simulator), consumingTwoTermUniformityas the regularity half, is tracked as Justify indifferentiability ofmapHashOutputsToCurvefrom an RO wrt thehash_to_fieldoutputs #25.🤖 Claude Fable 5