通信密钥 noise::{Keypair, X25519Spec}
- X25519/Ed25519类似RSA 算法。
- Noise 用于设计和实现安全通信协议。它允许通信双方
在没有预先共享密钥的情况下进行安全的密钥交换
,并通过加密和身份验证保护通信内容。libp2p
提供了对 Noise 协议的原生支持,它允许节点之间使用 Noise 协议进行安全的点对点通信。 - 例:
use libp2p::{noise::{Keypair, X25519Spec},identity,};
, let local_keys = Keypair::<X25519Spec>::new().into_authentic(&identity::Keypair::generate_ed25519());
identity::Keypair
- 在
libp2p
中,identity::Keypair
是一个用于管理加密和身份验证密钥的结构体。它允许你生成和管理加密算法(如椭圆曲线加密)所需的公钥和私钥对,以及进行数字签名和验证等操作。 - 下面是一个简单的示例,展示如何使用
Keypair
生成一个 Ed25519
算法的密钥对,并使用它进行签名和验证:
use libp2p::identity::{Keypair, ed25519};
fn main() {
let keypair = Keypair::generate_ed25519();
let public_key = keypair.public();
let private_key = keypair.secret();
let message = b"Hello, libp2p!";
let signature = keypair.sign(message);
assert!(public_key.verify(message, &signature).is_ok());
println!("Message: {:?}", message);
println!("Signature: {:?}", signature);
}
transport
- 传输在两个对等方之间提供面向连接的通信 通过有序的数据流(即连接)
- 负责从一个peer到另一个peer的实际数据的传输
- 收听和拨号
- 例如使用
let transport = libp2p::development_transport(local_keys).await?;
调用libp2p提供的高级API函数development_transport来创建传输。这个函数封装了传输的创建过程,通常会使用一组默认的配置参数和最佳实践,以便快速启动和测试libp2p应用程序。在这种情况下,local_keys是本地密钥,用于加密和身份验证。有关这个API的未来发展可以看这个ISSUE。 - 还可以手动配置和创建传输(transport)。下面的例子使用了TokioTcpConfig作为基础的TCP传输配置,手动指定了协议升级、身份认证和多路复用的配置。这种方式适用于需要精确控制传输行为和配置的场景,允许开发者根据具体需求进行灵活的设置和调整。
//Creates transport which is a feature of the lib p2p framework
let transport = TokioTcpConfig::new()
//Upgrades version of the transport once connection is established as Version 1 of the multi-stream-select protocol is the version that interacts with the noise protocol
//in short handles protocol negotiation
.upgrade(upgrade::Version::V1)
//Authenticates that channel is secure with the noise XX handshake
.authenticate(libp2p::noise::NoiseConfig::xx(auth_keys).into_authenticated())
//multiplex transport negotiates multiple sub-streams and/or connections on the authenticated transport
.multiplex(mplex::MplexConfig::new())
//boxed allows only output and error types to be captured
.boxed();
行为控制 Swarm
- Swarm 包含整个网络的状态。运行一组节点并管理它们之间的连接和行为。整个 libp2p 网络的行为可以通过其进行控制。
- 例子
extern crate core;
use libp2p::{
futures::StreamExt,
noise::{Keypair, NoiseConfig, X25519Spec},
identity,
PeerId,
tcp::TcpConfig,
swarm::{DummyBehaviour,Swarm,SwarmEvent},
};
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let local_keys = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_keys.public());
println!("local_peer_id is {:?}",local_peer_id);
let behaviour = DummyBehaviour::default();
let transport = libp2p::development_transport(local_keys).await?;
let mut swarm = {
Swarm::new(transport, behaviour, local_peer_id)
};
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
loop {
match swarm.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => {
println!("Listening on local address {:?}", address)
}
_ => {}
}
}
Ok(())
}
local_peer_id is PeerId("12D3KooWD4BMTXhmTV46fSbdRv238dRudXcXq9VPSF1PH4N4nWVk")
Listening on local address "/ip4/192.168.0.102/tcp/51516"
Listening on local address "/ip4/127.0.0.1/tcp/51516"
local_peer_id is PeerId("12D3KooWJRoPgqPPC8adBwrFHfx4XtCpCu1BprzBofgVirxoceJB")
Listening on local address "/ip4/192.168.0.102/tcp/51519"
Listening on local address "/ip4/127.0.0.1/tcp/51519"
在 peer 节点之间交换 ping 命令
use libp2p::futures::StreamExt; // 异步流有关
use libp2p::ping::{Ping, PingConfig};// ping 命令相关依赖
use libp2p::swarm::{Swarm, SwarmEvent};
use libp2p::{identity, Multiaddr, PeerId};
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let new_key = identity::Keypair::generate_ed25519();
let new_peer_id = PeerId::from(new_key.public());
println!("New Peer ID is: {:?}", new_peer_id);
let transport = libp2p::development_transport(new_key).await?;
let behaviour = Ping::new(PingConfig::new().with_keep_alive(true));
let mut swarm = Swarm::new(transport, behaviour, new_peer_id);
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
// 本地节点向远程节点发出连接 从命令行输入的参数取出
if let Some(remote_peer) = std::env::args().nth(1) {
let remote_peer_multiaddr: Multiaddr = remote_peer.parse()?;
swarm.dial(remote_peer_multiaddr)?;// 需要libp2p ,version = "0.46"
println!("Dialed remote peer: {:?}", remote_peer); // 打印远程地址
}
loop {
match swarm.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => {
println!("Listening on local Address {:?}", address)
}
SwarmEvent::Behaviour(event) => println!("Event received from peer is {:?}", event),
_ => {}
}
}
}
PS C:\Users\kingchuxing\Documents\CODE\P2PRecipeApp> cargo run
New Peer ID is: PeerId("12D3KooWFR97CdrL7jvboqU6MxyWjRzfHsR5V2sgs23yqg4xetnV")
Listening on local Address "/ip4/192.168.0.102/tcp/50997"
Listening on local Address "/ip4/127.0.0.1/tcp/50997"
PS C:\Users\kingchuxing\Documents\CODE\P2PRecipeApp> cargo run /ip4/192.168.0.102/tcp/50997
New Peer ID is: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG")
Dialed remote peer: "/ip4/192.168.0.102/tcp/50997" //对远程地址进行了拨号
Listening on local Address "/ip4/192.168.0.102/tcp/51014"
Listening on local Address "/ip4/127.0.0.1/tcp/51014"
Event received from peer is Event { peer: PeerId("12D3KooWFR97CdrL7jvboqU6MxyWjRzfHsR5V2sgs23yqg4xetnV"), result: Ok(Pong) }
Event received from peer is Event { peer: PeerId("12D3KooWFR97CdrL7jvboqU6MxyWjRzfHsR5V2sgs23yqg4xetnV"), result: Ok(Ping { rtt: 314.3µs }) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Pong) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Ping { rtt: 250.7µs }) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Pong) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Ping { rtt: 319.7µs }) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Pong) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Ping { rtt: 479.6µs }) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Pong) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Ping { rtt: 217.8µs }) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Pong) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Ping { rtt: 266.7µs }) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Pong) }
Event received from peer is Event { peer: PeerId("12D3KooWMGLjRBpysfHqjYWcYPf89bDNWH4S9Ao8RXj5tBehksCG"), result: Ok(Ping { rtt: 1.0212ms }) }
mdns发现peer
- 在计算机网络中,mDNS (Multicast DNS) 是一种用于在局域网内部广播和发现服务的协议。它允许设备在没有集中式DNS服务器的情况下相互发现和通信,特别是在没有预先配置的情况下。
use libp2p::{
futures::StreamExt,
identity,
mdns::{Mdns, MdnsConfig, MdnsEvent},
swarm::{Swarm, SwarmEvent},
PeerId,
};
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let new_key = identity::Keypair::generate_ed25519();
let new_peer_id = PeerId::from(new_key.public());
println!("New Peer ID is: {:?}", new_peer_id);
let transport = libp2p::development_transport(new_key).await?;
let behaviour = Mdns::new(MdnsConfig::default()).await?;
let mut swarm = Swarm::new(transport, behaviour, new_peer_id);
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
loop {
match swarm.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => {
println!("Listening on local Address {:?}", address)
}
SwarmEvent::Behaviour(MdnsEvent::Discovered(peers)) => {
for (peer, addr) in peers {
println!("discovered {} {}", peer, addr);
}
}
SwarmEvent::Behaviour(MdnsEvent::Expired(expired)) => {
for (peer, addr) in expired {
println!("expired {} {}", peer, addr);
}
}
_ => {}
}
}
}
PS C:\Users\kingchuxing\Documents\CODE\P2PRecipeApp> cargo run
New Peer ID is: PeerId("12D3KooWMU94yU8ZAFnPdRwLyQ9FuR47sVQfMG9VJUiiykCvmYdt")
Listening on local Address "/ip4/192.168.0.102/tcp/51361"
Listening on local Address "/ip4/127.0.0.1/tcp/51361"
discovered 12D3KooWNMofXEV4fp5NCEBF3m7km3keRnAuScrhoKqvc5Jiacy9 /ip4/192.168.0.102/tcp/51360
discovered 12D3KooWNMofXEV4fp5NCEBF3m7km3keRnAuScrhoKqvc5Jiacy9 /ip4/127.0.0.1/tcp/51360
PS C:\Users\kingchuxing\Documents\CODE\P2PRecipeApp> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s
Running `target\debug\P2PRecipeApp.exe`
New Peer ID is: PeerId("12D3KooWNMofXEV4fp5NCEBF3m7km3keRnAuScrhoKqvc5Jiacy9")
Listening on local Address "/ip4/192.168.0.102/tcp/51360"
Listening on local Address "/ip4/127.0.0.1/tcp/51360"
discovered 12D3KooWMU94yU8ZAFnPdRwLyQ9FuR47sVQfMG9VJUiiykCvmYdt /ip4/192.168.0.102/tcp/51361
discovered 12D3KooWMU94yU8ZAFnPdRwLyQ9FuR47sVQfMG9VJUiiykCvmYdt /ip4/127.0.0.1/tcp/51361
CG
- Swarm部分相关代码来自教程使用 Async Rust 构建简单的 P2P 节点【完结】