NethermindEth / NethermindEth/pluto
Rewrite `core/qbft` to async-Rust-friendly API
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 8
- Forks
- 5
- Avg merge
- 4d 16h
- Merged PRs (30d)
- 37
Description
Context
The current Rust port of core/qbft (crates/core/src/qbft/mod.rs) is a faithful translation of the Go reference but built on synchronous, thread-based primitives:
crossbeam::channelfor transportstd::thread::scopefor spawning per-process workers- A blocking
pub fn run(...)entry point cancellation::CancellationToken(third-party crate, nottokio_util)
This is at odds with the rest of Pluto, which is tokio-async end to end. Every consumer that will eventually wire QBFT in (core/consensus, core/scheduler, the duty pipeline) is async. The current shape forces either (a) bridging via spawn_blocking and ad-hoc channel adapters, or (b) blocking inside async tasks — both bad.
Closes the gap left by #13, which produced the initial sync port.
Goal
Rewrite core/qbft with an async-Rust-native API that integrates cleanly with the rest of the workspace and preserves the Byzantine-safety guarantees of the Go reference.
Scope
API
runbecomespub async fn run(...) -> Result<Decision, QbftError>Transporttrait methods returnimpl Future<Output = Result<...>> + Send(or areasync fnvia trait async)- Cancellation uses
tokio_util::sync::CancellationToken(already used elsewhere in Pluto) - Channels:
tokio::sync::mpsc(andoneshotwhere appropriate) - No
std::thread, nocrossbeam, nostd::sync::mpscanywhere in the public or internal API
Internals
- Replace
thread::scopewithtokio::spawn+JoinSet(orselect!for per-instance loops) - Replace blocking sleeps/timers with
tokio::time::sleep/Interval - Clock abstraction (
fake_clock.rs) becomes async-aware so deterministic tests still work — likely usingtokio::time::pause()+advance()rather than the current fake clock - Keep the algorithm shape (rounds, justifications, message bookkeeping) bit-for-bit identical to the Go reference — only the concurrency primitives change
Safety net (mandatory)
- Port
charon/core/consensus/qbft/strategysim_internal_test.go(~1040 LOC) as the parity gate. This is the test that catches BFT correctness regressions; without it we cannot trust the rewrite. - All current
crates/core/src/qbft/internal_test.rscases pass (or are replaced by equivalent async versions)
Acceptance criteria
- Public API is fully async; no
pub fn runblocking entry point remains - No
crossbeam,std::thread, or third-partycancellationcrate usage incrates/core/src/qbft/ - All existing QBFT unit tests pass (rewritten as async where needed)
- Strategysim parity test ported from Go and green
-
cargo clippy --workspace --all-targets --all-features -- -D warningsclean -
cargo +nightly fmt --all --checkclean - Public API documented;
missing_docswarning re-enabled for the module
References
- Go source: https://github.com/ObolNetwork/charon/blob/main/core/qbft/qbft.go
- Go strategysim test: https://github.com/ObolNetwork/charon/blob/main/core/consensus/qbft/strategysim_internal_test.go
- Current Rust port:
crates/core/src/qbft/mod.rs(1305 LOC) - Predecessor issue: #13 (closed — produced the initial sync port)
Notes
This is on the critical path for the duty-flow pipeline. core/consensus (#157) and downstream modules (core/scheduler #176, etc.) will consume the new async API directly, so this should land before consensus framework integration begins.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with crates/core/src/qbft/mod.rs and its internal_test.rs, then compare the Go reference and strategysim_internal_test.go. Run the existing QBFT tests before changing the concurrency model. Done means an async public API, equivalent async tests including strategysim parity, clean clippy and formatting, and documented public items.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- distributed-systems
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100