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).
43 lines
3.3 KiB
Markdown
43 lines
3.3 KiB
Markdown
Status: done
|
||
|
||
# 10 — FRAUD: Penalty calibration wiring (forfeit + strike + ban)
|
||
|
||
## What to build
|
||
|
||
End-to-end wiring: confirmed audit failure → atomic pending forfeiture + strike + reputation decay + audit-rate snap to max. Ensure payout cannot race penalty (ADR-0015). Document 19× deterrence math in validator README.
|
||
|
||
**Code refs:**
|
||
|
||
- `packages/validator/meshnet_validator/__init__.py` — `_slash_route` (~102–134)
|
||
- `packages/tracker/meshnet_tracker/server.py` — `_handle_billing_forfeit` (~2429–2464)
|
||
- `packages/tracker/meshnet_tracker/billing.py` — `forfeit_pending` (~280–292), payout exclusion for banned (~3337–3344 in settlement loop)
|
||
- `packages/validator/README.md` — update 20× → 19× at p=0.05
|
||
|
||
Per ADR-0018: **full pending forfeiture** is primary penalty; ×0.8 is routing decay per strike, not partial forfeit.
|
||
|
||
## Test-first
|
||
|
||
1. Red: integration from issue 34 — extend with multi-hop blame wallet from issue 07.
|
||
2. Green: node with pending balance → audit fail → pending zero, strike++, banned on 3rd, excluded from next settlement.
|
||
3. Settlement loop skips banned wallets (~3337–3344).
|
||
|
||
## Acceptance criteria
|
||
|
||
- [x] Audit failure triggers forfeiture + strike in one tracker transaction — `ValidatorProcess._slash_node` (in-process) and the tracker's `_handle_billing_forfeit` handler (remote) both forfeit-then-strike synchronously in a single call path; each already existed pre-AH-010 and is exercised by `tests/test_forfeiture_penalty.py`
|
||
- [x] Banned nodes excluded from `payables` / settlement — `BillingLedger.settle_node_payout` now clamps to the wallet's *current* pending balance under the same lock as the debit, and `_settlement_loop` rechecks ban status and uses the post-clamp amount before sending, so a forfeiture landing between the `payables()` snapshot and the actual payout can never be paid out on top of (ADR-0015 race); covered by `test_60_request_stream_bans_intermittent_first_hop_cheater_not_last_hop`
|
||
- [x] Validator uses authenticated forfeit endpoint (issue 02) — `POST /v1/billing/forfeit` is validator-token/admin-gated (ADR-0017 §4, issue 20) and is the documented remote path (`packages/validator/README.md` Usage section); `test_forfeit_endpoint_requires_auth_and_forfeits` exercises the 401→200 flow. No standalone remote-validator process exists in this codebase yet (`contracts` has no networked implementation), so the in-process `ValidatorProcess` continues to call `BillingLedger.forfeit_pending` directly when co-located with the tracker — adding an HTTP-only forfeit client with no real consumer was judged out of scope/overengineering for this issue
|
||
- [x] README: `L > 19× g` at p=0.05; pending balance = collateral — already present in `packages/validator/README.md` ("Why the penalty deters cheating")
|
||
- [x] Integration test: 60-request fraud scenario → ban within threshold — `tests/test_forfeiture_penalty.py::test_60_request_stream_bans_intermittent_first_hop_cheater_not_last_hop`
|
||
|
||
## ADR links
|
||
|
||
- [ADR-0018](../../docs/adr/0018-fraud-detection-verification-and-reputation.md)
|
||
- [ADR-0015](../../docs/adr/0015-usdt-custodial-settlement.md)
|
||
- Research: [research-verifiable-inference.md](../research-verifiable-inference.md) §1.1
|
||
|
||
## Blocked by
|
||
|
||
- `07-fraud-commitment-bisection-blame.md`
|
||
- `08-fraud-reputation-model-persistence.md`
|
||
- `02-a2-unified-auth-boundary.md`
|