Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 129 additions & 3 deletions yarn-project/p2p/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,133 @@
# P2P

This package includes the functionality of the P2P networking required by the aztec node. The `P2PClient` provides an interface for the introduction of transactions to the Tx Pool and propagation of those transactions through the network. The `P2PService` offers an abstraction of the P2P networking.
This package implements the P2P networking layer for Aztec nodes using libp2p. It handles transaction propagation, block and checkpoint proposal dissemination, attestation collection for consensus, and peer management. The `P2PClient` provides the top-level interface used by `aztec-node`; the `BootstrapNode` class runs a lightweight discovery-only node that introduces peers to the network without participating in gossip.

The package depends on a block source in order to reconcile the transaction pool and remove settled transactions.
## Architecture

Additionally, the `BootstrapNode` class provides the functionality for running a P2P 'bootnode', one that serves the purpose of introducing new peers to the network. It does not participate in transaction exchange.
- **P2PClient** wraps everything below. Manages lifecycle, bridges L2 block events to pool state transitions, exposes `ITxProvider` for RPC.
- **LibP2PService** is the core networking layer. Subscribes to gossipsub topics, registers req/resp handlers, runs message validation pipelines. It composes:
- **PeerManager** — peer scoring (gossipsub + application-level), authentication (STATUS/AUTH handshakes), connection gating.
- **DiscV5Service** — UDP-based peer discovery using Ethereum's discv5 protocol and ENR records.
- **ReqResp** — request-response protocols: BLOCK, BLOCK_TXS, TX, STATUS, AUTH, PING, GOODBYE.
- **TxCollection** — coordinates transaction fetching: fast collection for proposals/proving (deadline-driven, falls back to `BatchTxRequester`) and slow background collection for unproven blocks.
- **Mempools** sit below the service layer:
- **TxPoolV2** — transaction mempool with explicit state machine (pending, protected, mined, soft-deleted, hard-deleted) and pluggable eviction rules.
- **AttestationPool** — stores block/checkpoint proposals and attestations per slot. Handles equivocation detection and slash callbacks.

### Key Components

| Component | Responsibility |
|-----------|---------------|
| **P2PClient** | Top-level orchestrator. Manages lifecycle, bridges L2 block events to pool state transitions, exposes `ITxProvider` for RPC. |
| **LibP2PService** | Core networking. Subscribes to gossipsub topics, registers req/resp handlers, runs message validation pipelines. |
| **PeerManager** | Peer scoring (gossipsub + application-level), authentication (STATUS/AUTH handshakes), connection gating. |
| **DiscV5Service** | UDP-based peer discovery using Ethereum's discv5 protocol and ENR records. |
| **TxCollection** | Coordinates transaction fetching: fast collection for proposals/proving (deadline-driven, falls back to `BatchTxRequester`) and slow background collection for unproven blocks. |
| **BatchTxRequester** | Aggressive parallel fetching of missing txs from peers via BLOCK_TXS protocol. Classifies peers as pinned/dumb/smart for efficient batching. |
| **TxPoolV2** | Transaction mempool with explicit state machine (pending, protected, mined, soft-deleted, hard-deleted) and pluggable eviction rules. |
| **AttestationPool** | Stores block/checkpoint proposals and attestations per slot. Handles equivocation detection and slash callbacks. |

### Peer Lifecycle

```
Unknown → [DiscV5 discovery] → Discovered → [TCP connect] → Connected
→ [STATUS or AUTH handshake] → Authenticated → [gossip participation] → Active
```

Handshake type depends on config:
- `p2pAllowOnlyValidators` = true and peer is not protected: **AUTH** handshake (signature challenge proving validator identity). Unauthenticated peers get `appSpecificScore = -Infinity`, excluding them from all gossip.
- Otherwise: **STATUS** handshake (version compatibility check only).
- Protected peers (trusted/private/preferred): STATUS only, always considered authenticated.

Connection gating: peers with too many failed AUTH attempts (`p2pMaxFailedAuthAttemptsAllowed`, default 3) are denied inbound connections for 1 hour.

---

## Sub-module Documentation

