API测试
- 作者仓库星标 0
- 作者更新于 实时读取
- 作者仓库 skills-registry
- 领域
- 工程开发
- 兼容 Agent
-
- Claude Code
- Cursor
- Cline
- Codex
- Windsurf
- Gemini CLI
- +20
- 信任分
- 88 / 100 · 社区维护
- 作者 / 版本 / 许可
- @tomevault-io · 未声明 license
- Token 消耗评级
- 较高消耗
- 接入复杂程度
- 需简单配置
- 是否需要外部 API Key
- 不需要
- 兼容的系统
- macOS · Linux · Windows
- 底层运行要求
- Node.js
- 文件与系统权限
-
- 只读
- 允许写入 / 修改
- 网络行为
- 允许外网请求
- 安装命令数
- 26 条
档案由构建时根据 SKILL.md 与安装命令自动衍生,可能与作者实际意图存在差异。
需要注意: 未限定 allowed-tools,默认拥有全部工具权限。
---
name: rust-libp2p
description: Use this skill when the user asks about rust-libp2p, Rust libp2p, libp2p::SwarmBuilder, NetworkB…
category: 工程开发
runtime: Node.js
---
# rust-libp2p 输出预览
## PART A: 任务判断
- 适用问题:代码实现、重构、调试或代码审查。
- 输入要求:目标材料、限制条件、期望输出和验收方式。
- 证据边界:围绕“Scope / Version and freshness notes / Mental model”读取原文规则,不把推断写成作者承诺。
## PART B: 执行结果
- **01** 任务判断:确认你的需求是否属于代码实现、重构、调试或代码审查,并标出输入、限制和预期结果。
- **02** 执行计划:优先按“Scope / Version and freshness notes / Mental model”拆成步骤,说明每一步会读取什么、修改什么、产出什么。
- **03** 交付结果:给出可复制的命令、文件改动、检查清单或内容草稿,并说明如何继续迭代。
- **04** 风险边界:结合 读取文件、写入/修改文件、会按任务需要访问外部网络、通常不需要额外 API Key 给出执行前确认项。
## Running Rules
- 读取文件、写入/修改文件;会按任务需要访问外部网络;通常不需要额外 API Key。
- 先小样例验证,再放大到真实任务。
- 交付时同时给结果、检查口径和下一步迭代建议。 原文出现了 `/ipfs`、`/ip4`、`/ip6`、`/dnsaddr`、`/dns` 这类斜杠命令;如果你的 Agent 支持命令触发,优先用命令开场,再补充目标和边界。
告诉 Agent 目标文件或材料、期望结果、不可改范围、是否允许联网或执行命令。本 Skill 的权限画像是:读取文件、写入/修改文件。
先用一个小任务确认它会围绕“Scope / Version and freshness notes / Mental model”工作;涉及文件或命令时,先看 diff、日志、预览或测试结果。
检查最终产物是否包含明确结果、必要证据和下一步动作;如果输出泛泛而谈,就补充输入、边界和验收标准后重跑。
---
name: rust-libp2p
description: Use this skill when the user asks about rust-libp2p, Rust libp2p, libp2p::SwarmBuilder, NetworkB…
category: 工程开发
source: tomevault-io/skills-registry
---
# rust-libp2p
## 什么时候使用
- 把工程方向的常用动作沉淀成 Agent 可调用的技能 适合处理工程开发场景下的代码实现、调试、重构、测试或代码审查,核心价值是把输入、判断、执行、验证和交付边界固定下来,避免 Agent 泛泛回答。 把任务拆成可执行、可检查、可继续迭代…
- 面向代码实现、重构、调试或代码审查,优先处理能明确输入、步骤和验收标准的工作。
## 需要提供什么
- 目标材料、目录范围、期望结果和不可改动内容。
- 是否允许联网、执行命令、读写文件或调用外部服务。
## 执行规则
- 围绕「Scope / Version and freshness notes / Mental model」组织步骤,不把推断写成作者事实。
- 读取文件、写入/修改文件;会按任务需要访问外部网络;通常不需要额外 API Key。
- 先跑小样例,确认结果可检查后再扩大任务范围。
## 输出要求
- 给出最终产物、关键证据、验证方式和下一步动作。
- 信息不足时标记 unknown,不编造命令、平台或依赖。 作者原文负责流程事实;仓库文件负责来源和命令;流狐只补充适用场景、限制和质量判断。
skill "rust-libp2p" {
输入层 -> 用户目标 + 目标文件 + 禁止范围 + 验收标准
上下文层 -> Scope / Version and freshness notes / Mental model
规则层 -> SKILL.md 触发条件 / 执行顺序 / 输出格式
运行层 -> Node.js | 读取文件、写入/修改文件 | 会按任务需要访问外部网络
安全层 -> 通常不需要额外 API Key + 小任务验证 + diff / 日志复核
输出层 -> 可复制结果 + 检查清单 + 下一步迭代
} rust-libp2p
Scope
This skill is specifically for the Rust implementation of libp2p, not js-libp2p or go-libp2p.
Use the general libp2p skill for protocol concepts like peer IDs, multiaddrs, relays, and DHTs. Use this skill for Rust crate names, feature flags, APIs, module layout, code patterns, and implementation-specific gotchas.
When answering, prefer Rust API names and examples:
libp2p::SwarmBuilder, notcreateLibp2p.#[derive(NetworkBehaviour)]fromlibp2p::swarm, not JavaScript service configuration objects.Behaviour,Config, andEventtypes from protocol crates.SwarmEventloops, not callback/event-emitter style code.- Cargo feature flags, because the root crate compiles almost nothing unless the right features are enabled. Humanity invented optional compilation and then made everyone debug missing imports. Naturally.
Version and freshness notes
rust-libp2p evolves quickly. Before giving exact API answers, check the current crate/source when possible.
Known source baseline used for this skill:
- Current published docs on docs.rs show
libp2p0.56.0. - GitHub
mastermetadata has moved tolibp2p0.56.1. - The workspace MSRV is Rust
1.83.0, edition2021. - The root
libp2pcrate has no default features in0.56.0; users must enable features explicitly. - DeepWiki is useful for architecture, but source and rustdoc win when they disagree.
Use version = "0.56" in examples unless the user asks for an exact pinned version. For production answers, say “verify against the current libp2p/Cargo.toml and docs.rs.”
Mental model
A rust-libp2p node is built from these layers:
- Identity:
libp2p_identity::KeypairandPeerId. - Transport: how bytes move, such as TCP, QUIC, WebSocket, UDS, memory, or WASM transports.
- Security upgrade: usually Noise or TLS for TCP/WebSocket. QUIC already includes TLS 1.3.
- Stream multiplexer: usually Yamux for TCP/WebSocket. QUIC, WebTransport, and WebRTC have native multiplexing.
- Protocol behaviour:
NetworkBehaviourimplementations such asping::Behaviour,kad::Behaviour,gossipsub::Behaviour,request_response::Behaviour,identify::Behaviour,relay::client::Behaviour. - Swarm: the runtime orchestrator that drives transports, connection pools, behaviours, handlers, and events.
Rust-libp2p separates “how to send bytes” from “what bytes to send”:
Transporthandles dialing, listening, and producing connections.NetworkBehaviourdecides protocol actions, emits commands to the swarm, and produces application-visible events.ConnectionHandlerowns per-connection state and substream negotiation for a behaviour.Swarm<B>ties the transport to a root behaviourB. It must be polled as a stream to make progress.
Root crate and features
The root crate is libp2p. It re-exports many implementation crates behind Cargo features.
A minimal native Ping example needs:
[dependencies]
libp2p = { version = "0.56", features = ["noise", "ping", "tcp", "tokio", "yamux"] }
futures = "0.3"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
Common feature flags:
| Feature | Enables |
|---|---|
tokio |
Tokio provider for SwarmBuilder and supported transports |
tcp |
libp2p::tcp native TCP |
dns |
DNS address resolution wrapper |
quic |
native QUIC transport |
websocket |
native WebSocket transport |
websocket-websys |
browser/WASM WebSocket transport |
webrtc-websys |
browser/WASM WebRTC transport |
webtransport-websys |
browser/WASM WebTransport transport |
noise |
Noise security upgrade |
tls |
libp2p TLS security upgrade |
yamux |
Yamux stream muxer |
macros |
#[derive(NetworkBehaviour)] |
ping |
/ipfs/ping/1.0.0 behaviour |
identify |
Identify behaviour |
kad |
Kademlia DHT behaviour |
gossipsub |
Gossipsub pub/sub behaviour |
request-response |
Generic request/response framework |
cbor, json |
Predefined request-response codecs |
mdns |
LAN mDNS discovery |
relay |
Circuit Relay v2 client/server support |
autonat |
NAT reachability detection |
dcutr |
Direct Connection Upgrade through Relay, hole punching |
rendezvous |
Rendezvous peer registration/discovery |
upnp |
UPnP port mapping |
metrics |
OpenMetrics/Prometheus metrics support |
pnet |
private network pre-shared-key protection |
plaintext |
plaintext transport upgrade; avoid except tests/dev |
rsa, ed25519, ecdsa, secp256k1 |
identity key algorithm support |
serde |
serde integration for selected types |
The full feature exists, but do not recommend it blindly. It increases build time and target incompatibility risk. Use feature-specific examples unless the user explicitly wants “everything.”
Workspace and implementation crates
The repository is a monorepo with core, transports, protocols, muxers, examples, and utilities.
Important crates and paths:
| Crate | Path | Purpose |
|---|---|---|
libp2p |
libp2p/ |
Root convenience crate and SwarmBuilder |
libp2p-core |
core/ |
Core traits and types: Transport, upgrades, muxing, multiaddr glue |
libp2p-identity |
identity/ |
Keypairs, public keys, PeerId |
libp2p-swarm |
swarm/ |
Swarm, NetworkBehaviour, ConnectionHandler, events |
libp2p-swarm-derive |
swarm-derive/ |
#[derive(NetworkBehaviour)] macro |
libp2p-yamux |
muxers/yamux/ |
Recommended stream multiplexer for TCP/WebSocket |
libp2p-mplex |
muxers/mplex/ |
Legacy muxer; avoid for new work |
libp2p-tcp |
transports/tcp/ |
Native TCP transport |
libp2p-quic |
transports/quic/ |
QUIC transport with built-in TLS and multiplexing |
libp2p-websocket |
transports/websocket/ |
Native WebSocket transport |
libp2p-dns |
transports/dns/ |
DNS resolution wrapper |
libp2p-noise |
transports/noise/ |
Noise security upgrade |
libp2p-tls |
transports/tls/ |
TLS security upgrade |
libp2p-kad |
protocols/kad/ |
Kademlia DHT |
libp2p-gossipsub |
protocols/gossipsub/ |
Mesh gossip pub/sub |
libp2p-request-response |
protocols/request-response/ |
Typed request/response |
libp2p-identify |
protocols/identify/ |
Exchange peer metadata, protocols, addresses |
libp2p-relay |
protocols/relay/ |
Circuit Relay v2 |
libp2p-autonat |
protocols/autonat/ |
NAT reachability detection |
libp2p-dcutr |
protocols/dcutr/ |
Hole punching via relayed connection upgrade |
libp2p-mdns |
protocols/mdns/ |
LAN discovery |
libp2p-rendezvous |
protocols/rendezvous/ |
Rendezvous registration/discovery |
libp2p-upnp |
protocols/upnp/ |
Router port mapping |
libp2p-stream |
protocols/stream/ |
Raw stream opening with protocol negotiation; check current crate status before recommending |
SwarmBuilder API
Prefer SwarmBuilder for new examples. It is the high-level builder exported from libp2p.
Canonical native chain:
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
.with_tokio()
.with_tcp(
libp2p::tcp::Config::default(),
libp2p::noise::Config::new,
libp2p::yamux::Config::default,
)?
.with_behaviour(|key| {
let peer_id = key.public().to_peer_id();
libp2p::ping::Behaviour::default()
})?
.build();
Important builder methods:
| Method | Purpose |
|---|---|
SwarmBuilder::with_new_identity() |
Generate a fresh identity |
SwarmBuilder::with_existing_identity(keypair) |
Use a provided libp2p::identity::Keypair |
.with_tokio() |
Select Tokio runtime provider |
.with_tcp(tcp_config, security_upgrade, multiplexer_upgrade) |
Add native TCP plus security and mux upgrades |
.with_quic() / .with_quic_config(...) |
Add native QUIC |
.with_dns() / .with_dns_config(...) |
Add DNS resolution wrapper |
.with_websocket(security_upgrade, multiplexer_upgrade) |
Add native WebSocket over the existing transport stack |
| `.with_other_transport( | key |
.with_relay_client(security_upgrade, multiplexer_upgrade) |
Add relay client transport/behaviour support |
.with_bandwidth_metrics(&mut registry) |
Wrap transport with bandwidth metrics |
| `.with_behaviour( | key |
| `.with_swarm_config( | cfg |
.build() |
Build Swarm<B> |
with_tcp, with_websocket, and with_relay_client accept function items or tuples of function items for upgrades:
.with_tcp(
tcp::Config::default(),
(tls::Config::new, noise::Config::new),
yamux::Config::default,
)?
Use this tuple form when you want fallback negotiation between security upgrades. The same pattern applies to multiplexer upgrades, though Yamux alone is the recommended default for new TCP/WebSocket stacks.
When .with_relay_client(...) is used, the .with_behaviour(...) closure receives (key, relay_behaviour) and the relay behaviour must be included in the root behaviour:
#[derive(libp2p::swarm::NetworkBehaviour)]
struct Behaviour {
relay: libp2p::relay::client::Behaviour,
ping: libp2p::ping::Behaviour,
}
let swarm = libp2p::SwarmBuilder::with_new_identity()
.with_tokio()
.with_tcp(tcp::Config::default(), noise::Config::new, yamux::Config::default)?
.with_relay_client(noise::Config::new, yamux::Config::default)?
.with_behaviour(|_key, relay| Behaviour {
relay,
ping: ping::Behaviour::default(),
})?
.build();
Without relay client, the behaviour closure receives only &Keypair.
Swarm API
Swarm<B> contains network state and a behaviour. It must be continuously polled as a Stream.
Useful methods:
| Method | Use |
|---|---|
listen_on(Multiaddr) |
Start listening |
dial(peer_id_or_multiaddr_or_DialOpts) |
Dial a known peer or raw multiaddr |
local_peer_id() |
Access local peer ID |
listeners() |
Current listen addresses |
external_addresses() |
Confirmed externally reachable addresses |
add_external_address(addr) |
Announce an address known to be reachable |
add_peer_address(peer, addr) |
Tell behaviours about a peer address |
behaviour() / behaviour_mut() |
Access protocol behaviour |
connected_peers() |
Iterate connected peer IDs |
is_connected(&peer_id) |
Check peer connectivity |
disconnect_peer_id(peer_id) |
Close all connections to peer |
close_connection(connection_id) |
Gracefully close a specific connection |
Event loop skeleton:
use futures::StreamExt;
use libp2p::swarm::SwarmEvent;
loop {
match swarm.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => {
println!("Listening on {address}");
}
SwarmEvent::Behaviour(event) => {
println!("Behaviour event: {event:?}");
}
SwarmEvent::ConnectionEstablished { peer_id, .. } => {
println!("Connected to {peer_id}");
}
SwarmEvent::ConnectionClosed { peer_id, cause, .. } => {
println!("Connection to {peer_id} closed: {cause:?}");
}
_ => {}
}
}
If the swarm is not polled, nothing progresses. Not dialing, not listening, not protocol negotiation. A perfect machine, doing absolutely nothing, as requested by an unpolled future.
NetworkBehaviour
Every protocol crate exposes a Behaviour that implements NetworkBehaviour. Compose several behaviours with the derive macro:
use libp2p::{
gossipsub, identify, kad, mdns, ping,
swarm::NetworkBehaviour,
};
#[derive(NetworkBehaviour)]
struct Behaviour {
ping: ping::Behaviour,
identify: identify::Behaviour,
kad: kad::Behaviour<kad::store::MemoryStore>,
gossipsub: gossipsub::Behaviour,
mdns: mdns::tokio::Behaviour,
}
Enable the macros feature for the derive macro:
libp2p = { version = "0.56", features = ["macros", "..."] }
Manual NetworkBehaviour implementations are advanced. They must provide:
- Associated type
ConnectionHandler. - Associated type
ToSwarm. handle_established_inbound_connection.handle_established_outbound_connection.on_swarm_event.on_connection_handler_event.poll.
Use manual implementations only when writing a custom protocol crate or advanced behaviour. For applications, compose existing behaviours with the derive macro.
ConnectionHandler
ConnectionHandler is per-connection protocol state. Most application authors do not implement it directly.
Use it when implementing a custom protocol that needs to:
- Negotiate inbound or outbound substreams.
- Run protocol-specific state for each connection.
- Receive commands from a behaviour.
- Emit handler events back to the behaviour.
Most built-in protocols follow this pattern:
Behaviour: global protocol state, query state, peer tables, application events.Handler: per-connection substream negotiation and I/O.Config: tunable settings.Event: application-facing events.
Identity and PeerId
Common identity patterns:
let keypair = libp2p::identity::Keypair::generate_ed25519();
let peer_id = keypair.public().to_peer_id();
Use SwarmBuilder::with_new_identity() for throwaway/test nodes and SwarmBuilder::with_existing_identity(keypair) when stable peer identity matters.
Enable key features as needed:
ed25519: common default for new keys.rsa: useful for IPFS interoperability because many IPFS peers still use RSA identities.ecdsa,secp256k1: for networks that standardize on those key types.
Multiaddr
Rust examples usually parse a multiaddr from a string:
let addr: libp2p::Multiaddr = "/ip4/0.0.0.0/tcp/0".parse()?;
swarm.listen_on(addr)?;
Common native listen addresses:
/ip4/0.0.0.0/tcp/0
/ip6/::/tcp/0
/ip4/0.0.0.0/udp/0/quic-v1
Dialing usually requires the remote PeerId to appear in the multiaddr or to be known through peer store/behaviour state:
/ip4/203.0.113.10/tcp/4001/p2p/<peer-id>
/dnsaddr/bootstrap.libp2p.io/p2p/<peer-id>
Relayed address shape:
/ip4/<relay-ip>/tcp/<relay-port>/p2p/<relay-peer-id>/p2p-circuit/p2p/<dest-peer-id>
Transport choices
| Transport | Feature/crate | Target | Security/mux notes | Use when |
|---|---|---|---|---|
| TCP | tcp / libp2p-tcp |
native | Needs Noise/TLS + Yamux | Default native transport |
| QUIC | quic / libp2p-quic |
native | Built-in TLS 1.3 + multiplexing | Low-latency native transport |
| DNS | dns / libp2p-dns |
native | Wrapper, not a transport by itself | Dial /dns, /dns4, /dns6, /dnsaddr addresses |
| WebSocket | websocket / libp2p-websocket |
native | Usually with Noise/TLS + Yamux | Compatibility with WebSocket listeners |
| WebSocket websys | websocket-websys |
WASM/browser | Browser WebSocket constraints apply | Browser fallback |
| WebRTC websys | webrtc-websys |
WASM/browser | Native WebRTC streams | Browser peer connections |
| WebTransport websys | webtransport-websys |
WASM/browser | WebTransport/HTTP3 constraints | Browser-to-compatible endpoints |
| UDS | uds / libp2p-uds |
Unix native | Local IPC | Same-machine communication |
| Memory | MemoryTransport in core |
tests | In-process only | Unit/integration tests |
QUIC does not need .with_tcp(... noise ... yamux ...) style upgrades because QUIC already provides encryption and multiplexing. TCP and WebSocket do need security and mux upgrades.
The builder’s native transport methods are gated out on wasm32. Browser builds use the *-websys transports and wasm-bindgen.
Minimal Ping node
use std::{error::Error, time::Duration};
use futures::StreamExt;
use libp2p::{noise, ping, swarm::SwarmEvent, tcp, yamux, Multiaddr};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
.with_tokio()
.with_tcp(
tcp::Config::default(),
noise::Config::new,
yamux::Config::default,
)?
.with_behaviour(|_| ping::Behaviour::default())?
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
if let Some(addr) = std::env::args().nth(1) {
let remote: Multiaddr = addr.parse()?;
swarm.dial(remote)?;
}
loop {
match swarm.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => {
println!("Listening on {address}");
}
SwarmEvent::Behaviour(event) => {
println!("{event:?}");
}
_ => {}
}
}
}
Composite behaviour template
Use this pattern for real applications that need discovery plus messaging:
use std::{error::Error, time::Duration};
use futures::StreamExt;
use libp2p::{
gossipsub, identify, kad, noise, ping,
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux,
};
#[derive(NetworkBehaviour)]
struct Behaviour {
identify: identify::Behaviour,
kad: kad::Behaviour<kad::store::MemoryStore>,
gossipsub: gossipsub::Behaviour,
ping: ping::Behaviour,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
.with_tokio()
.with_tcp(
tcp::Config::default(),
noise::Config::new,
yamux::Config::default,
)?
.with_behaviour(|key| {
let peer_id = key.public().to_peer_id();
let identify = identify::Behaviour::new(identify::Config::new(
"/myapp/1.0.0".to_string(),
key.public(),
));
let store = kad::store::MemoryStore::new(peer_id);
let kad = kad::Behaviour::new(peer_id, store);
let gossipsub = gossipsub::Behaviour::new(
gossipsub::MessageAuthenticity::Signed(key.clone()),
gossipsub::Config::default(),
)?;
Ok(Behaviour {
identify,
kad,
gossipsub,
ping: ping::Behaviour::default(),
})
})?
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
loop {
match swarm.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => {
println!("Listening on {address}");
}
SwarmEvent::Behaviour(event) => {
println!("{event:?}");
}
_ => {}
}
}
}
For this template, enable:
libp2p = { version = "0.56", features = [
"gossipsub", "identify", "kad", "macros", "noise", "ping", "tcp", "tokio", "yamux"
] }
Identify
identify::Behaviour exchanges Info messages on established connections. It reports listen addresses, protocol support, observed address, and public key information.
Important Rust-specific discrepancy: Identify is not treated as core. Other behaviours do not automatically get Identify data. You must manually hook Identify events into protocols that need address information.
Kademlia integration pattern:
match event {
SwarmEvent::Behaviour(BehaviourEvent::Identify(identify::Event::Received {
peer_id,
info,
..
})) => {
for addr in info.listen_addrs {
swarm.behaviour_mut().kad.add_address(&peer_id, addr);
}
}
_ => {}
}
The exact generated BehaviourEvent enum name depends on the derive macro output and the containing behaviour name. Adjust match paths to the actual compiler-generated event type.
Kademlia DHT
Use kad::Behaviour for:
- Peer discovery and routing.
- Provider records: “peer X can provide content key Y.”
- Record get/put operations.
- Interop with IPFS Kademlia when configured for the IPFS protocol name.
Common setup:
let local_peer_id = key.public().to_peer_id();
let store = kad::store::MemoryStore::new(local_peer_id);
let behaviour = kad::Behaviour::new(local_peer_id, store);
Custom config example, useful for IPFS DHT interop:
use libp2p::swarm::StreamProtocol;
const IPFS_PROTO_NAME: StreamProtocol = StreamProtocol::new("/ipfs/kad/1.0.0");
let mut cfg = kad::Config::new(IPFS_PROTO_NAME);
cfg.set_query_timeout(std::time::Duration::from_secs(5 * 60));
let store = kad::store::MemoryStore::new(local_peer_id);
let kad = kad::Behaviour::with_config(local_peer_id, store, cfg);
Practical Kademlia calls:
swarm.behaviour_mut().kad.bootstrap()?;
swarm.behaviour_mut().kad.add_address(&peer_id, addr);
swarm.behaviour_mut().kad.get_closest_peers(peer_id);
swarm.behaviour_mut().kad.get_providers(key);
swarm.behaviour_mut().kad.start_providing(key)?;
Gotchas:
- Identify is not automatic. Hook
identify::Event::Receivedtokad.add_address. - Without Identify or another peer discovery source, Kad may not discover beyond bootnodes.
- For provider records/content routing, make sure the node is configured for the intended mode and reachable enough for the network’s expectations.
- IPFS public DHT interop often needs RSA identity support and
/ipfs/kad/1.0.0.
Gossipsub
Use gossipsub::Behaviour for pub/sub.
Common setup:
let behaviour = gossipsub::Behaviour::new(
gossipsub::MessageAuthenticity::Signed(key.clone()),
gossipsub::Config::default(),
)?;
Topic example:
let topic = gossipsub::IdentTopic::new("chat");
swarm.behaviour_mut().gossipsub.subscribe(&topic)?;
swarm.behaviour_mut().gossipsub.publish(topic, b"hello".to_vec())?;
Handle messages:
match event {
gossipsub::Event::Message {
propagation_source,
message_id,
message,
} => {
println!(
"Got message {message_id} from {propagation_source}: {:?}",
String::from_utf8_lossy(&message.data)
);
}
_ => {}
}
Gotchas:
- Gossipsub does not do peer discovery. Combine it with mDNS, Kademlia, Rendezvous, bootstrap peers, or explicit peer dialing.
- Topic hashing behavior is configurable. Rust defaults differ from some implementations when
hash_topicsis enabled. - For production networks, configure validation mode and peer scoring deliberately. Do not leave validation and scoring as an afterthought unless the application is a toy, which, fair enough, many are.
Request-response
Use request_response::Behaviour for request/response protocols where each request is sent over a new substream.
Options:
- Implement
request_response::Codecyourself. - Use predefined
request_response::cbor::Behaviourif request/response types implement serde andcborfeature is enabled. - Use predefined
request_response::json::Behaviourifjsonfeature is enabled.
Core API:
let request_id = swarm
.behaviour_mut()
.request_response
.send_request(&peer_id, request);
swarm
.behaviour_mut()
.request_response
.send_response(channel, response)?;
Events arrive as request_response::Event::Message with request_response::Message::{Request, Response}.
Use request-response for:
- RPC-like interactions.
- File chunk fetching.
- Metadata queries.
- One-shot application messages where pub/sub is the wrong tool.
Do not use it for long-lived streaming. Use custom streams or a protocol built for streaming.
Ping
ping::Behaviour measures liveness/RTT and emits ping events. It is useful for diagnostics but does not keep a connection alive forever by itself in a minimal node.
The default idle connection timeout can close otherwise-unused connections. Set a larger idle timeout in examples where Ping is the only active behaviour:
.with_swarm_config(|cfg| {
cfg.with_idle_connection_timeout(std::time::Duration::from_secs(60))
})
The upstream tutorial uses a very large timeout so users can observe pings indefinitely. Do not blindly copy that into production.
mDNS
Use mdns::tokio::Behaviour for local network discovery on native Tokio builds.
Typical pattern:
- Enable
mdns,tokio, andmacros. - Compose
mdns::tokio::Behaviourinto your root behaviour. - On
mdns::Event::Discovered, add discovered peers to the relevant behaviour, for examplegossipsub.add_explicit_peerorkad.add_address. - On
mdns::Event::Expired, remove explicit peers if appropriate.
mDNS is LAN-only. It does not discover peers across the internet.
Rendezvous
Use rendezvous for peer registration/discovery around a rendezvous server. It is useful when:
- You control rendezvous points.
- Peers cannot rely on global DHT discovery.
- You want application-scoped discovery.
Rendezvous complements Kademlia or can replace it in controlled networks.
Relay, AutoNAT, DCUtR, UPnP
rust-libp2p has a NAT traversal suite:
| Capability | Crate/feature | Use |
|---|---|---|
| Circuit Relay v2 | relay |
Reach peers via public relay nodes |
| AutoNAT | autonat |
Detect whether the node is publicly reachable |
| DCUtR | dcutr |
Upgrade relayed connections to direct connections via hole punching |
| UPnP | upnp |
Ask local router to map ports |
Relay address shape:
/ip4/<relay-ip>/tcp/<relay-port>/p2p/<relay-peer-id>/p2p-circuit/p2p/<dest-peer-id>
Relay client setup uses with_relay_client(...) and requires embedding the relay client behaviour in your root behaviour.
DCUtR generally requires:
- Relay connectivity first.
- Identify, so peers can exchange observed/listen addresses.
- A relay client behaviour.
- Direct transports configured, commonly TCP and/or QUIC.
- Patience with NAT reality, the universe’s least charming firewall ruleset.
UPnP is native-only and only helps when the local router supports it. It is not available to browsers.
Metrics and observability
Enable metrics to collect protocol/swarm metrics.
Common options:
with_bandwidth_metrics(&mut registry)wraps the transport with bandwidth metrics.libp2p-metricsrecords protocol and swarm events and exposes OpenMetrics-compatible metrics viaprometheus-client.
Use metrics for production services, relay nodes, and debugging peer churn.
Connection limits and allow/block lists
The root crate re-exports:
allow_block_list: manage allow/block lists for peers.connection_limits: connection count/limit utilities.memory_connection_limits: memory-aware limits on native builds.
Use these when building public-facing nodes, relays, or high-churn DHT/pubsub services.
Browser and WASM notes
Rust-libp2p has WASM/browser transports behind *-websys feature flags:
webrtc-websyswebsocket-websyswebtransport-websyswasm-bindgen
Do not use native tcp, dns, quic, websocket, uds, or upnp builder paths on wasm32; they are target-gated out. Browser networking has platform constraints, certificate constraints, and event-loop constraints. Treat browser examples separately from native Tokio examples.
For browser-focused libp2p answers, cross-check the current WASM examples and transport crates. The Rust WASM implementation is not a drop-in translation of js-libp2p config.
Source layout navigation
When source-checking:
- Root re-exports and feature gates:
libp2p/src/lib.rs,libp2p/Cargo.toml. - Builder:
libp2p/src/builder.rsandlibp2p/src/builder/phase/*.rs. - Swarm:
swarm/src/lib.rs. - Behaviour trait:
swarm/src/behaviour.rs. - Handler trait:
swarm/src/handler.rs. - Connection pool:
swarm/src/connection/pool.rs. - Transports:
transports/*/src/lib.rs. - Protocols:
protocols/*/src/lib.rs. - Examples:
examples/*. - Ping tutorial:
libp2p/src/tutorials/ping.rs.
Example applications in the repo
Use these examples as source-backed patterns:
| Example | Demonstrates |
|---|---|
examples/ping |
Minimal SwarmBuilder + TCP + Noise + Yamux + Ping |
examples/chat |
Gossipsub chat |
examples/file-sharing |
Kademlia provider records + request-response file fetching |
examples/ipfs-kad |
IPFS Kademlia interoperability and bootstrapping |
examples/dcutr |
Relay + DCUtR hole punching |
examples/relay-server |
Running a relay server |
examples/autonat, examples/autonatv2 |
Reachability detection |
examples/rendezvous |
Rendezvous protocol |
examples/identify |
Identify protocol |
examples/metrics |
Metrics collection |
examples/upnp |
Router port mapping |
examples/browser-webrtc |
Browser WebRTC/WASM pattern |
examples/stream |
Raw stream protocol example |
Common mistakes
- Forgetting Cargo features, then wondering why modules do not exist.
- Using
libp2p::NetworkBehaviourinstead oflibp2p::swarm::NetworkBehaviourfor the derive macro. - Forgetting the
macrosfeature for#[derive(NetworkBehaviour)]. - Not polling the
Swarm. - Assuming Identify automatically feeds Kademlia.
- Assuming Gossipsub discovers peers by itself.
- Adding QUIC and then also trying to wrap it in Noise/Yamux.
- Using browser transports in native examples, or native transports in WASM examples.
- Using
mplexin new code when Yamux is the recommended muxer. - Relying on Ping to keep a connection open without adjusting idle timeout or having an actual application protocol.
- Advertising private or unroutable addresses as external addresses.
- Assuming relay traffic is invisible to the relay. Payloads are end-to-end encrypted, but relay peer IDs, timing, and connection metadata are observable.
Answering checklist
When answering rust-libp2p questions:
- Identify target environment: native Tokio, WASM/browser, tests, or embedded/server.
- Identify required protocols: discovery, pub/sub, request-response, DHT, NAT traversal, raw streams.
- List the Cargo features required.
- Prefer
SwarmBuilderunless the user is writing a custom transport/protocol. - Use
#[derive(NetworkBehaviour)]for app-level composition. - Include the event loop.
- Mention Identify wiring when using Kademlia or address discovery.
- Mention discovery requirements when using Gossipsub.
- For NAT traversal, include relay, Identify, AutoNAT/DCUtR, and direct transports.
- Warn about target-gated transports and version/API drift.
- For exact APIs, cite or inspect docs.rs/source for the current version.
Quick recipes
Native TCP + Noise + Yamux
Features:
["tcp", "tokio", "noise", "yamux"]
Builder:
.with_tokio()
.with_tcp(tcp::Config::default(), noise::Config::new, yamux::Config::default)?
Native TCP + QUIC
Features:
["tcp", "quic", "tokio", "noise", "yamux"]
Builder:
.with_tokio()
.with_tcp(tcp::Config::default(), noise::Config::new, yamux::Config::default)?
.with_quic()
TCP + DNS + WebSocket
Features:
["tcp", "dns", "websocket", "tokio", "noise", "yamux"]
Builder:
.with_tokio()
.with_tcp(tcp::Config::default(), noise::Config::new, yamux::Config::default)?
.with_dns()?
.with_websocket(noise::Config::new, yamux::Config::default).await?
DHT + Identify
Features:
["kad", "identify", "macros", "tcp", "tokio", "noise", "yamux"]
Pattern:
- Compose both behaviours.
- On Identify received events, call
kad.add_address(&peer_id, addr)for listen addresses. - Add bootstrap peer addresses explicitly.
- Call
kad.bootstrap()after bootstrap peers are in the routing table.
Pub/sub
Features:
["gossipsub", "identify", "mdns", "macros", "tcp", "tokio", "noise", "yamux"]
Pattern:
- Compose Gossipsub with mDNS and/or Kademlia/Rendezvous.
- Subscribe to topics.
- Add explicit peers or rely on discovered/dialed peers.
- Configure validation and scoring for production.
Request/response with CBOR
Features:
["request-response", "cbor", "macros", "tcp", "tokio", "noise", "yamux"]
Pattern:
- Define serde request and response types.
- Use
request_response::cbor::Behaviour. - Send with
send_request. - Respond with
send_responseusing the response channel from inbound request events.
Relay client
Features:
["relay", "macros", "tcp", "tokio", "noise", "yamux"]
Pattern:
- Add
.with_relay_client(...). - Include relay behaviour in the root behaviour.
- Listen or dial relayed multiaddrs containing
/p2p-circuit. - Add Identify and DCUtR for hole punching.
Reference links
- DeepWiki rust-libp2p: https://deepwiki.com/libp2p/rust-libp2p
- GitHub repository: https://github.com/libp2p/rust-libp2p
- docs.rs
libp2p: https://docs.rs/libp2p/latest/libp2p/ - crates.io
libp2p: https://crates.io/crates/libp2p - Official libp2p docs: https://docs.libp2p.io/
Source: chanderlud/telepathy — distributed by TomeVault.
先判断是否适合
作者设计意图
作者的方法与取舍
边界和复核