ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

js-ipfs DHT API 完全指南:findPeer、findProvs、get、provide、put 与 query 实战详解

js-ipfs DHT API 完全指南:findPeer、findProvs、get、provide、put 与 query 实战详解 存储网络通信【免费下载链接】js-ipfsIPFS implementation in JavaScript项目地址https://gitcode.com/gh_mirrors/js/js-ipfs点击查看免费下载导读分布式哈希表DHTDistributed Hash Table是 IPFS 网络中节点发现、内容寻址与键值路由的核心基础设施。本文基于 js-ipfs 官方 API 文档docs/core-api/DHT.md系统讲解ipfs.dht命名空间下的六大核心方法——findPeer、findProvs、get、provide、put与query并深入 js-ipfs 源码packages/ipfs-core/src/components/dht.js与接口测试packages/interface-ipfs-core/src/dht/揭示每个方法底层如何经由 libp2p DHT 驱动帮助你在实际项目中完成节点地址解析、内容提供者发现、IPNS 记录读写等实战任务。一、DHT API 概览六大方法一览ipfs.dht暴露了完整的 DHT 路由能力全部为异步接口方法功能返回类型ipfs.dht.findPeer(peerId, [options])查询某 Peer ID 关联的所有 multiaddressAsyncIterableQueryEventipfs.dht.findProvs(cid, [options])查找能提供特定 CID 内容的节点AsyncIterableQueryEventipfs.dht.get(key, [options])根据 key 查询路由系统中的最佳值AsyncIterableQueryEventipfs.dht.provide(cid, [options])向网络宣告你正在提供某内容AsyncIterableQueryEventipfs.dht.put(key, value, [options])向路由系统写入键值对AsyncIterableQueryEventipfs.dht.query(peerId, [options])查询与给定 Peer ID / CID 最接近的节点AsyncIterableQueryEvent类型定义完整收录于 packages/ipfs-core-types/src/dht/index.ts 的API接口中。值得注意从 js-ipfs 的异步化改造开始DHT 接口统一以异步迭代器AsyncIterable的形式逐条产出查询事件这与传统的一次性Promise返回风格不同需要配合for await...of或it-drain、it-all等工具消费。1.1 事件驱动DHT 查询的返回真相类型定义中明确了 DHT 查询会产生的事件类型packages/ipfs-core-types/src/dht/index.ts#L69-L78EventTypes SENDING_QUERY | PEER_RESPONSE | FINAL_PEER | QUERY_ERROR | PROVIDER | VALUE | ADDING_PEER | DIALING_PEER而QueryEvent是一个联合类型packages/ipfs-core-types/src/dht/index.ts#L152常见事件结构SENDING_QUERY正在向某个节点发送查询PEER_RESPONSE收到节点应答携带closer更接近目标的节点、providers、record等字段FINAL_PEER找到最终目标节点携带peer: PeerInfoPROVIDER发现内容提供者携带providers: PeerInfo[]VALUE取回 DHT 中存储的值携带value: Uint8ArrayQUERY_ERROR某次查询出错携带error。这也是官方文档示例中message.type数值如1表示PEER_RESPONSE的来历。因此消费 DHT 接口返回值时正确姿势是遍历事件流并依据event.name过滤感兴趣的事件。1.2 通用选项timeout 与 signal除findProvs和provide外所有方法共享以下通用选项来自 packages/ipfs-core-types/src/utils.ts 定义的AbortOptions选项类型默认值说明timeoutNumberundefined超时时间毫秒signalAbortSignalundefined用于取消长时间运行请求的 AbortSignaltimeout由withTimeoutOption包装器统一实现源码见 packages/ipfs-core/src/components/dht.js#L181-L188 对每个方法的外层封装以及 packages/ipfs-core-utils/src/with-timeout-option.js 的实现。二、ipfs.dht.findPeer(peerId, [options])按 Peer ID 查找节点地址查询与某个 Peer ID 关联的所有 multiaddress。2.1 参数与返回名称类型说明peerIdPeerID要查找节点的 Peer ID返回Promise{ id: String, addrs: Multiaddr[] }——一个解析为id节点 ID 字符串与addrsmultiaddress 数组的对象。2.2 示例const info await ipfs.dht.findPeer(QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt) console.log(info.id.toString()) /* QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt */ info.addrs.forEach(addr console.log(addr.toString())) /* /ip4/147.75.94.115/udp/4001/quic /ip6/2604:1380:3000:1f00::1/udp/4001/quic /dnsaddr/bootstrap.libp2p.io /ip6/2604:1380:3000:1f00::1/tcp/4001 /ip4/147.75.94.115/tcp/4001 */2.3 底层原理与测试佐证在核心实现中findPeer直接委托给 libp2p 的 DHTpackages/ipfs-core/src/components/dht.js#L122-L132async * findPeer (peerIdToFind, options {}) { const { libp2p } await use(network, peerId, options) if (libp2p.dht null) { throw errCode(new Error(dht not configured), ERR_DHT_NOT_CONFIGURED) } yield * libp2p.dht.findPeer(peerIdToFind, { signal: options.signal }) }接口测试packages/interface-ipfs-core/src/dht/find-peer.js验证了三个关键行为超时选项生效timeout: 1会令操作快速中止成功路径在双节点网络中从FINAL_PEER事件提取的finalPeer.peer.id与目标节点nodeB的 ID 一致且其 multiaddrs 包含nodeB的地址失败路径查找不存在的 Peer 时不会产生FINAL_PEER事件而会产生QUERY_ERROR事件。三、ipfs.dht.findProvs(cid, [options])查找内容提供者给定 CID查找能提供该内容的节点。3.1 参数与选项名称类型说明cidCID要查找内容的 CID选项类型默认值说明numProvidersNumber20期望查找的提供者数量timeoutNumberundefined超时毫秒signalAbortSignalundefined取消信号注意若在 DHT 中找不到options.numProviders数量的提供者会抛出错误。返回AsyncIterable{ id: String, addrs: Multiaddr[] }——逐个产出提供者的 ID 与地址。3.2 示例import { CID } from multiformats/cid const providers ipfs.dht.findProvs(CID.parse(QmdPAhQRxrDKqkGPvQzBvjYe3kU8kiEEAd2J6ETEamKAD9)) for await (const provider of providers) { console.log(provider.id.toString()) }3.3 底层原理与测试佐证核心实现调用libp2p.dht.findProviders(cid, { signal })packages/ipfs-core/src/components/dht.js#L107-L117。HTTP 客户端侧则向dht/findprovs端点 POST 请求并以 NDJSON 流式消费事件packages/ipfs-http-client/src/dht/find-provs.js。接口测试packages/interface-ipfs-core/src/dht/find-provs.js演示了典型的三节点场景nodeB、nodeC先后provide同一 CIDnodeA调用findProvs后从PROVIDER事件的event.providers中收集到的 ID 必须同时包含nodeB与nodeC。四、ipfs.dht.get(key, [options])读取 DHT 键值给定 key查询路由系统中该 key 的最佳值。4.1 参数与返回名称类型说明keyUint8Array或string与目标值关联的键返回AsyncIterableQueryEvent其中的VALUE事件携带value: Uint8Array。4.2 示例const value await ipfs.dht.get(key)4.3 底层原理key 的规范化转换这是 DHT 读写链路上最值得关注的实现细节。核心代码packages/ipfs-core/src/components/dht.js#L22-L64中的toDHTKey函数对字符串 key 做严格规范化若以/ipns/开头先剥离该前缀以1ed25519 公钥或QRSA 公钥哈希开头时加z前缀并按 base58btc 解码以k开头则按 base36 解码校验 CIDv1libp2p-key前缀0x01 0x72缺失则补齐校验长度必须为 40 字节否则抛出Incorrect length错误最终重新拼接/ipns/前缀得到标准 DHT key。接口测试packages/interface-ipfs-core/src/dht/get.js验证了三种典型场景超时生效timeout: 1快速中止不存在的 key不产生VALUE事件产生QUERY_ERROR事件跨节点读取nodeA发布 IPNS 后nodeA.dht.get(/ipns/name)返回的VALUE事件值中包含所发布 CID 的字符串。五、ipfs.dht.provide(cid, [options])宣告提供内容向网络宣告你正在提供给定内容。5.1 参数与选项名称类型说明cidCID或ArrayCID要宣告提供的内容选项类型默认值说明recursivebooleanfalse为true时递归提供整个图timeoutNumberundefined超时毫秒signalAbortSignalundefined取消信号返回AsyncIterableObject——DHT 查询消息流。重要提示必须将迭代器消费至结束drain才能完成 provide 操作。5.2 示例for await (const message of ipfs.dht.provide(QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR)) { console.log(message) } /* Prints objects like: { extra: dial backoff, id: PeerId(QmWtewmnzJiQevJPSmG9s8aC7yRfK2WXTCdRc1pCbDFu6z), responses: [ { addrs: [ Multiaddr(/ip4/127.0.0.1/tcp/4001), Multiaddr(/ip4/172.20.0.3/tcp/4001), Multiaddr(/ip4/35.178.190.196/tcp/1024) ], id: PeerId(QmRz5Nth4jTFuJJKcjyb6uwvrhxWbruRvamKY2PJxwJKw8) } ], type: 1 } */也可以直接“排空”迭代器import drain from it-drain await drain(ipfs.dht.provide(QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR))5.3 底层原理与实现限制核心实现packages/ipfs-core/src/components/dht.js#L137-L157中有两个值得注意的事实本地块校验provide前会调用repo.blocks.has(cid)校验块确实存在本地否则抛出block(s) not found locally, cannot provide错误码ERR_BLOCK_NOT_FOUNDrecursive 未实现源码中recursive: true分支会抛出not implemented yet错误码ERR_NOT_IMPLEMENTED_YET——当前 js-ipfs 尚未实现递归提供整图的能力使用recursive选项需注意此限制。测试packages/interface-ipfs-core/src/dht/provide.js进一步确认提供本地不存在的 CID 会被拒绝CIDv1 与 CIDv0 均可正常提供传入非 CID 参数会报错。六、ipfs.dht.put(key, value, [options])写入 DHT 键值向路由系统写入一个键值对。6.1 参数与返回名称类型说明keyUint8Array要写入的键valueUint8Array要写入的值返回AsyncIterableObject——DHT 查询消息流结构与provide相同含extra、id、responses、type字段。6.2 示例for await (const message of ipfs.dht.put(key, value)) { console.log(message) }同样可以排空迭代器import drain from it-drain await drain(ipfs.dht.put(key, value))6.3 底层原理与测试佐证put同样经过toDHTKey规范化 key 后委托libp2p.dht.put(dhtKey, value, options)packages/ipfs-core/src/components/dht.js#L92-L102。接口测试packages/interface-ipfs-core/src/dht/put.js给出了一个真实闭环nodeAadd 内容 →name.publish(cid)发布 IPNS →dht.get(/ipns/name)取回记录 → 再将同一记录dht.put(/ipns/name, record)写回最后从PEER_RESPONSE事件确认写入了目标节点nodeB。七、ipfs.dht.query(peerId, [options])查询最近节点通过查询 DHT找到与给定 Peer ID 或 CID 最接近的 Peer ID。7.1 参数与返回名称类型说明peerIdPeerID或CID要查询的目标返回AsyncIterableObject——DHT 查询消息流。7.2 示例for await (const info of ipfs.dht.query(QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt)) { console.log(info) }7.3 底层原理与测试佐证query的实现packages/ipfs-core/src/components/dht.js#L162-L178有一个巧妙设计参数可以是 Peer ID 或 CID——若CID.asCID(peerIdToQuery)能解析为 CID则取其multihash.bytes作为查询字节否则按字符串解析 Peer ID 并取其二进制表示最终委托libp2p.dht.getClosestPeers(bytes, options)。测试packages/interface-ipfs-core/src/dht/query.js验证查询另一节点 ID 时PEER_RESPONSE事件的closer列表中应包含该节点。八、DHT 不可用时降级行为与配置当节点未启用 DHT 时例如配置文件Routing.Type设为nonejs-ipfs 不会直接崩溃而是通过use辅助函数packages/ipfs-core/src/components/dht.js#L197-L229注入一个“降级生成器”产出QUERY_ERROR事件错误信息为dht not enabledNotEnabledError而显式配置 DHT 但 libp2p 实例中无 DHT 时则会抛出dht not configuredERR_DHT_NOT_CONFIGURED。测试文件 packages/interface-ipfs-core/src/dht/disabled.js 展示了如何以Routing: { Type: none }启动节点并断言dht.put被拒绝——这是验证 DHT 禁用行为的标准做法。九、实战将 DHT API 串成一条完整链路结合上文一个典型的“发布 IPNS 记录并被其他节点读取”的实战链路如下import { CID } from multiformats/cid import drain from it-drain // 1. 添加内容并获取 CID const { cid } await ipfs.add(hello dht world) // 2. 发布 IPNS 名称 const publish await ipfs.name.publish(cid) // 3. 通过 DHT 取回记录value 为 Uint8Array for await (const event of ipfs.dht.get(/ipns/${publish.name})) { if (event.name VALUE) { console.log(new TextDecoder().decode(event.value)) break } } // 4. 将记录显式写回 DHT并排空迭代器确保完成 await drain(ipfs.dht.put(/ipns/${publish.name}, record)) // 5. 宣告本地提供该 CID await drain(ipfs.dht.provide(cid)) // 6. 其他节点查找提供者 for await (const event of ipfs.dht.findProvs(cid)) { if (event.name PROVIDER) { for (const prov of event.providers) { console.log(prov.id.toString()) } } }十、更多资源类型定义方法签名、QueryEvent联合类型与EventTypes枚举见 packages/ipfs-core-types/src/dht/index.ts核心实现createDht、toDHTKey与降级逻辑见 packages/ipfs-core/src/components/dht.js接口测试每个方法的完整用例见 packages/interface-ipfs-core/src/dht/含find-peer.js、find-provs.js、get.js、provide.js、put.js、query.js、disabled.jsHTTP 客户端如何将 DHT 操作映射为 HTTP 端点如dht/findprovs见 packages/ipfs-http-client/src/dht/相关文档DHT 在 IPNS 名称解析中的角色可参考 docs/core-api/NAME.md。赞分享存储网络通信【免费下载链接】js-ipfsIPFS implementation in JavaScript项目地址https://gitcode.com/gh_mirrors/js/js-ipfs点击查看免费下载相关推荐为什么Etcher正在改变操作系统镜像烧录的工作方式为什么Etcher正在改变操作系统镜像烧录的工作方式 想象一下这样的场景你刚刚下载了最新的树莓派操作系统镜像准备为你的物联网项目创建一个启动盘。传统的方法需存储网络通信终极指南LevelUP 核心 API 详解——掌握 put、get、del 操作的完整教程终极指南LevelUP 核心 API 详解——掌握 put、get、del 操作的完整教程 LevelUP 是一个强大的抽象层为 Node.js 和浏览器提后端js-ipfs Bitswap API 完全指南wantlist、unwant 与 stat 的实战用法与底层原理js ipfs Bitswap API 完全指南wantlist、unwant 与 stat 的实战用法与底层原理 本篇技术指南聚焦 js ipfsIPFS存储网络通信上一篇免费解锁WeMod专业版3步实现完整功能指南下一篇免费解锁WeMod专业版WandEnhancer终极指南与实战配置创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表