| README | Covers |
|--------|--------|
| [Gossipsub Scoring](src/services/gossipsub/README.md) | P1-P4 parameter calculation, decay mechanics, convergence math, global thresholds, application-level penalties, tuning guidelines |
| [Transaction Validation](src/msg_validators/tx_validator/README.md) | Validator factories per entry point, individual validator descriptions with benchmarks, coverage table |
| [Proposal Validation](src/msg_validators/proposal_validator/README.md) | BlockProposal and CheckpointProposal gossipsub validation, pool admission, validator-client processing, slashing |
| [Attestation Validation](src/msg_validators/attestation_validator/README.md) | CheckpointAttestation gossipsub validation, pool admission, equivocation detection, L1 submission validation |
| [ReqResp Protocols](src/services/reqresp/README.md) | Handshake protocols (STATUS, AUTH, PING, GOODBYE), block data protocols (BLOCK, BLOCK_TXS, TX), rate limits, transport validation |
| [BatchTxRequester](src/services/reqresp/batch-tx-requester/README.md) | Peer classification (pinned/dumb/smart), worker architecture, BLOCK_TXS wire protocol |
| [TxPool Interface](src/mem_pools/tx_pool/README.md) | TxPool contract, storage structure, priority system, nullifier deduplication, eviction rules |
| [TxPoolV2](src/mem_pools/tx_pool_v2/README.md) | State machine, soft deletion (slot-based vs prune-based), pre-add vs post-event rules |

---

## Gossipsub Objects

All gossipsub messages pass through a shared pre-validation pipeline before topic-specific logic:

| Stage | Rule | Consequence | File |
|-------|------|-------------|------|
| 0 | Snappy decompressed size <= per-topic limit (see per-object sections) | Message dropped | `p2p/src/services/encoding.ts` |
| 1 | P2PMessage envelope deserializes | REJECT + LowToleranceError | `p2p/src/services/libp2p/libp2p_service.ts` |
| 2 | Gossipsub-level message cache dedup (configurable `seenTTL`) | Silently dropped by gossipsub | gossipsub internals |
| 3 | Application-level dedup via `MessageSeenValidator` (fixed-size circular buffer + Set) | IGNORE | `p2p/src/msg_validators/msg_seen_validator/` |

A REJECT result from any validation stage increments the gossipsub P4 (invalidMessageDeliveries) counter for the peer on that topic. P4 weight is -20, decaying over 4 slots. This is in addition to any application-level peer penalty.

### Peer Penalty Severity Reference

| Severity | Approx. strikes to ban | Used for |
|----------|------------------------|----------|
| `LowToleranceError` | ~2 | Invalid proof, deserialization failure, old double-spend |
| `MidToleranceError` | ~10 | Most validation failures (metadata, data, gas, phases, size) |
| `HighToleranceError` | ~50 | Timestamp expiry, block header, recent double-spend, rate limits |

See [Gossipsub Scoring](src/services/gossipsub/README.md) for full score calculation, decay mechanics, and threshold alignment.

### Object Summary

| Topic | Snappy Limit | Description | Detailed Docs |
|-------|-------------|-------------|---------------|
| `tx` | 512 KB | Transactions. Two-stage validation: fast validators (parallel) then proof verification. Pool pre-check between stages avoids wasting CPU on proof for txs the pool would reject. | [Tx Validation](src/msg_validators/tx_validator/README.md) |
| `block_proposal` | 10 MB | Block proposals from proposers. Validated for slot timing, signature, proposer identity, tx hash integrity. Validator nodes may re-execute and slash on state mismatch. | [Proposal Validation](src/msg_validators/proposal_validator/README.md) |
| `checkpoint_proposal` | 10 MB | Checkpoint proposals containing the final block. Same proposal validation as blocks, plus embedded block extraction and separate validation. | [Proposal Validation](src/msg_validators/proposal_validator/README.md) |
| `checkpoint_attestation` | 5 KB | Validator attestations for checkpoints. Validated for slot timing, attester/proposer signatures, committee membership. Equivocation at count=2 triggers slash callback. | [Attestation Validation](src/msg_validators/attestation_validator/README.md) |

---

## ReqResp Protocols

See [ReqResp Protocols](src/services/reqresp/README.md) for full protocol details.

### Rate Limits (Responder Side)

| Protocol | Peer Limit | Global Limit |
|----------|-----------|-------------|
| PING | 5/s | 10/s |
| STATUS | 5/s | 10/s |
| AUTH | 5/s | 10/s |
| GOODBYE | 5/s | 10/s |
| BLOCK | 2/s | 5/s |
| BLOCK_TXS | 10/s | 200/s |
| TX | (see config) | (see config) |

