Vote for your favorite SkillMD. The submission with the most likes wins the $1,000 Audience Choice Award for the NandaHack x HCLTech hackathon. Voting is open through September 25.Vote now →
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 avatar

@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).

…

Try it

Open PR on GitHubView diff

Checkout locally

git fetch origin pull/3/head:pr-3
git checkout pr-3