https://github.com/blockblaz/zig-libp2p
A pure Zig implementation of the libp2p (WIP)
https://github.com/blockblaz/zig-libp2p
decentralisation decentralization libp2p networking peer-to-peer zig
Last synced: about 8 hours ago
JSON representation
A pure Zig implementation of the libp2p (WIP)
- Host: GitHub
- URL: https://github.com/blockblaz/zig-libp2p
- Owner: blockblaz
- License: mit
- Created: 2026-05-08T11:53:04.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-17T20:21:22.000Z (7 days ago)
- Last Synced: 2026-06-17T22:06:48.396Z (7 days ago)
- Topics: decentralisation, decentralization, libp2p, networking, peer-to-peer, zig
- Language: Zig
- Homepage:
- Size: 1.29 MB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Security: docs/SECURITY.md
Awesome Lists containing this project
README
# zig-libp2p
[](https://libp2p.io/)
[](https://github.com/blockblaz/zig-libp2p/actions/workflows/ci.yml)
[](https://ziglang.org/)
[](https://github.com/blockblaz/zig-libp2p/releases)
[](LICENSE)
A pure-Zig implementation of [libp2p](https://libp2p.io/), 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](https://github.com/libp2p/go-libp2p)
and [rust-libp2p](https://github.com/libp2p/rust-libp2p) on the wire.
It was built for the [zeam](https://github.com/blockblaz/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](https://github.com/blockblaz/zig-libp2p/issues/172)). Pin a release
> tag in your `build.zig.zon` and review the [changelog](CHANGELOG.md) before
> upgrading.
## Highlights
- **QUIC-first transport** (RFC 9000/9001) with libp2p TLS 1.3, backed by the
companion [`zquic`](https://github.com/ch4r10t33r/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](https://ziglang.org/) **0.16.0**
- [`zquic`](https://github.com/ch4r10t33r/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):
```sh
zig fetch --save "https://github.com/blockblaz/zig-libp2p/archive/refs/tags/v0.2.13.tar.gz"
```
Then wire it into `build.zig`:
```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`](https://github.com/ch4r10t33r/zquic) (v1.7.49+)
supports the [Shadow network simulator](https://shadow.github.io/) — 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`:
```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:
```sh
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](https://github.com/ch4r10t33r/zquic/blob/master/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`](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`](examples/host_quic_node.zig). Build the
examples and run it with:
```sh
zig build examples
./zig-out/bin/example-host-quic-node
```
## libp2p spec coverage
Coverage of the [libp2p specifications](https://github.com/libp2p/specs),
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](https://github.com/blockblaz/zig-libp2p/issues/94) |
| WebTransport | ⬜ | [#94](https://github.com/blockblaz/zig-libp2p/issues/94) |
| WebRTC | ⬜ | [#94](https://github.com/blockblaz/zig-libp2p/issues/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](https://github.com/blockblaz/zig-libp2p/issues/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](https://github.com/blockblaz/zig-libp2p/issues/203)), record validators ([#198](https://github.com/blockblaz/zig-libp2p/issues/198)) |
| mDNS (LAN discovery) | ✅ | `discovery.mdns`, `host`; `peer_discovered` events ([#207](https://github.com/blockblaz/zig-libp2p/issues/207)) |
| Rendezvous | ✅ | `rendezvous` client/server, cookie paging, `peer_discovered` ([#209](https://github.com/blockblaz/zig-libp2p/issues/209)) |
### NAT traversal
| Spec | Status | Notes |
|------|:------:|-------|
| AutoNAT v1 | ✅ | `autonat`; active probing, dial-back verification, sliding-window vote aggregation ([#206](https://github.com/blockblaz/zig-libp2p/issues/206)). v2 wire codecs present; v2 transport wiring pending |
| Circuit Relay v2 | 🚧 | `relay`, QUIC runtime; `/p2p-circuit` dial + reservation refresh ([#204](https://github.com/blockblaz/zig-libp2p/issues/204)) |
| DCUtR (hole punching) | ✅ | `dcutr`; auto-trigger on relayed connections with retry ([#205](https://github.com/blockblaz/zig-libp2p/issues/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](https://github.com/blockblaz/zig-libp2p/issues/171) |
| Resource manager (scope-based limits) | ⬜ | [#169](https://github.com/blockblaz/zig-libp2p/issues/169) |
The live cross-impl interop matrix is in
[`harness/quic/README.md`](harness/quic/README.md); the full module map is
[`src/root.zig`](src/root.zig) and the layout rationale is
[`docs/REPO_LAYOUT.md`](docs/REPO_LAYOUT.md).
## Interoperability
Cross-implementation conformance is part of CI. To run the QUIC matrix locally:
```sh
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`](harness/README.md).
## Examples
All examples are under [`examples/`](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`](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`](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/README.md) |
| `src/primitives/` | [`src/primitives/README.md`](src/primitives/README.md) |
| `src/core/` | [`src/core/README.md`](src/core/README.md) |
| `src/protocols/` | [`src/protocols/README.md`](src/protocols/README.md) |
| `src/transport/` | [`src/transport/README.md`](src/transport/README.md) |
| `src/security/` | [`src/security/README.md`](src/security/README.md) |
| `examples/` | [`examples/README.md`](examples/README.md) |
| `harness/` | [`harness/README.md`](harness/README.md) |
| `vendor/` | [`vendor/README.md`](vendor/README.md) |
Full rationale and the migration phases are in
[`docs/REPO_LAYOUT.md`](docs/REPO_LAYOUT.md); the layer diagram is in
[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md). Legacy `src/*.zig` import paths
remain as compatibility shims through the 1.0 freeze.
## Documentation
- **Repository layout** — [`docs/REPO_LAYOUT.md`](docs/REPO_LAYOUT.md) · **Architecture** — [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
- **Security model & wire limits** — [`docs/SECURITY.md`](docs/SECURITY.md)
- **AutoNAT** — [`docs/AUTONAT.md`](docs/AUTONAT.md) · **Kademlia DHT** — [`docs/KAD_DHT.md`](docs/KAD_DHT.md) · **mDNS** — [`docs/MDNS.md`](docs/MDNS.md)
- **Async swarm design** — [`docs/async-swarm.md`](docs/async-swarm.md)
- **zeam integration notes** — [`docs/zeam-parity.md`](docs/zeam-parity.md)
## 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](https://github.com/blockblaz/zig-libp2p/issues/172)
- **Third-party security audit + disclosure policy** — [#170](https://github.com/blockblaz/zig-libp2p/issues/170)
- **Async swarm** (`std.Io` co-scheduled, moving off the threaded runtime) — [#57](https://github.com/blockblaz/zig-libp2p/issues/57)
Spec-compliance umbrella: [#80](https://github.com/blockblaz/zig-libp2p/issues/80).
## Development
```sh
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/`](.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`](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`](docs/SECURITY.md). A coordinated-disclosure policy is
tracked in [#170](https://github.com/blockblaz/zig-libp2p/issues/170); until it
lands, please report vulnerabilities privately to the maintainer rather than via
public issues.
## License
Released under the [MIT License](LICENSE).
## Acknowledgements
Built on the [libp2p specifications](https://github.com/libp2p/specs) and
verified against [go-libp2p](https://github.com/libp2p/go-libp2p) and
[rust-libp2p](https://github.com/libp2p/rust-libp2p).