/** * quic-sender.ts — Transport adapter over @matrixai/quic 2.x * * Opens a QUIC connection with: * - ALPN = 'solana-tpu' (mandatory for Firedancer) * - Server cert pinning via verifyCallback (SPKI Ed25519 pubkey vs. leader identity) * - Client cert for stake-weighted QoS (user identity, PEM-encoded for @matrixai/quic) */ import { CryptoError } from '@matrixai/quic/native/types.js'; import type { Address } from '@solana/kit'; import type { TpuIdentity } from './identity.js'; import type { QuicConnection, PoolEntry } from './quic-pool.js'; import type { EventEmitter } from './events.js'; import type { TpuError } from './errors.js'; /** * Server-cert pin enforcement mode. * * - `'strict'` — reject the connection if the server cert SPKI does not match the * gossip-advertised identity pubkey. Only safe in fleets you know * present identity-signed certs (pure Agave, no LBs). * - `'observe'` — emit a `cert-pin-mismatch` TpuEvent on mismatch but accept the * connection. Default. Works against real mainnet in April 2026 * where Frankendancer presents per-connection certs (SPKI != * identity) and some Agave nodes sit behind load balancers. * - `'off'` — do not inspect server certs at all. * * Note: the client cert (your QoS identity) is ALWAYS presented on the QUIC * ClientHello regardless of pinMode, because validators use it for * stake-weighted QoS. `pinMode` only governs SERVER cert inspection. If you * need to suppress client-identity exposure, do not pass `identity` — use the * ephemeral default, which still presents a cert but with a throwaway keypair. */ export type PinMode = 'strict' | 'observe' | 'off'; export interface OpenArgs { /** Leader identity (base58 Address) — used for cert-pin check. */ identity: Address; /** "host:port" string for the TPU-QUIC endpoint. */ addr: string; /** Max number of concurrent streams on this connection. */ maxStreams: number; /** User's TpuIdentity (self-signed cert + keypair) for QoS. */ tpuIdentity: TpuIdentity; /** Event emitter for observability. */ emit: EventEmitter; /** Cert-pin enforcement mode. Default: 'observe'. */ pinMode?: PinMode; /** F14: tunable transport timeouts. Defaults: connectMs=5000, writeMs=2000, destroyMs=2000. */ timeouts?: { connectMs?: number; writeMs?: number; destroyMs?: number; }; } export declare function openTpuQuicConn(args: OpenArgs): Promise; export declare function sendOnce(entry: PoolEntry, txBytes: Uint8Array, signal: AbortSignal): Promise<{ rttMs: number; } | TpuError>; /** * Extract the raw 32-byte Ed25519 public key from a DER-encoded X.509 cert. * * Ed25519 SPKI (RFC 8410) is exactly 44 bytes: * 30 2a 30 05 06 03 2b 65 70 03 21 00 <32-byte pubkey> * * The last 32 bytes of the SPKI are the raw public key bytes. */ export declare function extractEd25519PubkeyFromCert(der: Uint8Array): Uint8Array; /** * Pure decision function for the TLS peer-cert check. Extracted so it can be * unit-tested without a live QUIC handshake. * * Returns `undefined` to accept the connection; returns a `CryptoError` to * reject. In `'observe'` mode a mismatch emits the `cert-pin-mismatch` event * for telemetry but still accepts, matching empirical mainnet behavior where * Frankendancer (and some Agave) validators present server certs whose SPKI * does not equal the gossip identity. */ export declare function evaluatePinDecision(args: { certs: Array; expectedPubkey: Uint8Array; identity: Address; pinMode: PinMode; emit: EventEmitter; }): CryptoError | undefined; //# sourceMappingURL=quic-sender.d.ts.map