51 个版本

0.18.2 2023 年 8 月 24 日
0.18.1 2023 年 4 月 21 日
0.18.0 2023 年 2 月 4 日
0.15.0 2022 年 11 月 13 日
0.8.0-alpha.02022 年 3 月 23 日

#2713 in 神奇豆

Download history 19/week @ 2024-04-08 22/week @ 2024-04-15 34/week @ 2024-04-22 89/week @ 2024-04-29 55/week @ 2024-05-06 63/week @ 2024-05-13 70/week @ 2024-05-20 23/week @ 2024-05-27 14/week @ 2024-06-03 10/week @ 2024-06-10 25/week @ 2024-06-17 14/week @ 2024-06-24 82/week @ 2024-07-01 34/week @ 2024-07-08 24/week @ 2024-07-15 33/week @ 2024-07-22

每月 175 次下载

Apache-2.0

315KB
5K SLoC

帕拉斯小协议

本库提供了 Ouroboros 小协议的实现,这些小协议在The Shelley Networking Protocol 规范中定义。

架构决策

针对此特定的 Rust 实现做出了以下架构决策

  • 小协议将与具体的账本实现保持无关。例如,区块检索实现是针对特定区块数据结构的泛型。
  • Ouroboros 规范定义的消息编解码器实现属于此库,但任何特定账本的结构都不在范围内。
  • 状态机执行将与具体的小协议规范保持无关。

开发状态

小协议 发起者 响应者
区块检索 完成 计划中
链同步 完成 计划中
握手 完成 计划中
本地状态 完成 计划中
交易提交 计划中 最小化
本地交易监控 完成 计划中
本地交易提交 进行中 计划中

实现细节

将 Ouroboros 小协议定义为状态机。此库提供了描述每个特定状态机和消息的原始工具。

本地代理(无论是发起者还是响应者)通过与远程代理交换消息并保持自己的状态版本来与远程代理交互。

通过实现以下特性行为,结构可以作为一个代理参与 Ouroboros 通信

pub trait Agent: Sized {
    type Message;

    fn is_done(&self) -> bool;
    fn has_agency(&self) -> bool;
    fn send_next(self, tx: &impl MachineOutput) -> Transition<Self>;
    fn receive_next(self, msg: Self::Message) -> Transition<Self>;
}
  • 关联类型 Message 是一个枚举,包含每个特定小协议的特定变体
  • 函数 has_agency 描述代理是否具有当前状态的行为能力。
  • 函数 is_done 描述代理是否认为所有任务都已完成。
  • 函数 send_next 指示代理发送序列中的下一个消息(仅在具有行为能力时调用)。
  • 函数 receive_next 指示代理处理收到的下一个消息。

send_nextreceive_next 方法将状态机从一种状态过渡到下一个状态。这种转换不会修改任何值,其想法是过程中的每一步将代理结构体转换为新类型的结构体,以描述新的状态。这种方法允许我们将状态机的执行实现为一个纯函数。

为了触发代理的执行,库提供了以下入口点:

run_agent<T>(agent: T, channel: &mut Channel)

其中 T 是要执行的具体系代理的类型,而 Channel 是已连接到远程方的 Ouroboros 多路复用器通道。

执行示例

以下示例展示了如何执行一个与远程中继节点进行握手的客户端。

// setup a TCP bearer against a relay node
let bearer = TcpStream::connect("relays-new.cardano-mainnet.iohk.io:3001").unwrap();
bearer.set_nodelay(true).unwrap();
bearer.set_keepalive_ms(Some(30_000u32)).unwrap();

// create a new multiplexer, specifying which mini-protocol IDs we want to sue
let mut muxer = Multiplexer::setup(bearer, &[0]).unwrap();

// get a handle for the handhsake mini-protocol handle
let mut channel = muxer.use_channel(0);

// create a handshake client agent with an initial state 
let agent = handshake::Client::initial(VersionTable::v4_and_above(MAINNET_MAGIC));

// run the agent, which internally executes all the transitions
// until it is done.
let agent = run_agent(agent, &mut channel).unwrap();

// print the final state of the agent
println!("{agent:?}");

依赖项

~1.9–2.8MB
~56K SLoC