显示包…

1 个不稳定版本

0.8.0 2021年4月4日
0.0.0 2021年3月5日

#12#tetcore

Download history 18/week @ 2024-03-13 33/week @ 2024-03-20 44/week @ 2024-03-27 47/week @ 2024-04-03 18/week @ 2024-04-10 17/week @ 2024-04-17 24/week @ 2024-04-24 17/week @ 2024-05-01 21/week @ 2024-05-08 22/week @ 2024-05-15 15/week @ 2024-05-22 24/week @ 2024-05-29 20/week @ 2024-06-05 15/week @ 2024-06-12 15/week @ 2024-06-19 16/week @ 2024-06-26

68 每月下载量
34 个包中使用 (15 直接)

GPL-3.0-or-later…

1.5MB
36K SLoC

Tetcore特定P2P网络。

重要:此包是不稳定的,API和用法可能会更改。

节点身份和地址

在去中心化网络中,每个节点都拥有一个网络私钥和网络公钥。在Tetcore中,密钥基于ed25519曲线。

从节点的公钥中,我们可以推导出其身份。在Tetcore和libp2p中,节点的身份用PeerId结构体表示。网络上节点之间的所有网络通信都使用从双方密钥派生的加密,这意味着身份不能伪造

节点身份唯一标识网络上的机器。如果您使用相同的网络密钥启动两个或多个客户端,将发生大量干扰。

Tetcore的网络协议

Tetcore的联网协议基于libp2p。目前不可能,也没有计划允许使用除libp2p网络堆栈和rust-libp2p库之外的其他任何内容。然而,libp2p框架非常灵活,rust-libp2p库可以扩展以支持比libp2p提供的更广泛的协议。

发现机制

为了使我们的节点加入点对点网络,它必须知道属于该网络的节点列表。这包括节点身份和它们的地址(如何到达它们)。构建此类列表称为发现机制。Tetcore使用三种机制

  • 引导节点。这些是硬编码的节点身份和地址,与网络配置一起传递。
  • mDNS。我们在本地网络上执行UDP广播。监听的节点可以响应其身份。更多信息在这里。mDNS可以在网络配置中禁用。
  • 凯德米拉随机游走。一旦连接,我们在配置的凯德米拉DHT(每个配置的链协议一个)上执行随机的凯德米拉 FIND_NODE 请求,以便节点传播它们的网络视图。有关凯德米拉的更多信息,可以在维基百科上找到。

建立连接

当节点Alice知道节点Bob的身份和地址时,它可以与Bob建立连接。所有连接必须始终使用加密和复用。虽然一些节点地址(例如使用 /quic 的地址)已经暗示了要使用哪种加密和/或复用,但对于其他地址,则使用 multistream-select 协议来协商加密层和/或复用层。

建立连接的机制称为 传输

截至编写本文档时,Tetcore 支持以下底层协议

  • 用于形式为 /ip4/1.2.3.4/tcp/5 的地址的 TCP/IP。一旦TCP连接打开,就在其上协商加密和复用层。
  • 用于形式为 /ip4/1.2.3.4/tcp/5/ws 的地址的 WebSocket。打开一个TCP/IP连接,并在其上协商WebSocket协议。然后,通信在WebSocket数据帧内进行。在此通道内再次协商加密和复用。
  • 用于形式为 /dns/example.com/tcp/5/dns/example.com/tcp/5/ws 的地址的 DNS。一个节点的地址可以包含域名。
  • (所有上述内容均使用IPv6代替IPv4。)

在底层协议之上,协商并应用了 Noise 协议。确切的握手协议是实验性的,可能发生变化。

以下为支持的复用协议

  • Mplex。可能未来将弃用对mplex的支持。
  • Yamux.

子流

一旦建立连接并使用复用,就可以打开子流。当子流打开时,使用 multistream-select 协议协商在该子流上使用哪种协议。

针对特定链的协议在其名称中具有一个 <protocol-id>。此 "协议 ID" 在链规范中定义。例如,波卡协议的协议 ID 为 "dot"。在以下协议名称中,<protocol-id> 必须替换为相应的协议 ID。

注意:同一个连接可能用于多个链。例如,如果远程端支持,则可以在同一个连接上使用 /dot/sync/2/sub/sync/2 协议。

Tetcore 使用以下标准 libp2p 协议

  • /ipfs/ping/1.0.0。我们定期打开一个临时子流,以ping远程端并检查连接是否仍然活跃。如果远程端未回复,则导致断开连接。
  • /ipfs/id/1.0.0。我们定期打开一个临时子流,以从远程端请求信息。
  • /<protocol_id>/kad。我们定期打开临时子流,以进行凯德米拉随机游走查询。每个凯德米拉查询都在一个单独的子流中完成。

