# meshnet-validator Optimistic fraud detection (ADR-0003, penalty amended by ADR-0015): the validator re-runs a random ~5% sample of completed inference requests against a trusted reference node. Audit-capable events are checked by teacher-forcing the claimed token sequence through the reference node and verifying the claimed TOPLOC activation proof. Legacy events without TOPLOC metadata still fall back to text comparison until node-side proof capture lands. ## Why the penalty deters cheating There is no upfront stake. Settlement is periodic (US-033), so a node always has an unpaid **pending balance** — that balance *is* the collateral. At a sampling rate `p`, a cheater who gains `G` per fraudulent job and loses `L` when caught has expected value: ``` (1 - p) * G - p * L < 0 L > ((1 - p) / p) * G # p = 0.05 -> L > 19 x G ``` With the production settlement period of 24h, the pending balance at any moment approximates a full day's earnings — hundreds to thousands of jobs — which is far above the 19× bar. Each catch also records a strike; three strikes ban the wallet (registration rejected, excluded from routes, unpaid pending never settled), and the probationary period (first N jobs unpaid) makes re-entry with a fresh wallet costly. ## TOPLOC audit contract The validator expects audit-capable events to carry: - `claimed_token_ids`: the final token sequence claimed by the prover. - `toploc_proof`: compact TOPLOC proof data built from prover activations. On audit the validator calls the reference node's `POST /v1/audit/toploc` endpoint with the original messages plus `claimed_token_ids`. The reference node must run a teacher-forced prefill over exactly that token sequence and return the activations for TOPLOC verification. It must not free-generate a second answer for audit. Canonical audit parameters for the current alpha preset are: ``` dtype = "bfloat16" quantization = "bfloat16" decode_batching_size = 32 topk = 8 skip_prefill = true encoding = "base64" ``` Production audit thresholds remain gated on the honest-noise calibration corpus in issue 21. Two operational notes: - Shortening the settlement period shrinks the collateral. Period changes must weigh chain overhead against deterrence. - A cheater immediately after a payout has little to forfeit — the strike/ban ladder covers that window. ## Usage ```python ValidatorProcess( contracts=contracts, # registry/validation boundary billing=ledger, # BillingLedger — enables forfeiture reference_node_url="http://...", sample_rate=0.05, ) ``` Remote validators can instead call the tracker's privileged `POST /v1/billing/forfeit` endpoint (non-empty Authorization header). ## Reputation-weighted audit rate (ADR-0018 §1, §6-7) `sample_rate` is a flat coin flip: every wallet audited at the same rate. Pass `audit_sampler=AdaptiveAuditSampler(...)` instead to make the audit probability a function of each wallet's tenure and reputation — newcomers and low-reputation wallets sampled at 20–30%, veterans in good standing floor at ≥2% — while a running budget balance keeps the fleet-wide realized rate anchored to `AuditRateConfig.target_rate` (default 5%) regardless of the wallet mix. Passive tripwires (`detect_output_tripwire`) bump only that one request's odds; they never strike, ban, or affect other wallets' rates. ```python from meshnet_validator import AdaptiveAuditSampler, detect_output_tripwire ValidatorProcess( contracts=contracts, reference_node_url="http://...", audit_sampler=AdaptiveAuditSampler(random_seed=42), ) ``` When `audit_sampler` is set, `sample_rate` is ignored — the sampler decides per event, keyed on whichever route wallet has the lowest reputation.