alea_verifier/instructions/map_to_point_debug.rs
1//! T1.04 — BPF-vs-native `map_to_point` parity debug instruction.
2//!
3//! Takes 32 bytes of field-element input (big-endian representation
4//! of `u ∈ Fq`) and returns 64 bytes (`x || y`, both BE) = the output
5//! of `map_to_point(u)`. Fires `AleaError::NoSquareRoot` (6004) if all
6//! three SVDW candidates fail (matches production `hash_to_g1`'s
7//! propagation path).
8//!
9//! SECURITY POSTURE (see `instructions/mod.rs` for full rationale):
10//! stateless pure function, no authority check, no state mutation,
11//! computation freely available off-chain via gnark-crypto. This
12//! instruction is INTENTIONALLY always-present in the shipped binary
13//! — not feature-gated — because Anchor 0.30.1's `#[program]` macro
14//! emits client-account bindings that don't respect `cfg` on a single
15//! inner function, and carrying the instruction as always-on with zero
16//! attack surface is cleaner than maintaining two parallel `#[program]`
17//! modules. The `mod.rs` SECURITY POSTURE block documents the full
18//! risk analysis.
19//!
20//! Test harness (`tests/map-to-point-diff.ts`) calls this with the
21//! gnark-crypto-verified `u0_hex`/`u1_hex` values from the existing
22//! round-1 / round-9337227 fixtures and asserts byte-equality with
23//! the expected `Q0_x_hex`/`Q0_y_hex`/`Q1_x_hex`/`Q1_y_hex` outputs.
24//! 8 direct BPF-vs-gnark byte-equality assertions — closes T1.04
25//! (AUDIT-REPORT-R5.md §T1.04).
26
27use anchor_lang::prelude::*;
28
29use crate::crypto::svdw::{fq_from_be_bytes, map_to_point};
30use crate::errors::AleaError;
31
32/// Accounts struct for the debug instruction. Stateless — only needs a
33/// signer for tx fees; no PDAs, no config, no side effects.
34#[derive(Accounts)]
35pub struct MapToPointDebug<'info> {
36 /// Signer pays fees. No authorization required — the instruction is
37 /// a stateless pure function (see module-level SECURITY POSTURE for
38 /// full rationale). Codex-D POST-T3.01: prior comment here incorrectly
39 /// said "compile-time gated by `diff-test` feature"; that design was
40 /// abandoned due to Anchor 0.30.1's #[program] cfg limitation (see
41 /// instructions/mod.rs). The instruction is intentionally always-
42 /// present with documented zero attack surface.
43 pub payer: Signer<'info>,
44}
45
46/// Invoke `map_to_point(u)` on BPF and return the 64-byte result.
47///
48/// Input: 32 bytes = `u.into_bigint()` big-endian.
49/// Output: 64 bytes = `x || y` big-endian.
50/// Failure: `AleaError::NoSquareRoot` (6004) if SVDW theorem violation
51/// (all three x candidates fail try_sqrt_curve — should not occur for
52/// honest inputs per the theorem; surfaces a syscall oracle regression).
53pub fn map_to_point_debug_handler(
54 _ctx: Context<MapToPointDebug>,
55 u_bytes: [u8; 32],
56) -> Result<[u8; 64]> {
57 let u = fq_from_be_bytes(&u_bytes);
58 let result = map_to_point(&u).ok_or(AleaError::NoSquareRoot)?;
59 Ok(result)
60}