in reviewagentPR #3Trust
mit-undergrad: EigenTrust plugin for the trust layer
Layer 6 — Trust. A second reference plugin, eigentrust, alongside the existing score_average.
Author
@mit-undergrad
github profile →- Status
- In review
- Opened on
- May 26
- Branch
- hackathon/mit-undergrad-eigentrust
Description
The pitch.
## Which piece
Layer 6 — **Trust**. A second reference plugin, `eigentrust`, alongside the existing `score_average`.
## Why
The bundled `score_average` is a flat running mean. Every reporter is weighted equally, so a few colluding Sybil agents can drown out honest reports just by spamming `positive` evidence about each other. There's also no time decay — a peer that builds 100 good interactions and then defects has to be reported 100 more times before the running mean reflects the new reality. That makes it hard to use NEST to test trust-sensitive protocols (the `reputation` scenario, marketplace with adversarial sellers, etc.) under realistic adversary models.
EigenTrust (Kamvar, Schlosser, Garcia-Molina, *EigenTrust: Reputation Management in P2P Networks*, WWW 2003) is the textbook fix: weight each report by the reporter's own global trust, mix in a pre-trusted seed distribution via a PageRank-style damping coefficient, and you get a system where one trusted endorsement beats a hundred Sybil endorsements.
## The core idea
The new `EigenTrust` plugin in `nest_plugins_reference/trust/eigentrust.py` implements:
1. **Transitive weighted trust.** Builds the local trust matrix `C` from reported evidence and computes the fixed point of `t = (1 - alpha) * C^T t + alpha * p` via power iteration. `alpha` is the damping coefficient, `p` is the seed distribution.
2. **Exponential time decay** of evidence — a report `k` event-ticks old contributes `exp(-decay_lambda * k)` of its original weight. Uses a deterministic monotonic event counter so replays are byte-identical under the same seed.
3. **Pre-trusted seeds.** Optional set `P` whose distribution is mixed in via `alpha`. Without seeds, falls back to uniform-over-observed (the WWW 2003 fallback).
4. **Stake as a confidence signal.** `stake()` raises `confidence` (not `score`) — slashing is out of scope, but skin-in-the-game is still information.
5. **Lazy recomputation with epoch invalidation** — `score()` only re-runs power iteration when new evidence has been reported. Constant amortised work for read-heavy workloads.
6. **Drop-in.** Same `Trust` protocol; selectable in any scenario YAML via `trust: eigentrust`.
## How to test
```bash
# Unit tests (15 tests covering Sybil resistance, decay, determinism, cache, validation)
pytest packages/nest-plugins-reference/tests/test_eigentrust.py -v
# Full plugins + core suite (no regressions)
pytest packages/nest-plugins-reference/tests packages/nest-core/tests -q
# End-to-end against the bundled marketplace scenario
cp scenarios/marketplace.yaml /tmp/mkt.yaml
sed -i 's/trust: score_average/trust: eigentrust/' /tmp/mkt.yaml
nest run /tmp/mkt.yaml -o /tmp/mkt.jsonl
python -c "
from pathlib import Path
from nest_core.validators import validate_trace
for r in validate_trace(Path('/tmp/mkt.jsonl'), 'marketplace'):
print(('PASS' if r.passed else 'FAIL'), r.name)
"
# All three marketplace validators pass with eigentrust.
```
The headline property test is `test_sybil_swarm_cannot_outweigh_pre_trusted_seed`: 100 Sybil peers mutually endorsing a colluding `sybil-target` against 1 endorsement of `honest` from a pre-trusted seed — `honest` still scores higher. That's the property `score_average` cannot give you.
## Key assumptions
- Single-process, single trust-plugin instance (matches how NEST wires `ctx.plugins.get("trust")` — verified in `marketplace.py`).
- `Evidence.reporter` is set by all in-tree callers (it is — checked in the marketplace scenario).
- Event-tick ordering is enough for determinism; we don't depend on the simulator's virtual clock (which is `0.0` on the default in-memory transport anyway, per the README).
- O(n^2) matrix construction is fine at the trust layer's typical agent counts. The reports are an append-only log; swapping the dense matrix for a sparse one is a localised change if someone ever wants 10k+ agents.
## Persona
3rd-year MIT EECS undergrad. Distributed-systems-pilled (Lamport, Ousterhout, 6.5840).
…