p2p、分布式,区块链笔记: libp2p基础

通信密钥 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() {// 生成一个 Ed25519 类型的密钥对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 frameworklet 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 网络的行为可以通过其进行控制。
  • 例子
// https://stackoverflow.com/questions/74126811/rust-libp2p-cannot-find-function-development-transport-in-crate-libp2p
extern crate core;// 显式地声明对 core crate(包含Rust核心标准库)的依赖。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();// 从公钥生成peeridlet local_peer_id = PeerId::from(local_keys.public());println!("local_peer_id is {:?}",local_peer_id);// 采用“默认”行为let behaviour = DummyBehaviour::default();// 创建 libp2p transport实现peer间的数据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()?)?;// 本机中所有的IPV4地址,使用 TCP 协议,端口号为 0 表示让操作系统自动选择一个空闲端口来监听.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 }) } 
  • 后续两个peer之间会不断的ping和pang
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); // 创建Swarmswarm.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 runFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.28sRunning `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 节点【完结】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/37681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20、PHP字符串的排列(含源码)

题目&#xff1a; PHP字符串的排列&#xff1f; 描述&#xff1a; 输入一个字符串,按字典序打印出该字符串中字符的所有排列。 例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 输入描述&#xff1a; 输入一个字符串,长度不超过9(可…

尺度函数在图像处理中的应用与优化

尺度函数在图像处理中的应用与优化 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨尺度函数在图像处理中的应用与优化。尺度函数是图像处理中…

spring快速上手

一、基础概念 1.使用spring后&#xff0c;被spring管理的类&#xff0c;不需要再new。 2.要想类被spring管理&#xff0c;则需要通过bean的方式&#xff0c;把类引入到spirng的配置文件中。 二、导入spring框架 导入spring依赖 <properties><maven.compiler.sourc…

2-requests模块(6节课学会爬虫)

2-requests模块&#xff08;6节课学会爬虫&#xff09; 1&#xff0c;安装requests2&#xff0c;发送get&#xff0c;post请求&#xff0c;获取响应3&#xff0c;response的方法方法一&#xff08;Response.text&#xff09;方法二&#xff08;response.content.decode()&#…

Docker 查看源地址/仓库地址,更改

一、源地址文件配置路径。若有docker文件夹&#xff0c;没有json&#xff0c;可以新增&#xff0c;复制进去内容 /etc/docker/daemon.json {"registry-mirrors": ["https://dockerhub.azk8s.cn","https://hub-mirror.c.163.com"&#xff0c;&q…

JWT权限验证

在Web开发中&#xff0c;用户认证和授权是确保系统安全和数据安全的关键环节。随着前后端分离、微服务架构等技术的普及&#xff0c;传统的基于session的用户认证机制已经很难去满足现代Web应用的需求。JWT&#xff08;JSON Web Tokens&#xff09;作为一种轻量级的认证和授权机…

【数据分析】1、用Pandas计算数据相关性系数

相关性系数和相关分析是了解变量之间关系的重要工具。通过合理选择相关性系数和科学分析数据&#xff0c;能够有效揭示变量之间的关系&#xff0c;为进一步研究和决策提供有力支持。在实际应用中&#xff0c;应结合业务背景、数据特性和统计原则&#xff0c;谨慎解释和应用相关…

物联网相关

因为收藏夹上限了&#xff0c;所以只能这个帖子来记录物联网相关得文章了。 链接: 搭建自己的MQTT服务器、实现设备上云(WindowsEMQX) 链接: Windows系统下本地MQTT服务器搭建&#xff08;保姆级教程&#xff09;

【小学期】常用基于Swing的七个静态界面

示例1&#xff1a;基本的带按钮和标签的界面 import javax.swing.*; import java.awt.*;public class SimpleSwingApp1 {public static void main(String[] args) {JFrame frame new JFrame("Simple Swing App 1");frame.setDefaultCloseOperation(JFrame.EXIT_ON_C…

【linux】从零到入门

linux概述 Linux是一个免费使用和自由传播的一套操作系统。用户可以无偿地得到它地源代码&#xff0c;和大量地应用程序&#xff0c;并且可以随意修改和增加它们。 Linux的内核起初由林纳斯编写。内核是啥&#xff1f; 驱动设备&#xff0c;文件系统&#xff0c;进程管理&…

UE5(c++)demo开发日志(1):Actor类添加

工具---新建c类---选用Actor&#xff0c;创造出头文件(.h&#xff0c;用于声明变量、函数、重写父类函数等)和源文件(.cpp&#xff0c;涉及到具体功能实现)&#xff0c;客户端界面成功显示出来新建类&#xff1a; Actor头文件默认方法简介&#xff1a; UCLASS(): ue提供的宏&a…

算法-位运算基础

文章目录 1. 前置知识2. 交换两个数3. 比较两个数的大小3. leetcode268 寻找缺失的数字4. leetcode136 只出现一次的数字5. leetcode260 只出现一次的数字|||6. leetcode137 只出现一次的数字||7. 2/3的幂8. 大于等于该数字的最小2的幂9. leetcode201 数字范围按位与10. 位运算…

Docker部署Dillinger个人文本编辑器

Docker部署Dillinger个人文本编辑器 一、Dillinger介绍1.1 Dillinger简介1.2 Dillinger使用场景 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、拉取Dillinger镜像五、部署Dill…

汇聚荣拼多多运营好吗?

在当前电商行业竞争激烈的背景下&#xff0c;拼多多凭借其独特的商业模式和市场定位迅速崛起&#xff0c;成为众多商家和品牌争相入驻的平台。对于“汇聚荣拼多多运营好吗?”这一问题&#xff0c;答案是肯定的。拼多多不仅提供了一个广阔的市场空间&#xff0c;还通过其创新的…

HTML5+JavaScript单词游戏

HTML5 JavaScript单词游戏 数据字典格式&#xff1a;每行一个 单词 &#xff0c;单词和解释用空格分隔&#xff0c;如 a art.一(个)&#xff1b;每一(个) ability n.能力&#xff1b;能耐&#xff0c;本领 able a.有能力的&#xff1b;出色的 baby n.婴儿&#xff1b;孩子…

数据库对比脚本,java如何对比两个数据库的表字段的不同

因为有时候开发环境和 测试环境&#xff0c;有时候会有不同的数据库表&#xff0c;比如有些加字段了&#xff0c;所以这个脚本就实现了对比两个数据库连接的数据库到底哪里不一样&#xff0c;输出到控制台 package com.junfun.pms;import lombok.extern.slf4j.Slf4j;import ja…

25届最近5年北京工业大学自动化考研院校分析

北京工业大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图表 六、初试大纲复试大纲 七、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试科目介绍 2、指定教…

C++进修——C++核心编程

内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制编码&#xff0c;由操作系统进行管理全局区&#xff1a;存放全局变量和静态变量以及常量栈区&#xff1a;由编译器自动分配释放&#xff0c;存放函数的参数值&#xff…

grpc学习golang版( 三、proto文件数据类型 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、proto语法二、proto中的标量类型三、proto中的数组类型四、p…

资料导览(持续更新)

经典推荐 多模态大模型&#xff1a;基础架构 图解DSPy&#xff1a;Prompt的时代终结者&#xff1f;&#xff01; vLLM, LMDeploy, MLC-LLM, TensorRT-LLM, and TGI的性能小实验 优雅谈大模型13&#xff1a;一文读懂LoRA/DoRA/MoRA 新鲜速递&#xff1a;图解新颖LLM的CoPE位…