1个不稳定版本
0.1.0 | 2023年1月5日 |
---|
#7 在 #dusk
190KB
4.5K SLoC
共识协议
Dusk Network使用名为Succinct Attestation (SA)的共识协议。SA是一种无许可的证明权益(PoS)共识机制,提供统计最终性保证[^1]。由于它使用委员会来最终确定给定轮次的块,SA属于基于委员会的PoS类别[^2]。
SA是无许可的,这意味着Dusk Network协议中的任何合格参与者都可以加入并参与共识过程。要具备资格,参与者必须满足以下要求
- 拥有预先配置的DUSK作为抵押品锁定(称为
Provisioner
) - 拥有至少两个纪元的抵押品(称为
Eligible Provisioner
)
SA语境中使用的其他术语
Round
:单个SA执行。Round iteration
:连续执行三个阶段(选择、第一次缩减和第二次缩减)。Committee
:合格抵押品的子集,通过“确定性抽签”过程选出。
仓库结构
示例节点
这是dusk-blockchain节点的最小化、无状态版本,允许使用Kadcast[^3]与共识协议结合进行测试和诊断兼容性问题。它使节点能够加入并参与dusk-blockchain/test-harness。一旦dusk-blockchain完全迁移,此可执行文件将不再需要,可以弃用。
示例测试平台
一个多实例设置,运行10个SA实例,每个实例配备10个合格参与者。该设置配置为运行最多1000轮。适用于任何类型的测试(问题、压力和性能测试)。
共识crate
SA机制的完整实现。
实现细节
SA的实现由两个主要的tokio-rs
任务组成,分别是Main_Loop
和Agreement_Loop
,它们通过消息队列/通道与外部组件进行通信。《SA》的协议参数位于src/config.rs
。
-
Main_Loop
负责使用Operations
特性执行合约存储调用,并使用Database
特性存储和检索候选块。它按顺序执行选择、第一次缩减和第二次缩减步骤[^4],最终生成和广播一个Agreement Message
。Main_Loop
的输入队列可以包含 NewBlock 或 Reduction 类型的消息。 -
Agreement_Loop
在选择获胜哈希时,使用Database
特性检索候选块。它负责验证和累积来自不同共识迭代的 Agreement 消息并处理 Aggregated Agreement 消息。Agreement_Loop
的输入队列可以包含 Agreement 或 Aggregated Agreement 类型的消息。这些消息由tokio-rs
中的工作任务池并发验证和累积。
如何使用(示例代码)
let mut consensus = Consensus::new(
// Inbound messages for Main Loop
inbound_msgs,
// Outbound messages for Main Loop
outbound_msgs,
// Inbound messages for Agreement Loop
agr_inbound_queue,
// Outbound messages for Agreement Loop
agr_outbound_queue,
// Implements Operations trait
Arc::new(Mutex::new(crate::mocks::Executor {})),
// Implements Database trait
Arc::new(Mutex::new(crate::mocks::SimpleDB::default())),
);
let mut most_recent_block = Block::default();
loop {
/// Provisioners list is retrieved from contract storage state.
let provisioners = rusk::get_provisioners();
// Round update is the input data for any consensus round execution.
// Round update includes mostly data from most recent block.
let round_update = from(most_recent_block);
/// Consensus::Spin call initializes a consensus round
/// and spawns main consensus tokio::tasks.
let ret = consensus.spin(
round_update
provisioners,
cancel_rx,
)
.await;
/// Consensus spin output/ret can be a winner block or an error.
match ret {
Ok(winner_block) => {
println!("new block produced");
}
Err(_) => {
// Cancelled from outside by cancel_rx chan.
// Max Step Reached - happens only if no consensus is reached for up to 213 steps/71 iterations.
}
}
most_recent_block = winner;
/// Internally, consensus instance may accept future messages for next round.
/// They will be drained on running the round, that's why same consensus instance is used for all round executions.
}
Tokio 运行时
实现完全基于 Tokio-rs/Runtime。也就是说,以下展示了设置运行时的推荐方法。
tokio::runtime::Builder::new_multi_thread()
// A thread per an accumulator worker so that CPU-bound operations
// (the agreement verification) does not impact negatively main tokio tasks.
.worker_threads(2 + consensus::config::ACCUMULATOR_WORKERS_AMOUNT)
// Enable the time driver so we can use timeout feature in all steps execution.
.enable_time()
.build()
.unwrap()
.block_on(async { ... } )
构建、运行和测试
# Run unit tests
cargo test
# Build consensus
cargo b --release
# Build and Run in-process testbed example
cargo run --release --example testbed
# Build example node
cargo b --release --example node
# Run example node
export DUSK_WALLET_DIR="TBD"
export DUSK_CONSENSUS_KEYS_PASS="TBD"
USAGE:
node --bootstrap <bootstrap>... --address <public_address> --preloaded-num <preloaded-num> --provisioner-unique-id <prov-id> --log-level <LOG>
[^1]: 通过随时间积累块而实现的最终确定性保证,使得块被逆转的概率随着更多块堆叠在它上面而指数级降低。这种保证与绝对最终确定性相对立,绝对最终确定性是在块被逆转在数学上不可能的情况下实现的。[^2]: 一种依赖于验证者委员会而不是网络中所有验证者来就下一个块达成共识的 PoS 共识机制。基于委员会的 PoS 机制通常比非委员会机制具有更快的块时间和更低的开销,但可能更容易受到审查或集中化的影响。[^3]: Kadcast 是一种用于在网络的节点之间进行高效通信的分布式协议。它基于 Kademlia 算法,并维护一个路由表以找到到达另一个节点的最佳路径。Kadcast 常用于去中心化系统,如去中心化应用程序(DApps)和去中心化文件共享系统,以在节点之间快速可靠地发送消息和数据。Kadcast 的一个主要优点是其去中心化特性,这使得它对审查和其他形式的干扰具有抵抗力,使其成为需要去中心化的应用的流行选择。请在此处找到白皮书(链接)。Dusk 的实现可在其存储库中找到。[^4]: 在选择阶段,一个作为块生成器的副本(或在 Dusk 术语中为提供者)提出一个块。在第一次缩减阶段,一个抽样委员会的提供者通过使用 BLS 签名消息并广播它来对块的合法性进行投票。在第二次缩减阶段,不同的抽样委员会的提供者对块进行投票,收集第一次缩减阶段的结果,并产生一个“Agreement”消息。这些步骤会持续迭代,直到 Agreement
循环中断流程。这允许该组就同意哪个块做出最终决定。
依赖项
~9–16MB
~187K SLoC