Crates.io | streamlette |
lib.rs | streamlette |
version | 0.2.7 |
source | src |
created_at | 2022-11-01 16:03:08.125745 |
updated_at | 2023-02-25 01:59:41.646198 |
description | Streamlet-based pluggable oneshot consensus |
homepage | |
repository | https://github.com/themeliolabs/streamlette |
max_upload_size | |
id | 702897 |
size | 71,599 |
We do a straightforward transformation of Streamlet into a oneshot consensus algorithm.
In Streamlet, we have a continuously growing tree of blocks, where "sufficiently-buried" blocks become finalized.
In Streamlette, the purpose of one instance of the consensus algorithm is to eventually decide on one conclusion. We keep track of a tree of three different message types:
Translating the Streamlet finalization criterion, a proposal buried by three consecutively-numbered, notarized (>2/3 voted) solicits becomes finalized. There can only be one such proposal (correctness), by a proof analogous to that of Streamlet.
Fuzzing a consensus implementation is really, really important. Streamlette must be generic over:
themelio-stf
and friends. Ideally, it should be useful as a BFT consensus for anything that needs a BFT consensus.For fuzzing, we want to be able to deterministically reproduce runs of the consensus algorithm. This means that we must be able to externally "tick" every consensus participant rather than have it run off in the background, as well as use a deterministic RNG for, say, simulating unreliable networks. The fuzzing will check invariants like liveness and safety, and will be sanity-checked by making sure intentionally buggy logic (say, using a 50% threshold instead of 2/3 threshold) does actually lead to failures.
Core
: implements the message tree. Contains methods for things like obtaining and applying diffs, as well as getting any finalized proposal. We use a diff-based, "pull" approach rather than a "push" approach to propagate messages in order to uphold the key property that all messages sent by an honest player eventually reach all honest players, even over an unreliable gossip network.
Decider
: implements the protocol, unified within a single tick() -> Result<Option<Bytes>, Fatal>
function. tick_to_end()
blocks and drives the tick()
function with the usual gradually slowing clock.
tick_to_end() -> Result<Bytes, Fatal>
while the fuzzer calls tick()
deterministically with a "mock" configuration.Decider
drops, all resources should synchronously free.DeciderConfig
next_diff_req(req)
and get_diff_from_peer(req)
, both of which must return relatively quickly, or time out if that's not possibleFatal
propagate to client (TODO in next version; right now we do not return errors and bad stuff causes misbehavior)