You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Rust rust-libp2p向IPFS DHT插入/pk类型记录?

核心错误原因

  • 键格式错误:你的Rust代码中/pk/后缀拼接的是PeerID的原始二进制字节,而IPFS DHT规范要求/pk/记录的键后缀是PeerID的base58编码字符串,和Go代码的处理逻辑一致。
  • 值格式错误:你使用into_protobuf_encoding()输出的是libp2p公钥的protobuf封装格式,而IPFS /pk记录要求值为公钥的原始二进制编码,和Go代码中GetPublic().Bytes()的输出一致。
  • Kademlia配置不兼容IPFS DHT:rust-libp2p默认的Kademlia协议标识不是IPFS公共DHT使用的/ipfs/kad/1.0.0,且未开启对应记录校验规则,同时你提交的Record中publisher字段留空,IPFS节点会拒绝存储无发布者签名的记录。
  • Quorum配置不合理:IPFS公共DHT写入至少需要Quorum::Majority才能保证写入成功。

可用演示代码

use libp2p::{
    identity,
    kad::{Kademlia, KademliaConfig, Record, Key, Quorum, store::MemoryStore},
    multiaddr::Protocol,
    swarm::{Swarm, SwarmEvent},
    PeerId, Transport,
    tcp::TcpConfig,
    noise::NoiseConfig,
    yamux::YamuxConfig,
};
use std::error::Error;
use base58::ToBase58;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 生成本地密钥对
    let local_key = identity::Keypair::generate_ed25519();
    let local_peer_id = PeerId::from(local_key.public());
    println!("本地节点ID: {local_peer_id}");

    // 构建传输层
    let transport = TcpConfig::new()
        .upgrade(libp2p::core::upgrade::Version::V1)
        .authenticate(NoiseConfig::xx(&local_key).into_authenticated())
        .multiplex(YamuxConfig::default())
        .boxed();

    // 配置Kademlia为IPFS公共DHT兼容模式
    let mut kad_config = KademliaConfig::default();
    kad_config.set_protocol_name(&b"/ipfs/kad/1.0.0"[..]);
    kad_config.set_record_ttl(Some(std::time::Duration::from_secs(48 * 3600)));
    kad_config.set_publication_interval(Some(std::time::Duration::from_secs(12 * 3600)));
    let store = MemoryStore::new(local_peer_id);
    let mut kademlia = Kademlia::with_config(local_peer_id, store, kad_config);

    // 接入IPFS公共DHT引导节点
    let bootstrap_peer_id: PeerId = "QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN".parse()?;
    let bootstrap_addr = "/ip4/104.131.131.82/tcp/4001".parse()?;
    kademlia.add_address(&bootstrap_peer_id, bootstrap_addr);
    kademlia.bootstrap()?;

    // 构建Swarm
    let mut swarm = Swarm::new(transport, kademlia, local_peer_id);
    swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;

    // 等待引导完成
    loop {
        match swarm.select_next_some().await {
            SwarmEvent::Behaviour(libp2p::kad::KademliaEvent::BootstrapResult(Ok(_))) => {
                println!("DHT引导完成");
                break;
            }
            SwarmEvent::Behaviour(libp2p::kad::KademliaEvent::BootstrapResult(Err(e))) => {
                eprintln!("引导失败: {e}");
                return Ok(());
            }
            _ => {}
        }
    }

    // 构造符合规范的/pk记录
    let peer_id_b58 = local_peer_id.to_base58();
    let key = Key::from(format!("/pk/{peer_id_b58}").into_bytes());
    // 取公钥原始编码,不是protobuf封装格式
    let value = match &local_key.public() {
        identity::PublicKey::Ed25519(pk) => pk.to_bytes().to_vec(),
        identity::PublicKey::Secp256k1(pk) => pk.to_bytes().to_vec(),
        _ => unimplemented!("仅支持ed25519/secp256k1公钥"),
    };

    // 提交记录
    let record = Record {
        key: key.clone(),
        value,
        publisher: Some(local_peer_id),
        expires: None,
    };
    swarm.behaviour_mut().put_record(record, Quorum::Majority)?;
    println!("已提交/pk记录写入请求");

    // 等待写入结果
    loop {
        match swarm.select_next_some().await {
            SwarmEvent::Behaviour(libp2p::kad::KademliaEvent::PutRecordResult(Ok(res))) => {
                println!("写入成功,成功存储节点数: {}", res.successes.len());
                break;
            }
            SwarmEvent::Behaviour(libp2p::kad::KademliaEvent::PutRecordResult(Err(e))) => {
                eprintln!("写入失败: {e}");
                break;
            }
            _ => {}
        }
    }

    Ok(())
}

依赖配置(Cargo.toml)

[dependencies]
libp2p = { version = "0.39.1", features = ["tcp", "noise", "yamux", "kad"] }
tokio = { version = "1.0", features = ["full"] }
base58 = "0.2.0"

内容的提问来源于stack exchange,提问作者fygesser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 16:15:02