Skip to Content
ProtocolCryptographic Primitives

Cryptographic Primitives

BN254 Curve

Lateo uses the BN254 (alt-bn128) elliptic curve — the same curve used by Ethereum’s EIP-196/EIP-197 precompiles. Stellar Protocol 25 provides native host functions for BN254 operations.

ParameterValue
CurveBN254 (alt-bn128)
Base field (Fp)21888242871839275222246405745257275088696311157297823662689037894645226208583
Scalar field (Fr)21888242871839275222246405745257275088548364400416034343698204186575808495617
Security level~100 bits
Embedding degree12

Poseidon2

Poseidon2 is a ZK-friendly hash function optimized for arithmetic circuits. It operates natively over the BN254 scalar field.

Lateo uses Poseidon2 with domain separators to prevent cross-domain attacks:

DomainSeparatorConstruction
Commitment0x01Poseidon2(amount, pubKey, blinding, 0x01)
Nullifier0x02Poseidon2(commitment, pathIndices, privKey, 0x02)
Public key derivation0x03Poseidon2(privKey, 0x03)
Signature0x04Poseidon2(commitment, privKey, 0x04)
Merkle tree internal nodesN/APoseidon2(left, right)

The domain separator is appended as an additional input to the hash. This ensures that a valid commitment hash cannot be reused as a nullifier or vice versa.

Groth16 Proving System

Groth16 provides succinct non-interactive zero-knowledge proofs with:

PropertyValue
Proof size256 bytes (constant)
Verification time~3ms (BN254 pairing)
Prover time8-15 seconds (WASM, single core)
Trusted setupRequired (circuit-specific)
SoundnessComputational (discrete log assumption)
Zero-knowledgePerfect (statistical)

Proof structure

A Groth16 proof consists of three elliptic curve points:

A ∈ G1 (64 bytes, Y-coordinate negated for verification) B ∈ G2 (128 bytes, two Fp2 elements) C ∈ G1 (64 bytes)

Verification equation

e(A, B) = e(α, β) · e(Σ aᵢ·ICᵢ, γ) · e(C, δ)

Where α, β, γ, δ are from the trusted setup and ICᵢ are the verification key’s IC points. This is computed on-chain using bn254_pairing_check.

Key Derivation

Agent BN254 private keys are derived deterministically:

privKey = SHA256(agentId || serverEncryptionKey) mod BN254_FR pubKey = Poseidon2(privKey, 0x03)

This ensures keys are reproducible from the agent ID without storing the raw private key.

Note Encryption

Output notes are encrypted with X25519 (Curve25519 Diffie-Hellman) so only the intended recipient can decrypt them:

encryptedOutput = X25519_Encrypt(recipientEncPubKey, noteData)

The encrypted outputs are stored on-chain in the NewCommitmentEvent — allowing future client-side note scanning.

Last updated on