Per-peer limit exceeded: `HighToleranceError` + `RATE_LIMIT_EXCEEDED` status. Global limit exceeded: `RATE_LIMIT_EXCEEDED` status only (no peer penalty).

### Peer Score Thresholds

| Score | State | Action |
|-------|-------|--------|
| > -50 | Healthy | Normal |
| -100 < score <= -50 | Disconnect | GOODBYE sent + disconnect on next heartbeat |
| <= -100 | Banned | GOODBYE sent + disconnect on next heartbeat |

### Protocol Summary

| Protocol | Request | Response | Purpose |
|----------|---------|----------|---------|
| STATUS | Own blockchain state | Peer's blockchain state | Version compatibility check on connect |
| AUTH | Random challenge (`Fr`) | Signed challenge response | Validator identity verification on connect |
| PING | (empty) | `pong` | Liveness check |
| GOODBYE | Reason byte | (none meaningful) | Graceful disconnect |
| BLOCK | Block number (`Fr`) | Block data (3 MB snappy) | Block sync |
| BLOCK_TXS | Archive root + tx hashes + BitVector | Txs + BitVector of availability | Batch tx fetching for proposals/proving |
| TX | `TxHashArray` | Matching txs | Individual tx fetching |

Request payloads are NOT snappy-compressed (asymmetric: only responses use snappy).
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Attestation Validation

This module validates `CheckpointAttestation` gossipsub messages. Attestations are signatures from committee members endorsing a checkpoint proposal.

**Topic**: `checkpoint_attestation` | **Snappy size limit**: 5 KB

## Stage 1: AttestationValidator (Gossipsub Validation)

| # | Rule | Consequence | Severity | File |
|---|------|-------------|----------|------|
| 1 | **Slot timeliness**: `currentSlot` or `nextSlot`. Previous slot within 500ms: IGNORE. Older: REJECT. | REJECT or IGNORE | HighToleranceError | `attestation_validator.ts` |
| 2 | **Attester signature**: `getSender()` must recover valid address | REJECT | LowToleranceError | same |
| 3 | **Attester in committee**: recovered address in committee for slot | REJECT | HighToleranceError | same |
| 4 | **Proposer exists**: `getProposerAttesterAddressInSlot` must return defined | REJECT | HighToleranceError | same |
| 5 | **Proposer signature**: `getProposer()` must recover valid address | REJECT | LowToleranceError | same |
| 6 | **Proposer matches expected**: recovered proposer = expected for slot | REJECT | HighToleranceError | same |
| 7 | **NoCommitteeError**: committee unavailable | REJECT | LowToleranceError | same |

**Fisherman mode extension** (`FishermanAttestationValidator`): if a checkpoint proposal for the same archive exists in pool, the attestation's `ConsensusPayload` must `.equals()` the stored proposal's payload. On mismatch: REJECT + LowToleranceError.

## Stage 2: Pool Admission

| # | Rule | Consequence |
|---|------|-------------|
| 8 | Sender recoverable (pool-side) | Silent drop |
| 9 | Not a duplicate (same slot + proposalId + signer) | IGNORE |
| 10 | Per-signer cap: `MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER` = 3 | IGNORE |

Own attestations added via `addOwnCheckpointAttestations` bypass the per-signer cap.

## Stage 3: Equivocation Detection

When a signer's attestation count for a slot reaches exactly 2 (different proposals): `duplicateAttestationCallback` fires -> `WANT_TO_SLASH_EVENT` with `OffenseType.DUPLICATE_ATTESTATION`. Attestation still ACCEPTED and rebroadcast. Callback fires once (not again at count 3+).

## Validation at L1 Checkpoint Submission (Archiver)

| Rule | Consequence | File |
|------|-------------|------|
| Each attestation must have recoverable signature (or address-only is allowed but does not count toward quorum) | Checkpoint rejected as invalid | `archiver/src/modules/validation.ts` |
| Attestation at index `i` must correspond to committee member at index `i` | Checkpoint rejected as invalid | same |
| Valid attestation count >= floor(committee * 2/3) + 1 | Checkpoint rejected as invalid | same |
| No committee / escape hatch open | Accepted unconditionally | same |

Note: `skipValidateCheckpointAttestations` config flag bypasses all archiver attestation validation.

## Gossipsub Topic Scoring

P3 enabled with expected messages per slot = `targetCommitteeSize`. Conservative threshold (30% of convergence value). Max P3 penalty = -34 per topic.

Loading
Loading