Rust网络库sc-network-gossip的使用:实现高效P2P网络通信与去中心化消息传播

以下是基于您提供的内容整理的完整示例代码:

use sc_network_gossip::{GossipEngine, Network, Validator, ConsensusEngineId, ValidatorContext, ValidationResult};
use sp_runtime::traits::Block as BlockT;
use sc_network::PeerId;

// 1. 实现Network trait
struct MyNetwork;
impl<B: BlockT> Network<B> for MyNetwork {
    fn report_peer(&self, _who: PeerId, _cost_benefit: sc_network::ReputationChange) {
        // 实现peer报告逻辑
    }
    
    fn disconnect_peer(&self, _who: PeerId) {
        // 实现断开peer连接逻辑
    }
    
    // 其他必要的方法实现...
}

// 2. 实现Validator trait
struct MyValidator;
impl<B: BlockT> Validator<B> for MyValidator {
    fn validate(
        &self,
        context: &mut dyn ValidatorContext<B>,
        sender: &PeerId,
        data: &[u8],
    ) -> ValidationResult<B> {
        // 验证消息内容
        if data.len() > 1024 {
            // 消息过大,拒绝处理
            return ValidationResult::Discard;
        }
        
        // 处理有效消息
        println!("Received message from {}: {:?}", sender, data);
        
        // 保留消息并继续传播
        ValidationResult::ProcessAndKeep
    }

    fn message_expired<'a>(&'a self) -> Box<dyn FnMut(B::Hash, &[u8]) -> bool + 'a> {
        Box::new(move |_topic, _data| {
            // 实现消息过期逻辑
            false // 这里示例中消息永不过期
        })
    }

    fn message_allowed<'a>(
        &'a self,
    ) -> Box<dyn FnMut(&PeerId, B::Hash, &[u8]) -> bool + 'a> {
        Box::new(move |who, _topic, _data| {
            // 实现消息允许发送的逻辑
            // 这里示例中允许发送给所有节点
            true
        })
    }
}

fn main() {
    // 3. 选择共识引擎ID (4字节标识符)
    let engine_id = ConsensusEngineId::new(*b"DEMO");
    
    // 4. 构建GossipEngine
    let network = MyNetwork;
    let validator = MyValidator;
    let gossip_engine = GossipEngine::new(
        Box::new(network),
        Box::new(validator),
        engine_id,
    );
    
    // 5. 使用GossipEngine
    // 创建主题(32字节)
    let topic = [1u8; 32]; 
    
    // 广播主题
    gossip_engine.broadcast_topic(topic, false);
    
    // 发送消息
    let message = b"This is a test message for P2P network";
    gossip_engine.gossip_message(topic, message.to_vec());
    
    // 发送给特定peer
    let target_peer = PeerId::random();
    gossip_engine.send_topic(
        &target_peer,
        topic,
        b"Private message".to_vec(),
        false,
    );
}

这个完整示例展示了如何:

  1. 实现一个基本的Network trait,提供底层网络功能
  2. 实现Validator trait来处理消息验证、过期检查和发送权限
  3. 创建自定义的共识引擎ID
  4. 初始化GossipEngine并使用它进行消息广播和定向发送

关键点说明:

  • 消息主题是32字节的任意标识符
  • 共识引擎ID是4字节的协议标识符
  • Validator决定了如何处理传入消息和哪些节点可以接收消息
  • 示例包含了广播和定向发送两种消息传播方式

1 回复

Rust网络库sc-network-gossip的使用:实现高效P2P网络通信与去中心化消息传播

完整示例demo

以下是一个完整的sc-network-gossip使用示例,包含了消息广播和接收的基本功能:

use sc_network_gossip::{GossipEngine, Config, Validator, ValidationResult, TopicNotification};
use sc_network_common::service::NetworkService;
use sp_runtime::traits::Block;
use futures::StreamExt;
use libp2p::PeerId;
use std::sync::Arc;

// 自定义消息验证器
struct MyMessageValidator;

impl Validator for MyMessageValidator {
    fn validate(
        &self,
        _sender: &PeerId,
        data: &[u8],
    ) -> ValidationResult<TopicNotification> {
        // 只接受长度小于1KB的消息
        if data.len() > 1024 {
            ValidationResult::Discard
        } else {
            ValidationResult::ProcessAndKeep(TopicNotification {
                message: data.to_vec(),
                topic: b"my_app_topic".to_vec(),
            })
        }
    }
}

#[tokio::main]
async fn main() {
    // 1. 创建网络服务 (实际使用时需要配置更多参数)
    let network_service = Arc::new(NetworkService::new(
        Default::default(),
        Default::default(),
        Default::default(),
        None,
    ));

    // 2. 配置gossip引擎
    let gossip_config = Config {
        topic: b"my_app_topic".to_vec(),
        ..Default::default()
    };

    // 3. 创建gossip引擎
    let gossip_engine = GossipEngine::new(
        network_service.clone(),
        gossip_config
    );

    // 注册自定义验证器
    let validator = Box::new(MyMessageValidator);
    gossip_engine.register_validator(b"my_app_topic".to_vec(), validator);

    // 启动消息处理任务
    tokio::spawn({
        let gossip_engine = gossip_engine.clone();
        async move {
            // 4. 接收消息
            let mut message_stream = gossip_engine.messages_for(b"my_app_topic");
            while let Some(message) = message_stream.next().await {
                println!("收到消息: {:?}", message);
            }
        }
    });

    // 5. 广播消息
    for i in 0..5 {
        let message = format!("测试消息 {}", i).into_bytes();
        gossip_engine.gossip_message(message);
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    }

    // 6. 给特定peer发送消息
    let peers = gossip_engine.peers();
    if !peers.is_empty() {
        let target_peer = peers[0].clone();
        gossip_engine.send_message(
            MessageIntent::Broadcast,
            target_peer,
            b"私有消息".to_vec()
        );
    }

    // 保持程序运行
    tokio::signal::ctrl_c().await.unwrap();
}

代码说明

  1. 网络服务初始化:创建基本的网络服务实例,这是gossip引擎的基础
  2. Gossip引擎配置:设置消息主题等基本参数
  3. 自定义验证器:实现Validator trait来过滤和验证收到的消息
  4. 消息接收:使用异步流处理接收到的消息
  5. 消息广播:向整个网络广播消息
  6. 定向发送:向特定对等节点发送消息

使用建议

  1. 在实际项目中,需要更完善的网络服务配置
  2. 根据业务需求调整消息验证逻辑
  3. 考虑使用多个主题来分类不同类型的消息
  4. 对于生产环境,建议实现更完善的错误处理和日志记录

这个示例展示了sc-network-gossip的基本用法,包括消息的发送、接收和验证。根据实际需求,可以在此基础上扩展更多功能。

回到顶部