Repository navigation
Closed
Labels
Description
Unit W6.4 of docs/PLAN.md.
Gossipsub v1.1: the RPC codec, mesh, scoring, and the heartbeat as one pure step with time as an Event (§3.3), the signing policies, and the bounded queues of base/conc.
Where the spec lives
- The unit row: root
docs/PLAN.md— the deliverable, the dependencies, the priority. - The frozen interfaces: root
docs/ARCHITECTURE.md, §3 (the mechanisms) and §8 (this package). - The package's own docs:
packages/libp2p/protocols/docs/ARCHITECTURE.mdand itsPLAN.md— read them first; they refine the root docs and never contradict them. - The reference: the
spikebranch, none — new work, the largest component (ARCHITECTURE §7). Read it before you implement. Port its tests, keep the wire bytes; the code shape follows §3, not the spike's internals (§7 preamble, §9).
Your freedom, and its cost
The docs govern, and they are yours to change. Where a better design exists, change it — and change the documents in the same pull request. A contract change starts at the root docs/ARCHITECTURE.md; the package docs follow it in the same change. Code that disagrees with the docs, or package docs that disagree with the root, does not merge.
Definition of done
- The public surface follows ARCHITECTURE §4; the owned contracts hold.
- The wire suite, the scoring and trickle regressions, and the interop gate: go and rust peers with no behavior difference.
- The carried vector and property tests pass through the
Testssuite. lake build,lake test, andlake test -- +RTS -N1 -RTSare green;scripts/lint-imports.shis green.- No
sorry, no build warnings (CLAUDE.md, "Strict checking"). - First submodule under your leaf? Widen the lib's
globsinlakefile.tomlin the same commit.
Depends on
- [W5.6] libp2p/host: host, swarm, peerstore, dedup #19 (
W5.6) — blocking. - [W5.7] libp2p/protocols: identify and ping #20 (
W5.7) — blocking. - [W1.1] base/conc: the concurrency primitives #1 (
W1.1) — blocking.
Every issue is claimable from day one; you build ahead of open dependencies against mocks of their frozen interfaces (RULES.md, "Working ahead of the tree").
Ground rules
- Comment
claimto take the issue; an organiser assigns it. One issue at a time. - A pull request within 8 hours of the assignment; drafts count. Link the issue (
Closes #N). Miss the window, lose the claim. - Target the
hackathon26branch. - The license-acceptance line of the PR description stays ticked; commits carry no AI co-author trailers. Two guards fail the PR otherwise.
- Prose register everywhere: CLAUDE.md, "Writing Style".
- A contract question the docs do not settle: ask on this issue before you code past it.
Activity
IvanAnishchuk commentedon Nov 2, 2026
W1.1 (#27) changes frozen signatures this unit builds on, so I'm posting here as RULES.md asks ("Working ahead of the tree"). The change is approved on the PR: #27 (comment)
Everything that can park now runs in
Conc.Async, since a parkedAsyncholds no OS thread (5000 parked receivers: 12 threads, against 5005 with a blockingIO.wait;scripts/park-threads.lean).What gossipsub will see:
Chan.sendandChan.recvareAsync.sendanswers.error .closedon a closed channel, andtrySendnever parks.Chan.newwants a proof of0 < capacity, so a queue can't end up with capacity 0 by accident.Chan.newUnboundedis the named exception, and it needs its reason in the docstring.selectisAsyncand takes a proof that its array of parks isn't empty.Alarmis new: the task that wakes a loop at the due time its core asked for last. I think the heartbeat fits on it.Asyncwith its otherbase/concimports now.Until #27 merges, build against a mock of it (RULES.md); once it merges, rebase.
IvanAnishchuk commentedon Nov 4, 2026
The W4.2 pull request (#47) changes the TCP close discipline of root ARCHITECTURE §4.7, which the
Connectionofnet/streamscarries to every layer above it.closesends a FIN when no write is in flight, and an RST when one is. On v4.34, a write to a peer that stops reading never completes. libuv'sshutdownwaits behind it, and the write request holds the socket and its descriptor. A C shim innet/streamsends such a connection, and the peer gets an RST. A failed write follows the same rule.none, the end-of-stream channel of §3.5. go-libp2p closes every TCP connection with an RST (linger 0,vendor/go-libp2p/p2p/transport/tcp/tcp.go, lines 278 to 281), so a session with a go node ends this way.The
Connectiontype and its fields stay the same. Thenet/streamsARCHITECTURE, "Decisions", records both rules with their sources.Wenbobobo commentedon Nov 4, 2026
claim
IvanAnishchuk commentedon Nov 5, 2026
#60 (W5.9) adds
newStreamto the host's public surface (packages/libp2p/host/docs/ARCHITECTURE.md), the call that opens an outbound stream:newStream (h : Host) (peer : PeerId) (protocols : List ProtocolId), answered with the selected id and the stream. With no live session, it dials the peer first. It is go-libp2p'shost.NewStream(vendor/go-libp2p/core/host/host.go, lines 61 to 65). A client of this unit that opens its own stream reaches it through this call. No existing host signature changes.IvanAnishchuk commentedon Nov 5, 2026
#61 (W5.6) touches the docs of two packages this unit builds on, through the chain of root PLAN.
packages/libp2p/core/docs/ARCHITECTURE.mdfixes the policy shapes, which the core surface left to the host: the gater'sallowDial,allowInbound, andallowSecured;ResourceManager.openConnectionwith itsConnectionScope; andAddressRanker.rankover go-libp2p'sAddrDelayschedule. No seam ofSecurityProtocol,Muxer,MuxSession, orStreamHandlerchanges.packages/libp2p/negotiate/docs/ARCHITECTURE.mdgainsupgradeWith, the upgrade with a checkpoint after the handshake, andnegotiateStream, multistream-select over one muxed stream.upgradekeeps its signature.The host surface also has
newStream(#60 posted it). A unit that holds aHostopens its streams through it, and one that serves streams registers aStreamHandler, unchanged.docs(protocols): give the trickle regressions an owner in the plan
IvanAnishchuk commentedon Nov 5, 2026
#62 (W4.3, yamux) touches docs this unit builds on. No existing signature changes.
base/bytesgainsBytes.take?(withsliceAt?), which moves out ofStreams.Framing, andBytes.Blob, the wrapper that gives core data aReprfor its bytes.net/streamsgainsStreams.readLoop, the reader task of a session: a credit from the loop before each read, a post per chunk, and a post for the end of the connection.net/yamuxlands its session:Session.new role conn leftover clock keepalive,openStream,acceptStream,close, andjoin, serving theStreamseam.IvanAnishchuk commentedon Nov 5, 2026
#63 (W5.1) lands
libp2p/identityand touches docs and types this unit builds on. No existing signature changes.Libp2p.IdentityexportsKeyType,PubKey,PrivKey,PeerId, andIdentity.Error. The entry points arePubKey.unmarshal?,PrivKey.unmarshal?,PubKey.marshal,PubKey.verify,PrivKey.sign : ByteArray → ExceptT Error IO ByteArray,PrivKey.toPublic,PeerId.ofPubKey,PeerId.ofBytes?,PeerId.toBytes, andPeerId.ofString?.PeerIdderivesBEq,DecidableEq,Hashable,Ord, andRepr, as root §3.2 asks.ToStringprints the parsed text form. The derived==also compares that form, so code that asks "same peer?" comparesa.hash == b.hash.Multiformats.Multihashnow derivesHashableandOrd, and the generated multiformats enums (HashCode,ContentCodec,Protocol,Multibase.Base) deriveOrd.Multiformats.Multiaddr.validPeerHash;PeerIdcarries its proof.IvanAnishchuk commentedon Nov 6, 2026
Interface change from W5.2:
StreamHandler.handlenow takes aStreamContext(the provedremotePeerand the connection'sremoteAddr) before the stream. The reason and the full shape are on #15.A handler value or a core mock in this unit's PR needs the new argument. A handler that needs neither field writes
fun _ s => ….leolara commentedon Nov 9, 2026
The gate closed with PR #59. The review verified the recorded Go+Lean and Rust+Lean cells on a binary built from the head the body names, with the full SHA verifiable on the fork, seed 1, reach 1.0, and the branch resolved onto the reviewed seam versions of the tip. The wire suite and the scoring and trickle regressions run in Tests.Gossipsub, and the merged tip passes the four gates.