此外,Tetcore 还使用以下非 libp2p 标准协议

  • /tetcore/<协议ID>/<版本>(其中 <协议ID> 需要用目标链的协议ID替换,而 <版本> 是一个介于2和6之间的数字)。对于每个连接,我们可以选择保留一个额外的子流来保持所有基于Tetcore的通信活跃。此协议被认为是过时的,并且正在逐步被替代方案所取代。在本文档中,这被称为“过时Tetcore子流”。下面将提供更多详细信息。
  • /<protocol-id>/sync/2 是一个请求-响应协议(见下文),允许执行有关区块的信息请求。每个请求是对 BlockRequest 的编码,每个响应是对 BlockResponse 的编码,如本源树中 api.v1.proto 文件中定义的那样。
  • /<protocol-id>/light/2 是一个请求-响应协议(见下文),允许执行与轻客户端相关的关于状态的信息请求。每个请求是对 light::Request 的编码,每个响应是对 light::Response 的编码,如本源树中 light.v1.proto 文件中定义的那样。
  • /<protocol-id>/transactions/1 是一个通知协议(见下文),其中将交易推送到其他节点。双方握手为空。消息格式是包含交易的SCALE编码列表,其中每个交易都是一个不可见字节数组。
  • /<protocol-id>/block-announces/1 是一个通知协议(见下文),其中将区块公告推送到其他节点。双方握手为空。消息格式是包含区块头部和与该区块公告相关的一些数据的不可见字节数组的SCALE编码元组,例如候选消息。
  • 使用 NetworkConfiguration::notifications_protocols 注册的通知协议。例如:/tetcoin/grandpa/1。下面将提供更多信息。

过时Tetcore子流

Tetcore使用一个名为 节点组管理器(PSM) 的组件。通过发现机制,PSM了解网络中的节点,并决定我们应该与哪些节点进行基于Tetcore的通信。对于这些节点,如果需要,我们将打开一个连接并为基于Tetcore的通信打开一个唯一的子流。如果PSM决定我们应该断开一个节点的连接,那么该子流将被关闭。

有关PSM的更多信息,请参阅 tc-peerset crate。

请注意,目前尚无机制来解决连接的两侧同时打开唯一子流时出现的问题。为了避免出现这些问题,只有连接的拨号端被允许打开唯一子流。当子流关闭时,整个连接也会关闭。这是一个将完全弃用协议来解决的bug。

在唯一的Tetcore子流中,使用tetsy-scale-codec进行编码的消息被交换。这些消息的详细信息尚未完全就绪,但可以在message.rs文件中找到。

一旦子流打开,第一步是双方交换一个包含链根哈希、链头等信息的状态消息。

此子流中的通信包括

  • 同步。从其他节点宣布和请求区块。
  • 轻客户端请求。当一个轻客户端需要信息时,我们会选择与之一个打开子流的随机节点,并从它那里请求信息。
  • 八卦。例如,由grandpa使用。

请求-响应协议

所谓的请求-响应协议定义如下

  • 当子流打开时,打开端发送一个内容为特定协议的消息。该消息必须以一个表示其长度的LEB128编码的数字为前缀。消息发送后,写入端关闭。
  • 远程发送回以LEB128编码的长度为前缀的响应,并关闭其端点。

每个请求都在一个新的单独子流中执行。

通知协议

所谓的通知协议定义如下

  • 当子流打开时,打开端发送一个握手消息,其内容为特定协议。握手消息必须以一个表示其长度的LEB128编码的数字为前缀。握手消息的长度可以为0,在这种情况下,发送方必须发送单个0
  • 接收方随后可以立即关闭子流,或者以自己的LEB128前缀的特定协议握手响应进行回答。消息的长度可以为0,在这种情况下,必须发送单个0
  • 一旦握手完成,通知协议是单向的。只有发起子流的节点可以推送通知。如果远程节点也想要发送通知,它必须打开自己的单向子流。
  • 每个通知都必须以一个LEB128编码的长度为前缀。消息的编码对每个协议都是特定的。
  • 任何一方都可以通过关闭其写入端来表示它不再需要通知子流。另一方应随后关闭其自己的写入端。

tc-network的API允许注册用户定义的通知协议。tc-network会自动尝试为每个节点打开子流,对于这些节点,传统的子流是打开的。然后自动执行握手。

例如,tc-finality-grandpa存储库注册了/tetcoin/grandpa/1通知协议。

目前,为了向后兼容,通知协议与传统的Tetcore子流绑定。此外,握手消息被硬编码为单个8位整数,表示节点的角色

  • 1表示全节点。
  • 2表示轻节点。
  • 4表示权威节点。

然而,在未来,这些限制将被取消。

用法

使用tc-network crate需要通过NetworkWorker结构体来实现。通过传递一个config::Params来创建这个结构体,然后像处理Future一样轮询它。你可以从NetworkWorker中提取一个Arc<NetworkService>,以便在多个地方共享,以便向网络发送命令。

有关如何配置网络的更多信息,请参阅config模块。

NetworkWorker创建后,需要做的重要事情包括

  • 通过调用NetworkWorker::poll来推进网络。这可以通过使用NetworkWorker调度后台任务来实现。
  • 每当客户端添加了一个区块时,调用on_block_import
  • 每当一个区块被最终确定时,调用on_block_finalized
  • 当事务被添加到池中时,调用trigger_repropagate

更详细的用法细节仍在开发中,并可能在将来发生变化。

许可证:GPL-3.0-or-later WITH Classpath-exception-2.0

依赖关系

~31–47MB
~832K SLoC