Highlights
- Connection management gained high/low watermark pruning, peer scoring, protected peers, decaying tags, and composable hard-limit + trimming modes, exposed through
SwitchBuilder.withWatermarkPolicy,withPeerScoring,withMaxConnections, andwithMaxInOut. LPProtocolnow supports incoming/outgoing stream budgets, including total and per-peer limits.- Service Discovery landed, including advertiser, registrar, discoverer, signed extended peer records, routing-table management, component tests, and C binding support.
- C bindings were significantly expanded with configurable transports and muxers, Kademlia validators/selectors, circuit relay, AutoNAT, peerstore APIs, service discovery APIs, and custom protocol handlers.
- SwitchBuilder and connection management were reworked around connection limits, watermarks, peer scoring, address policies, announced addresses, NAT configuration, hole punching, and Identify Push.
- GossipSub gained extension-based ping/pong, preamble, and partial-message support, H/M/L message priorities, slow-peer scoring controls, improved queue behavior, and broader interoperability coverage.
- Kademlia gained metrics, configurable record TTLs, provider rejection/spillover support, optional bootstrapping disablement, privacy-preserving connection-status hiding, and several race fixes.
- Transport and stream handling improved with QUIC multi-address listening, stream reset support, stricter transport start errors, WebSocket accept concurrency fixes, and better cancellation propagation.
- Crypto and dependency handling were hardened with a libp2p-owned
Rngabstraction, BoringSSL wiring, deterministic Ed25519 keys from seed, RSA key-size validation, and refreshed Nim/Nimble/Nix dependency metadata. - New network simulation tooling, Gossipsub/transport unified-testing interop helpers, and many flaky-test fixes were added.
- Identify Push support was added as a switch service, enabled by default in
SwitchBuilderand configurable withwithIdentifyPusher, so peers can be notified when local peer information changes. - Address announcement support improved with
withAnnouncedAddresses,withPrivateAddressFilter. - PubSub and stream write paths now use
sinkin several hot paths to reduce message/buffer copies.
Breaking changes
- The minimum supported Nim version is now
2.2.4. The tested versions are2.2.4and2.2.10. - The Mix protocol was extracted from this repository into
logos-co/nim-libp2p-mix. Imports underlibp2p/protocols/mix, Mix tests/examples/docs,MixPubKeyBook, and thelibp2p_mix_*C APIs were removed. - Public APIs that used
std/options.Optionnow useresults.Opt. Migratesome(...)/none(...)call sites toOpt.some(...)/Opt.none(...)where required. - Public RNG-facing APIs now use the libp2p
Rngtype instead ofref HmacDrbgContext/var HmacDrbgContext. UsenewRng()or wrap existing BearSSL RNG state with the compatibility helper where needed. newStandardSwitchandnewStandardSwitchBuilderwere removed from the public API. UseSwitchBuilder.new()...build()instead.- Manual switch construction changed:
newSwitchwas removed, andSwitchBuilderis now the supported stable path for building switches. SwitchBuilder.withServiceswas removed.Serviceis now an internal switch lifecycle abstraction; externally created background work should be managed by the application. Service methods changed as well:setupis synchronous and may raiseServiceSetupError,runwas renamed tostart, and lifecycle methods no longer returnbool.- Connection limit configuration changed.
withMaxInandwithMaxOutwere removed; usewithMaxInOut(...),withMaxConnections(...), orwithConnectionLimits(...). Also,maxConnsPerPeernow enforces the configured value exactly; custom values may allow one fewer connection than before because an off-by-one bug was fixed. ConnManager.newnow takes structured limit/watermark/scoring configuration instead of the oldmaxConnections,maxIn, andmaxOutargument set.- Several public buffer APIs now take
sink seq[byte]and may consume buffers withmove(...)to reduce copies, including PubSub publish and stream/protobuf write paths. Normal call sites usually continue to compile, but custom overrides, wrapper proc types, or code that reuses/mutates a buffer after passing it to libp2p may need updates. - PubSub/GossipSub priority APIs changed from boolean priority flags to
MessagePriority.High,MessagePriority.Medium, andMessagePriority.Low. Deprecatedsend/broadcastoverloads takingisHighPrioritywere removed. GossipSubParams.maxNumElementsInNonPriorityQueuewas removed. UsemaxMediumPriorityQueueLenandmaxLowPriorityQueueLen.- PubSub custom connection naming was changed to stream naming: for example
useCustomConnbecameuseCustomStream, and custom connection callbacks became custom stream callbacks. - GossipSub preamble and ping/pong behavior moved to the extension system. Do not rely on
-d:libp2p_gossipsub_1_4; configure the relevant extension throughGossipSubParams. LPProtocolstream limits changed.maxIncomingStreamswas replaced by total/per-peer incoming and outgoing stream limit fields:maxIncomingStreamsTotal,maxIncomingStreamsPerPeer,maxOutgoingStreamsTotal, andmaxOutgoingStreamsPerPeer.- Kademlia module/type names changed in a few places:
routingtablewas renamed torouting_table, andTimeStampwas renamed toTimestamp. - Kademlia now hides connection status by default when encoding peer records. Pass the relevant config/encode option if your application intentionally needs the old behavior.
- Kademlia locally stored value records now expire after the configured TTL. Code relying on indefinite local
PUT_VALUEretention should set an appropriaterecordExpirationInterval. - Transport
startbehavior is stricter. TCP, WebSocket, QUIC, and Tor transports now raiseTransportStartErroron unsupported or non-wire addresses instead of silently skipping or accepting them. - RSA key handling is stricter: imported RSA keys below 2048 bits and RSA keys above 4096 bits are rejected.
- The C binding ABI changed.
libp2p_config_tno longer uses the oldflagsbitmask, stream callbacks were renamed from connection-oriented names to stream-oriented names, Mix APIs were removed, and users should rebuild against the v2 header.
Switch creation
newStandardSwitch and newStandardSwitchBuilder were removed. Use SwitchBuilder:
let switch = SwitchBuilder
.new()
.withAddress(MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet())
.withTcpTransport()
.withMplex()
.build()Options API
Public APIs moved from std/options.Option to results.Opt:
# before
publishParams = some(PublishParams(...))
# after
publishParams = Opt.some(PublishParams(...))RNG API
Public RNG-facing APIs now use libp2p Rng:
# before
let rng: ref HmacDrbgContext = newRng()
# after
let rng: Rng = newRng()Connection limits
Use structured connection limit configuration:
# before
.withMaxIn(30)
.withMaxOut(20)
# after
.withMaxInOut(30, 20)Pubsub sink/move
var data = @[byte 1, 2, 3]
discard await pubsub.publish(topic, move(data))
# Do not read or mutate `data` after this point.What's Changed
- feat(kad): DHT Metrics by @SionoiS in #2111
- chore(mix): truncate exponential delay to practical limits based on probablity by @chaitanyaprem in #2120
- fix(cbind): various by @richard-ramos in #2123
- chore: resolve exception in logos -delivery by @darshankabariya in #2122
- fix(cbind): protocol mounting duplication by @richard-ramos in #2128
- chore(cbind): remove duplicate flags by @gmelodie in #2130
- feat(cbind): kad validator and selectors by @richard-ramos in #2129
- chore: bump lsquic by @richard-ramos in #2125
- feat(cbind): withAddresses, multiplexers by @gmelodie in #2131
- feat(cbind): add circuit relay, autonat by @gmelodie in #2137
- feat(cbind): add transport, conn limits by @gmelodie in #2135
- test(interop): add partial message interop with go peer by @vladopajic in #2119
- test(interop): fix partial message flakines by @vladopajic in #2140
- refactor(gossipsub): convert ping pong to extensions by @vladopajic in #2144
- chore: harmonized proc name for no-op completed future by @rikettsie in #2145
- fix(cbind): libp2p_kad_random_records - add missing import by @rlve in #2149
- chore(ai): add .github/copilot-instructions.md for coding agent onboarding by @Copilot in #2151
- test: hardening and cosmetics by @vladopajic in #2150
- chore: add msys+gcc build target for windows by @richard-ramos in #2133
- test: use
rnginstead ofnewRngby @vladopajic in #2154 - fix(kad): update async schedule of findrandom by @SionoiS in #2142
- fix(kad): handle dial failed error early by @gmelodie in #2147
- feat(cbind): add circuit relay client by @rlve in #2146
- chore: fix hint
XCannotRaiseYby @vladopajic in #2157 - chore: fix some hints
XDeclaredButNotUsedby @vladopajic in #2155 - chore: avoid using deprecated callbacks of newDatagramTransport and createStreamServer by @vladopajic in #2160
- chore: avoid using deprecated type ByteAddress by @vladopajic in #2158
- chore: fix depracated warning for
Future.cancel()by @vladopajic in #2161 - chore: utilize newFutureCompleted by @vladopajic in #2159
- refactor: use
resultslib instead ofoptionslib by @vladopajic in #2162 - chore: make UnreachableCode warnings as error by @vladopajic in #2165
- test(mix): component tests by @rlve in #2167
- test(mix): organise component tests by @rlve in #2175
- test(mix): unit tests by @rlve in #2176
- refactor(preamblestore): simplifying interface by @vladopajic in #2177
- test(mix): misc by @rlve in #2178
- test(gossipsub): improve test "mesh is rebalanced during heartbeat - opportunistic grafting" by @vladopajic in #2183
- refactor(gossipsub): add preamble extension by @vladopajic in #2179
- chore(extensions): more generic missbehvior callback by @vladopajic in #2187
- chore(extensions): add penalty cases by @vladopajic in #2188
- chore: add
with*constructors to messages by @vladopajic in #2191 - test(interop): update transport workflow and support
unified-testingby @rlve in #2185 - chore: switch update_copilot_instructions workflow to claude-3-7-sonnet by @Copilot in #2205
- chore: bump chronos, jwt, bearssl, testutils by @nitely in #2199
- feat(quic): add support for listening on many addresses by @vladopajic in #2193
- chore: reduce log level for noisy "too many channels created" log by @richard-ramos in #2197
- test(interop): update hp script by @rlve in #2189
- fix(kad): get providers aggregates race by @gmelodie in #2204
- fix(mix): delay correlation risks by @chaitanyaprem in #2198
- test(multiaddress): getField protobuf tests by @rlve in #2195
- chore(test): utilize rng() template by @vladopajic in #2211
- refactor(mix): add
Delaytype by @vladopajic in #2226 - fix: nil pointer dereference issues caused when sha256 is used in ref object by @vladopajic in #2216
- test(transport): inconsistent start behaviour by @rlve in #2229
- fix(autonatv2): reachability greater than expected by @gmelodie in #2215
- chore: remove semaphore by @vladopajic in #2056
- fix(autonat): cleanup duplicated services on tests by @gmelodie in #2232
- fix(mix): avoid creation of random by @vladopajic in #2228
- feat: create Ed25519 key from seed by @rlve in #2239
- chore(service-disco): add protobuf messages and utilities by @gmelodie in #2237
- chore(connmanager): performance and cosmetic improvements by @vladopajic in #2242
- chore: remove unused ngtcp2 dependency from pinned list by @richard-ramos in #2244
- test(interop): GossipSub - core instructions (part 1) by @rlve in #2240
- chore(crypto): add pick utilities by @gmelodie in #2245
- feat(gossipsub): extend message priorities to H/M/L by @richard-ramos in #2241
- test(mix): fix flaky test "rate limit exceeded - message rejected at intermediate node" by @vladopajic in #2255
- chore(future): add cancelSoon by @vladopajic in #2250
- chore(crypto): reduce memory allocations for ecnist keys by @Copilot in #2251
- chore(service-disco): add service discovery by @gmelodie in #2246
- test(gossipsub): fix flaky test when peers should be dropped in same heatbeat as publish by @vladopajic in #2259
- test(switch): fix flaky test causing "mount unstarted protocol" errors by @Copilot in #2257
- test(transports): fix flaky test "server writes after EOF" by @vladopajic in #2263
- fix: add asyncSleep before dial in "mount unstarted protocol" test to fix Windows flakiness by @Copilot in #2271
- chore(connmanager): add muxer store by @vladopajic in #2247
- fix(autotls): letsencrypt challenge type change by @gmelodie in #2262
- feat(switchbuilder): add withHolePunching by @SionoiS in #2265
- test(interop): GossipSub - partial messages (part 2) by @rlve in #2249
- feat(service-disco): add ipTree, signatures by @gmelodie in #2267
- chore(deps): use lsquic nimble package by @richard-ramos in #2279
- chore: update API stability and experimental extensions section by @richard-ramos in #2277
- feat(service-disco): routing table manager by @gmelodie in #2274
- test(transports): replace sleepAsync with write loop in "server writes after EOF" by @Copilot in #2273
- chore(service-disco): use ServiceId type by @gmelodie in #2290
- refactor(connmanager): constructors by @vladopajic in #2282
- fix(mix): track and cancel handleMixMessages futures by @Copilot in #2272
- feat(builder):
withPrivateAddressFilterby @richard-ramos in #2286 - feat(quic): add getStreams, close session after handle exit by @fcecin in #2280
- feat(gossip): reduce score of slow peers by @richard-ramos in #2269
- chore: remove trailing space from copyright header by @Copilot in #2299
- fix(gossipsub): flaky scoring test by @gmelodie in #2289
- chore: update copilot instructions to reflect latest repository state by @Copilot in #2297
- feat(connmanager): watermark by @vladopajic in #2284
- feat: extend libp2p_network_bytes and agents traffic metrics to all transports by @Copilot in #2295
- chore: add code formatting guidelines to instructions by @richard-ramos in #2298
- fix(service-disco): add missing tables import by @gmelodie in #2302
- feat(service-disco): add registrar by @gmelodie in #2275
- test(gossipsub): extensions race condition + fix by @rlve in #2288
- feat: network simulation by @richard-ramos in #2294
- fix: raise exception rather than defect on malformed DNS response by @jm-clius in #2300
- feat(service-disco): add advertiser by @gmelodie in #2285
- chore(copilot): add more instructions by @vladopajic in #2307
- chore: bump lsquic by @richard-ramos in #2311
- test(gossipsub): partial messages with fanout bug + fix by @rlve in #2310
- fix(transports): unify start proc error behavior - raise TransportStartError for all invalid addresses by @Copilot in #2253
- feat(mix): cover traffic with constant rate by @chaitanyaprem in #2243
- feat(service-disco): add discoverer by @gmelodie in #2306
- chore: bump deps by @richard-ramos in #2312
- test(interop): GossipSub - fixes (part 3) by @rlve in #2313
- chore(service-disco): add component tests by @gmelodie in #2308
- feat(connmanager): ephemeral tags by @vladopajic in #2316
- feat(cbind): register custom protocol handlers by @richard-ramos in #2314
- chore: add local testing addr policy by @SionoiS in #2315
- chore(service-disco): various fixes by @SionoiS in #2320
- chore(service-disco): add peer table and store update side effect by @SionoiS in #2323
- fix(service-disco): registrar wait formula ceiling by @SionoiS in #2326
- fix(floodsub): increase timeout for large message transfer in FloodSub message size validation 2 by @Copilot in #2331
- feat(connmanager): composable modes by @vladopajic in #2325
- chore(connmanager): cosmetics by @vladopajic in #2327
- feat(service-disco): add missing API functions by @gmelodie in #2321
- chore(cbind): add service discovery by @gmelodie in #2324
- chore(cbind): add service disco headers by @gmelodie in #2338
- chore(examples): add connection manager examples by @vladopajic in #2332
- chore(connmanager): consts tidy by @vladopajic in #2329
- feat(mix): add coverRateFraction config to cover traffic by @chaitanyaprem in #2322
- test: correct lower bound tests by @tinniaru3005 in #2337
- chore: remove runAfter by @vladopajic in #2355
- feat(cbind): add peerstore by @gmelodie in #2346
- fix(kad): race in randomFind by @gmelodie in #2345
- chore(examples): add peer scoring examples by @vladopajic in #2356
- test(interop): unified-testing helpers by @rlve in #2333
- chore: removing
.public.pragma by @vladopajic in #2365 - chore(examples): tidy by @vladopajic in #2362
- fix(docs): add root index.html redirect to fix 404 on GitHub Pages by @Copilot in #2358
- refactor(connmanager): add limits config by @vladopajic in #2363
- feat(pubsub): reduce publish-time message copies with sink by @richard-ramos in #2368
- feat: add dial back addr in StatusAndConfidenceHandler by @2-towns in #2354
- test(interop): perf by @rlve in #2364
- feat: reset stream by @richard-ramos in #2283
- fix(service-disco): reduce chance of flaky test by @SionoiS in #2367
- chore: update NIMBLE_COMMIT to version v0.99.1 by @jmgomez in #2348
- chore(service-disco): refactor registrar time types by @SionoiS in #2334
- chore(connmanager): naming improvements by @vladopajic in #2372
- test(gossipsub): eliminate timing-sensitive waits from scoring tests by @Copilot in #2371
- fix(connmanager): max conns per peer limit by @vladopajic in #2344
- chore: removing deprecated things by @vladopajic in #2366
- fix: truncated
identify: decoded messagelog due to unbounded address list by @Copilot in #2374 - fix: replace generic
payloadlog key with descriptive names in pubsub by @Copilot in #2379 - chore: move interop ignore items to their own gitignore by @Copilot in #2377
- feat(kad): hide connection info by @gmelodie in #2361
- chore(ci): test Nim 2.2.4 and 2.2.10 by @narimiran in #2339
- fix(pubsub): track pending sends without adding backpressure by @richard-ramos in #2370
- fix: prevent GossipSub from relaying messages back to original source by @Copilot in #2376
- chore(service-disco): add ipSimCoefficient by @gmelodie in #2342
- chore(kad): handle dial failed exception by @gmelodie in #2164
- feat(kad): add flag to disable bootstrapping by @SionoiS in #2387
- fix(muxer): accept loop stuck by @gmelodie in #2360
- fix: propagate shortAgent through wrapped connection chain to restore peer metrics by @Copilot in #2389
- refactor: unify default DNS servers under dnsresolver by @Copilot in #2390
- test(interop): unified testing refactor by @rlve in #2373
- chore: use multicodec CSV to generate list of codecs by @Copilot in #2392
- chore(service-disco): added debug logging by @SionoiS in #2388
- chore: run autobump and documentation as daily jobs instead of on every push to master by @Copilot in #2393
- chore: test ORC memory management by @narimiran in #2148
- ci: add runnableExamples check and daily CI workflow by @Copilot in #2401
- test(interop): transport fix by @rlve in #2405
- chore: remove old nim hacks by @gmelodie in #2396
- fix: random (rng) arguments initialization in constructors by @Copilot in #2398
- fix(autotls): withAutotls independent ordering by @gmelodie in #2410
- feat: boringssl by @richard-ramos in #2411
- test: stabilize flaky
Heartbeat::catch up on slow heartbeattiming assertion by @Copilot in #2414 - test(service-disco): refactor utils by @rlve in #2409
- feat(service-disco): Local registrar access by @SionoiS in #2406
- feat: identify pusher by @vladopajic in #2412
- test(service-disco): clean up and improve unit/component separation by @rlve in #2415
- feat(kad): add provider rejection and spillover by @gmelodie in #2394
- chore: extract mix to logos-co/nim-libp2p-mix by @chaitanyaprem in #2378
- test(interop): GossipSub - fix message id by @rlve in #2427
- chore(identify): cosmetics improvment by @vladopajic in #2418
- refactor(rng): make the rng a libp2p type by @richard-ramos in #2420
- fix(gossip): make slow peer penalty opt-in by default by @richard-ramos in #2429
- chore: fix required Nim version and some CI warnings by @narimiran in #2426
- test(websocket): stabilize WebSocket EOF write assertion in stream transport tests by @Copilot in #2423
- chore: use >= to choose boringssl dependency by @richard-ramos in #2435
- test(service-disco):
addProvidedService/lookupcomponent tests by @rlve in #2432 - feat(PeerInfo): add observer by @vladopajic in #2439
- chore(MultiAddress): memory optimization by @vladopajic in #2428
- refactor(IdentifyPusher): as Service by @vladopajic in #2440
- chore: Use protobuf_serialization in RendezVous protocol by @nitely in #2166
- test: drop
untilTimeoutand standardize oncheckUntilTimeoutby @Copilot in #2447 - test: fix flaky service-discovery test for two advertisers on one service by @Copilot in #2445
- chore(service-disco): dedupe identical ads by @rlve in #2443
- chore(service-disco): rename
startDiscoveringtoregisterInterest+ improve component test by @rlve in #2441 - fix(kad): table insertion check by @SionoiS in #2434
- chore: regenerate nix deps by @rlve in #2452
- chore: drop
newStandardSwitchandnewStandardSwitchBuilderfrom public api by @vladopajic in #2442 - chore: utilize
cancelAndWaittemplate by @Copilot in #2451 - test: simplify
makeStandardSwitchandmakeStandardSwitchBuilderby @Copilot in #2453 - test: stabilize
Switch::e2e max outgoing connection limitsby forcing TCP transport by @Copilot in #2456 - fix(service-disco): fix misplaced log line by @SionoiS in #2460
- test(service-disco): advertise and registration response by @rlve in #2457
- fix(peerstore): reset identify stream on cancellation by @richard-ramos in #2459
- test(service-disco): lookup component by @rlve in #2461
- test(service-disco): error handling component by @rlve in #2464
- fix(ws): process pending handshakes concurrently by @richard-ramos in #2359
- refactor(Switch): Service lifecycle by @vladopajic in #2462
- feat(peerstore): address TTL by @gmelodie in #2425
- chore(deps): bump nim-websock to >= 0.4.0 by @richard-ramos in #2465
- chore: makefile instead of nimble by @gmelodie in #2454
- test(service-disco): client mode + one register component by @rlve in #2463
- test(service-disco): misc component by @rlve in #2467
- test(Noise): cosmetics by @vladopajic in #2472
- chore(PeerInfo): cosmetics by @vladopajic in #2473
- feat(kademlia): expire value records after configurable TTL by @Copilot in #2397
- chore(SwitchBuilder):
build()proc cleanup by @vladopajic in #2466 - chore(SwitchBuilder): avoid braking building chain by @vladopajic in #2476
- feat(nat): announcedAddrs by @gmelodie in #2483
- chore: better names for streams and connections by @richard-ramos in #2482
- test(service-disco): validateRegisterMessage + message size by @rlve in #2480
- fix(websocket): avoid asyncSpawn by @Copilot in #2471
- chore(SwitchBuilder): drop
withServicesby @vladopajic in #2475 - chore(SwitchBuilder): gracePeriod disabled by default by @vladopajic in #2486
- test(service-disco): non-32-byte keys + misc component by @rlve in #2488
- fix(rsa): reject imported keys below 2048 bits by @richard-ramos in #2491
- test: improve "one advertiser provides two services - both discoverable" by @Copilot in #2492
- fix(autotls): parsing failed due to missing enum value by @vladopajic in #2497
- fix(cancellation): preserve CancelledError in broad handlers by @richard-ramos in #2495
- fix(rsa): cap max key size by @richard-ramos in #2494
- test(service-disco): add repro test for #2499 by @rlve in #2500
- feat(streams): use sink for write buffers by @richard-ramos in #2501
- feat(pubsub): use sink for RPC buffers by @richard-ramos in #2503
- feat(nat): NATService skeleton by @gmelodie in #2493
- fix(service-disco): build advert once to keep adverts byte-identical by @rlve in #2502
- chore: use
protobuf_serialization0.4.0 by @richard-ramos in #2508 - feat(protobuf): Use sink in protobuf decode paths by @richard-ramos in #2504
- chore: remove implicit
resultvariable usage across libp2p source by @Copilot in #2506 - chore(readme): add Mix Protocol to project list by @vladopajic in #2507
- chore: remove remaining result keyword usage by @richard-ramos in #2518
- feat: more
sinkchanges by @richard-ramos in #2517 - fix(autotls): avoid
dns-persist-01challenge and raise api errors by @vladopajic in #2519 - chore: remove unnecessary ProveField warning override by @tersec in #2523
- chore: dcutr protobuf serialization using nim-protobuf-serialization by @moigagoo in #2477
- feat(LPProtocol): stream limits by @vladopajic in #2522
- feat: v2.0.0 by @richard-ramos in #2527
New Contributors
- @darshankabariya made their first contribution in #2122
- @rikettsie made their first contribution in #2145
- @nitely made their first contribution in #2199
- @fcecin made their first contribution in #2280
- @2-towns made their first contribution in #2354
- @jmgomez made their first contribution in #2348
- @moigagoo made their first contribution in #2477
Full Changelog: v1.15.3...v2.0.0