Complete the alpha-hardening Ralph task set, including tracker billing/accounting guards, validator fraud-audit primitives, wallet binding proof support, documentation runbooks, and updated tests. Verification: .venv/bin/python -m compileall -q packages tests; .venv/bin/python -m pytest -q --tb=short (313 passed, 3 skipped, 1 failed: tests/test_mining_cli.py::test_legacy_start_without_port_uses_next_available_port because meshnet-node pid 1263451 is already listening on port 7000).
101 lines
3.7 KiB
Markdown
101 lines
3.7 KiB
Markdown
# 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.
|