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.0 | 2022 年 3 月 23 日 |
#2713 in 神奇豆
每月 175 次下载
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_next
和 receive_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