# Week 13 — Update
## TL;DR
Implemented the gossipsub "publish" behavior in zig-libp2p.
PR: https://github.com/zen-eth/eth-p2p-z/pull/83/commits/08cfa1bd2f030a21ec15155fac4c9b57f1b25dcb
---
## Summary of Behavior
High-level rules:
1. When a valid message is received and not previously seen or self-originated, the router forwards it:
- First to peers.floodsub[topic] (floodsub backward-compatibility).
- Then to all peers in mesh[topic].
2. When the router publishes a message that originates locally:
- Always send to peers.floodsub[topic].
- If subscribed to topic (i.e., mesh[topic] exists), send to all peers in mesh[topic].
- If not subscribed:
- Use fanout[topic] if non-empty.
- If fanout[topic] is empty, select up to D peers from peers.gossipsub[topic], set fanout[topic], then send to fanout members.
---
## Forwarding received messages — explicit steps
When a message M is received:
1. Validate M.
2. If M was published by this router (self-origin), drop for forwarding.
3. If M was previously seen (dedup), drop.
4. Otherwise forward:
- Send M to every peer in peers.floodsub[topic].
- Send M to every peer in mesh[topic] (if mesh[topic] exists).
Notes:
- Dedup must occur before forwarding to avoid message loops.
- Do not add forwarded messages to fanout or mesh as if they were local publishes.
---
## Publishing messages (router-originated) — decision tree
When the application asks the router to publish message P to topic T:
1. Send P to all peers in peers.floodsub[T].
2. If mesh[T] exists (the router is subscribed):
- Send P to all peers in mesh[T].
- Done.
3. Else (router is not subscribed):
- If fanout[T] exists and is non-empty:
- Send P to all peers in fanout[T].
- Else:
- Select up to D peers from peers.gossipsub[T].
- Set fanout[T] to the selected peers.
- Send P to all peers in fanout[T].
Notes:
- fanout[T] persists across publishes; it is used until the topic is subscribed or fanout is cleared by TTL/maintenance rules.
- Selection policy for fanout should aim for connectivity and diversity (e.g., random + prefer connected peers), and should be deterministic enough for testing.
---
## Sequence diagram
```mermaid
sequenceDiagram
participant App
participant Router
participant FloodPeers as peers.floodsub[T]
participant MeshPeers as mesh[T]
participant FanoutPeers as fanout[T]
participant GossipPeers as peers.gossipsub[T]
App->>Router: publish(P, T)
Router->>FloodPeers: send P
alt subscribed (mesh[T] exists)
Router->>MeshPeers: send P
else not subscribed
alt fanout[T] non-empty
Router->>FanoutPeers: send P
else fanout empty
Router->>GossipPeers: select up to D -> set fanout[T]
Router->>FanoutPeers: send P
end
end
```
---
## Pseudocode
```pseudo
function publish(P, T):
for p in peers.floodsub[T]:
send(p, P)
if mesh[T] exists:
for m in mesh[T]:
send(m, P)
return
if fanout[T] empty:
fanout[T] = select_up_to_D(peers.gossipsub[T])
for f in fanout[T]:
send(f, P)
```
---
## Next
Start work on topic membership (mesh management and membership events). Concrete next tasks:
- Implement mesh join/leave hooks used by publish/forward logic.
- Add fanout TTL and refresh rules.
- Add unit tests listed above.
- Update PR with README note describing fanout selection policy and test cases.