OPTXOPTX DOCS
AARON Protocol

Biometric Proof Registry

JOULE templates, knot-encoded gaze keys, and the biometric proof submission flow.

Each gaze verification session produces a JOULE template — a knot encoding of the user's AGT tensor sequence. The AARON protocol hashes this into a knot invariant and stores it on-chain.

JOULE Template

// JOULE Template — knot-encoded gaze key
interface JOULETemplate {
  timestamp: number;
  sessionNonce: string;
  expirationWindow: number;          // 30s default
  gazeSequence: GazeTensor[];        // ordered AGT tensor sequence
  holdDurations: number[];           // ms per position
  transitionVectors: number[][];     // gaze path between positions
  polynomialEncoding: string;        // proprietary knot encoding
  knotPolynomial: string;            // knot invariant identifier
  verificationHash: string;          // cryptographic proof hash
}

// Verification hash generation is proprietary.
// The hash binds the session nonce, gaze sequence, hold durations,
// and timestamp into a single 32-byte proof submitted on-chain.

Rust Reducers (SpacetimeDB)

The AARON registry runs as SpacetimeDB reducers on OPTX Validator Nodes. Biometric proofs are validated server-side before on-chain attestation.

Submit Biometric Proof

// AARON biometric proof — SpacetimeDB module (Rust)
use spacetimedb::spacetimedb;
use sha2::{Sha256, Digest};

#[spacetimedb(table)]
pub struct BiometricProof {
    #[primarykey]
    #[autoinc]
    pub id: u64,
    pub user_id: u64,
    pub polynomial_encoding: String,   // proprietary knot encoding
    pub knot_polynomial: String,       // knot invariant identifier
    pub verification_hash: String,     // cryptographic proof hash
    pub hold_durations_ms: Vec<u64>,
    pub confidence_mean: f64,
    pub verified: bool,
    pub created_at: u64,
}

#[spacetimedb(reducer)]
pub fn submit_biometric_proof(
    ctx: &ReducerContext,
    user_id: u64,
    polynomial: String,
    knot: String,
    hash: String,
    durations: Vec<u64>,
    confidence: f64,
) -> Result<(), String> {
    // Validate minimum confidence threshold
    if confidence < CONFIDENCE_THRESHOLD {
        return Err("Confidence below threshold".into());
    }

    BiometricProof::insert(BiometricProof {
        id: 0,
        user_id,
        polynomial_encoding: polynomial,
        knot_polynomial: knot,
        verification_hash: hash,
        hold_durations_ms: durations,
        confidence_mean: confidence,
        verified: false,
        created_at: ctx.timestamp.to_micros_since_epoch(),
    });

    log::info!("Biometric proof submitted for user {}", user_id);
    Ok(())
}

Verify Proof

#[spacetimedb(reducer)]
pub fn verify_proof(
    ctx: &ReducerContext,
    proof_id: u64,
    nonce: String,
    sequence: Vec<u8>,
    durations: Vec<u64>,
    timestamp: u64,
) -> Result<(), String> {
    let proof = BiometricProof::filter_by_id(&proof_id)
        .ok_or("Proof not found")?;

    // Server-side hash recomputation (proprietary)
    // Binds nonce + gaze sequence + durations + timestamp
    let computed = compute_verification_hash(&nonce, &sequence, &durations, timestamp);

    if computed != proof.verification_hash {
        return Err("Hash mismatch — proof invalid".into());
    }

    BiometricProof::update_by_id(&proof_id, |p| {
        p.verified = true;
    });

    log::info!("Proof {} verified for user {}", proof_id, proof.user_id);
    Ok(())
}

On this page