Skip to content

blockblaz/zig-libp2p

Repository files navigation

zig-libp2p

project-libp2p CI Zig Release License: MIT

A pure-Zig implementation of libp2p, the modular peer-to-peer networking stack. zig-libp2p targets the lean-consensus / Ethereum-consensus subset of libp2p — QUIC transport, gossipsub, and request/response — and is verified to interoperate with go-libp2p and rust-libp2p on the wire.

It was built for the zeam lean-Ethereum client, but the Host API is client-agnostic and usable by any Zig project that needs a libp2p node.

Status: pre-1.0. The public API is still evolving toward a 1.0 freeze (#172). Pin a release tag in your build.zig.zon and review the changelog before upgrading.

Highlights

  • QUIC-first transport (RFC 9000/9001) with libp2p TLS 1.3, backed by the companion zquic stack — no C dependencies, builds in a FROM scratch container.
  • Gossipsub v1.1 (StrictNoSign) with mesh maintenance, peer scoring, PX, IDONTWANT, direct peers, and FANOUT.
  • Request/response with length-prefixed SSZ + snappy framing.
  • Cross-implementation interop continuously exercised in CI against go-libp2p and rust-libp2p (handshake, ping, gossipsub, req/resp).
  • Single dependency, single import@import("zig_libp2p") exposes the whole surface; one Host object drives transport, muxing, and protocols.

Getting started

Requirements

  • Zig 0.16.0
  • zquic, pinned transitively and re-exported as zig_libp2p.zquic

Add it to your build

Add the dependency to your build.zig.zon (pin a released tag):

zig fetch --save "https://github.com/blockblaz/zig-libp2p/archive/refs/tags/v0.2.13.tar.gz"

Then wire it into build.zig:

const zig_libp2p = b.dependency("zig_libp2p", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("zig_libp2p", zig_libp2p.module("zig_libp2p"));

Shadow simulator

The transitively-pinned zquic (v1.7.49+) supports the Shadow network simulator — deterministic, bit-exact multi-peer replays — via the -Dshadow=true build flag. Because zig-libp2p sits entirely on top of zquic for QUIC transport (no direct syscalls of its own beyond what zquic re-exports), running a libp2p node under Shadow just means building zquic with that flag transitively.

Embedders forward the flag through their own build.zig:

const shadow = b.option(bool, "shadow", "Build for the Shadow simulator") orelse false;

const zig_libp2p_dep = b.dependency("zig_libp2p", .{
    .target = target,
    .optimize = optimize,
    // Forwarded into the zquic dep — zquic owns the syscall layer. When zquic
    // is built with -Dshadow=true it links libc and routes time / random / UDP
    // through libc so Shadow's LD_PRELOAD shim can intercept.
    .shadow = shadow,
});

Build with:

zig build -Dtarget=x86_64-linux-gnu -Dshadow=true -Doptimize=ReleaseSafe
file zig-out/bin/your-node   # → dynamically linked, /lib64/ld-linux-x86-64.so.2

The dynamically-linked-against-glibc binary is what Shadow's shim injects into. The default no-libc Linux build is unaffected. See zquic/docs/shadow.md for the full list of behavior knobs that flip (libc-routed clock_gettime / getrandom, sendmmsg/recvmmsg disabled in favor of per-message I/O), a minimal shadow.yaml, and known limitations.

Hello, node

The public surface lives in src/root.zig; the canonical end-to-end wiring (host creation, QUIC listen/dial, gossipsub, req/resp, event loop) is examples/host_quic_node.zig. Build the examples and run it with:

zig build examples
./zig-out/bin/example-host-quic-node

libp2p spec coverage

Coverage of the libp2p specifications, organized by spec area. zig-libp2p targets the subset required by lean / Ethereum consensus, so some libp2p features are intentionally out of scope.

Legend: ✅ implemented · 🚧 partial / experimental · ⬜ planned · ⛔ out of scope

Transports

Spec Status Notes
TCP transport.tcp
QUIC v1 (RFC 9000/9001) primary transport, via zquic; interop go ✅ · rust ✅
WebSocket — /ws (RFC 6455) transport.ws*; unit-tested
Secure WebSocket — /wss #94
WebTransport #94
WebRTC #94

Secure channels

Spec Status Notes
TLS 1.3 (libp2p TLS, RFC 0001) over QUIC and TCP (/tls/1.0.0); interop go ✅ · rust ✅
Noise (/noise, XX) RSA, ECDSA-P256, secp256k1, ed25519 identities

Stream multiplexing

Spec Status Notes
QUIC native streams default for the QUIC transport
yamux transport.yamux
mplex transport.mplex

Protocol negotiation

Spec Status Notes
multistream-select 1.0 transport.stream_multistream

Peer identity

Spec Status Notes
Peer IDs / keypairs identity, keypair
Signed peer records (RFC 0002) identify.verifySignedPeerRecord

Publish / subscribe

Spec Status Notes
gossipsub v1.1 (StrictNoSign) mesh, peer scoring (#199), PX, IDONTWANT, direct peers, FANOUT; interop go ✅ · rust ✅
floodsub superseded by gossipsub

Peer discovery & content routing

Spec Status Notes
Bootstrap (static dial) connect_peers via connection_manager
Kademlia DHT kad_dht, host; lifecycle (#203), record validators (#198)
mDNS (LAN discovery) discovery.mdns, host; peer_discovered events (#207)
Rendezvous rendezvous client/server, cookie paging, peer_discovered (#209)

NAT traversal

Spec Status Notes
AutoNAT v1 autonat; active probing, dial-back verification, sliding-window vote aggregation (#206). v2 wire codecs present; v2 transport wiring pending
Circuit Relay v2 🚧 relay, QUIC runtime; /p2p-circuit dial + reservation refresh (#204)
DCUtR (hole punching) dcutr; auto-trigger on relayed connections with retry (#205)

Utility & application protocols

Spec Status Notes
ping (/ipfs/ping/1.0.0) interop go ✅ · rust ✅
identify (/ipfs/id/1.0.0) identify
identify-push (/ipfs/id/push/1.0.0) identify, host, QUIC runtime auto-opens push streams
Request/response (length-prefixed, SSZ-snappy) req_resp; interop go ✅ · rust ✅

Not yet implemented

Spec Status Notes
Private networks (PSK / pnet) #171
Resource manager (scope-based limits) #169

The live cross-impl interop matrix is in harness/quic/README.md; the full module map is src/root.zig and the layout rationale is docs/REPO_LAYOUT.md.

Interoperability

Cross-implementation conformance is part of CI. To run the QUIC matrix locally:

zig build -Doptimize=ReleaseFast
(cd harness/quic/impls/go-libp2p && go build -o interop-quic-node-go .)
(cd harness/quic/impls/rust-libp2p && cargo build --release --locked)
harness/quic/run_matrix.sh zig,go-libp2p handshake,ping,gossipsub,reqresp
harness/quic/run_matrix.sh zig,rust-libp2p handshake,ping,gossipsub,reqresp

Or zig build interop-matrix for a quick zig↔go handshake+ping smoke. Harness details and the full status table live in harness/README.md.

Examples

All examples are under examples/ and install to zig-out/bin/ via zig build:

Example What it shows
example-host-quic-node Full Host + QUIC lifecycle (production wiring)
interop-quic-node Env-driven endpoint used by the cross-impl matrix
gen-libp2p-cert Mint a libp2p TLS certificate + derive its peer id
example-gossipsub-mesh Gossipsub publish/subscribe over a mesh
example-quic-ping-loopback QUIC ping round-trip on loopback
example-autonat-membuf, example-kad-dht-membuf In-memory AutoNAT / Kademlia smoke

See examples/README.md for the complete list.

Repository layout

Organized by libp2p layer (primitives → core → protocols → transport), not by transport. Each folder below has its own README describing its modules; the public API is the facade in src/root.zig.

zig-libp2p/
├── src/                  → library source — see src/README.md
│   ├── primitives/       wire-agnostic building blocks (identity, varint, multistream, protobuf)
│   ├── core/             node runtime: Host, Swarm, connection manager, events
│   ├── protocols/        one folder per libp2p protocol (gossipsub, kad-dht, autonat, relay, …)
│   ├── transport/        QUIC stack, TCP, WebSocket, yamux/mplex
│   └── security/         libp2p TLS 1.3 + Noise
├── examples/             runnable examples — see examples/README.md
├── harness/              cross-impl interop harnesses (quic/, tcp/) — see harness/README.md
├── bench/                micro-benchmarks
├── build/                build helpers (deps, examples, fuzz, soak, interop)
├── docs/                 design docs (architecture, security, per-protocol)
├── tests/                integration tests — see tests/interop/README.md
├── fixtures/             shared test fixtures
└── vendor/               vendored TLS/RSA, outside src/ — see vendor/README.md
Folder README
src/ overview src/README.md
src/primitives/ src/primitives/README.md
src/core/ src/core/README.md
src/protocols/ src/protocols/README.md
src/transport/ src/transport/README.md
src/security/ src/security/README.md
examples/ examples/README.md
harness/ harness/README.md
vendor/ vendor/README.md

Full rationale and the migration phases are in docs/REPO_LAYOUT.md; the layer diagram is in docs/ARCHITECTURE.md. Legacy src/*.zig import paths remain as compatibility shims through the 1.0 freeze.

Documentation

Roadmap

Per-protocol gaps are tracked in the spec-coverage tables above. The broader milestones toward a stable release:

  • 1.0-RC API freeze + semver#172
  • Third-party security audit + disclosure policy#170
  • Async swarm (std.Io co-scheduled, moving off the threaded runtime) — #57

Spec-compliance umbrella: #80.

Development

zig fmt --check .     # formatting
zig build test        # unit tests + example smoke-runs
zig build soak-test   # opt-in 60s QUIC gossipsub soak (#235)
zig build fuzz        # wire-decoder fuzzing via std.testing.fuzz

CI workflows live in .github/workflows/.

Releases are cut manually: tag the chosen commit and publish a GitHub release (gh release create vX.Y.Z --target main --notes …), bumping .version in build.zig.zon and the install snippet above in the same change.

Contributing

Contributions are welcome. Please open an issue to discuss substantial changes first, keep zig fmt clean, and make sure zig build test passes. New protocol behaviour should come with unit tests and, where it crosses the wire, an entry in the interop matrix.

Security

Wire-size limits and the threat model are documented in docs/SECURITY.md. A coordinated-disclosure policy is tracked in #170; until it lands, please report vulnerabilities privately to the maintainer rather than via public issues.

License

Released under the MIT License.

Acknowledgements

Built on the libp2p specifications and verified against go-libp2p and rust-libp2p.

About

A pure Zig implementation of the libp2p (WIP)

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors