Expand description
Simple and fast BFT agreement inspired by Simplex Consensus.
Inspired by Simplex Consensus, simplex provides simple and fast BFT
agreement with network-speed view (i.e. block time) latency and optimal finalization latency in a
partially synchronous setting.
§Features
- Wicked Fast Block Times (2 Network Hops)
- Optimal Finalization Latency (3 Network Hops)
- Externalized Uptime and Fault Proofs
- Decoupled Block Broadcast and Sync
- Lazy Message Verification
- Application-Defined Block Format
- Pluggable Hashing and Cryptography
- Embedded VRF (via signing_scheme::bls12381_threshold)
§Design
§Protocol Description
§Specification for View v
Upon entering view v:
- Determine leader
lfor viewv - Set timer for leader proposal
t_l = 2Δand advancet_a = 3Δ- If leader
lhas not been active in lastrviews, sett_lto 0.
- If leader
- If leader
l, broadcastnotarize(c,v)- If can’t propose container in view
vbecause missing notarization/nullification for a previous viewv_m, requestv_m
- If can’t propose container in view
Upon receiving first notarize(c,v) from l:
- Cancel
t_l - If the container’s parent
c_parentis notarized atv_parentand we have nullifications for all views betweenvandv_parent, verifycand broadcastnotarize(c,v)
Upon receiving 2f+1 notarize(c,v):
- Cancel
t_a - Mark
cas notarized - Broadcast
notarization(c,v)(even if we have not verifiedc) - If have not broadcast
nullify(v), broadcastfinalize(c,v) - Enter
v+1
Upon receiving 2f+1 nullify(v):
- Broadcast
nullification(v)- If observe
>= f+1notarize(c,v)for somec, requestnotarization(c_parent, v_parent)and any missingnullification(*)betweenv_parentandv. Ifc_parentis than last finalized, broadcast last finalization instead.
- If observe
- Enter
v+1
Upon receiving 2f+1 finalize(c,v):
- Mark
cas finalized (and recursively finalize its parents) - Broadcast
finalization(c,v)(even if we have not verifiedc)
Upon t_l or t_a firing:
- Broadcast
nullify(v) - Every
t_rafternullify(v)broadcast that we are still in viewv:- Rebroadcast
nullify(v)and eithernotarization(v-1)ornullification(v-1)
- Rebroadcast
When 2f+1 votes of a given type (notarize(c,v), nullify(v), or finalize(c,v)) have been have been collected
from unique participants, a certificate (notarization(c,v), nullification(v), or finalization(c,v)) can be assembled.
These certificates serve as a standalone proof of consensus progress that downstream systems can ingest without executing
the protocol.
§Joining Consensus
As soon as 2f+1 notarizes, nullifies, or finalizes are observed for some view v, the Voter will
enter v+1. This means that a new participant joining consensus will immediately jump ahead to the
latest view and begin participating in consensus (assuming it can verify blocks).
§Deviations from Simplex Consensus
- Fetch missing notarizations/nullifications as needed rather than assuming each proposal contains a set of all notarizations/nullifications for all historical blocks.
- Introduce distinct messages for
notarizeandnullifyrather than referring to both as avotefor either a “block” or a “dummy block”, respectively. - Introduce a “leader timeout” to trigger early view transitions for unresponsive leaders.
- Skip “leader timeout” and “notarization timeout” if a designated leader hasn’t participated in some number of views (again to trigger early view transition for an unresponsive leader).
- Introduce message rebroadcast to continue making progress if messages from a given view are dropped (only way to ensure messages are reliably delivered is with a heavyweight reliable broadcast protocol).
§Architecture
All logic is split into four components: the Batcher, the Voter, the Resolver, and the Application (provided by the user).
The Batcher is responsible for collecting messages from peers and lazily verifying them when a quorum is met. The Voter
is responsible for directing participation in the current view. The Resolver is responsible for
fetching artifacts from previous views required to verify proposed blocks in the latest view. Lastly, the Application
is responsible for proposing new blocks and indicating whether some block is valid.
To drive great performance, all interactions between Batcher, Voter, Resolver, and Application are
non-blocking. This means that, for example, the Voter can continue processing messages while the
Application verifies a proposed block or the Resolver fetches a notarization.
+------------+ +++++++++++++++
| +--------->+ +
| Batcher | + Peers +
| |<---------+ +
+-------+----+ +++++++++++++++
| ^
| |
| |
| |
v |
+---------------+ +---------+ +++++++++++++++
| |<----------+ +----------->+ +
| Application | | Voter | + Peers +
| +---------->| |<-----------+ +
+---------------+ +--+------+ +++++++++++++++
| ^
| |
| |
| |
v |
+-------+----+ +++++++++++++++
| +--------->+ +
| Resolver | + Peers +
| |<---------+ +
+------------+ +++++++++++++++§Batched Verification
Unlike other consensus constructions that verify all incoming messages received from peers, simplex
lazily verifies messages (only when a quorum is met). If an invalid signature is detected, the Batcher
will perform repeated bisections over collected messages to find the offending message (and block the
peer(s) that sent it via commonware_p2p::Blocker).
If using a p2p implementation that is not authenticated, it is not safe to employ this optimization as any attacking peer could simply reconnect from a different address. We recommend commonware_p2p::authenticated.
§Pluggable Hashing and Cryptography
Hashing is abstracted via the commonware_cryptography::Hasher trait and cryptography is abstracted via the Scheme trait, allowing deployments to employ approaches that best match their requirements (or to provide their own without modifying any consensus logic). The following Schemes are supported out-of-the-box:
§signing_scheme::ed25519
commonware_cryptography::ed25519 signatures are “High-speed high-security signatures” with 32 byte public keys and 64 byte signatures. While they are well-supported by commercial HSMs and offer efficient batch verification, the signatures are not aggregatable (and certificates grow linearly with the quorum size).
§signing_scheme::bls12381_multisig
commonware_cryptography::bls12381 is a “digital signature scheme with aggregation properties”. Unlike commonware_cryptography::ed25519, signatures from multiple participants (say the signers in a certificate) can be aggregated into a single signature (reducing bandwidth usage per broadcast). That being said, commonware_cryptography::bls12381 is much slower to verify than commonware_cryptography::ed25519 and isn’t supported by most HSMs (a standardization effort expired in 2022).
§signing_scheme::bls12381_threshold
Last but not least, signing_scheme::bls12381_threshold employs threshold cryptography (specifically BLS12-381 threshold signatures
with a 2f+1 of 3f+1 quorum) to generate both a bias-resistant beacon (for leader election and post-facto execution randomness)
and succinct consensus certificates (any certificate can be verified with just the static public key of the consensus instance) for each view
with zero message overhead (natively integrated). While powerful, this scheme requires both instantiating the shared secret
via commonware_cryptography::bls12381::dkg and performing a resharing procedure whenever participants are added or removed.
§Embedded VRF
Every notarize(c,v) or nullify(v) message includes a part(v) message (a partial signature over the view v). After 2f+1
notarize(c,v) or nullify(v) messages are collected from unique participants, seed(v) can be recovered. Because part(v) is
only over the view v, the seed derived for a given view v is the same regardless of whether or not a block was notarized in said
view v.
Because the value of seed(v) cannot be known prior to message broadcast by any participant (including the leader) in view v
and cannot be manipulated by any participant (deterministic for any 2f+1 signers at a given view v), it can be used both as a beacon
for leader election (where seed(v) determines the leader for v+1) and a source of randomness in execution (where seed(v)
is used as a seed in v).
§Succinct Certificates
All broadcast consensus messages (notarize(c,v), nullify(v), finalize(c,v)) contain partial signatures for a static
public key (derived from a group polynomial that can be recomputed during reconfiguration using dkg).
As soon as 2f+1 messages are collected, a threshold signature over notarization(c,v), nullification(v), and finalization(c,v)
can be recovered, respectively. Because the public key is static, any of these certificates can be verified by an external
process without following the consensus instance and/or tracking the current set of participants (as is typically required
to operate a lite client).
These threshold signatures over notarization(c,v), nullification(v), and finalization(c,v) (i.e. the consensus certificates)
can be used to secure interoperability between different consensus instances and user interactions with an infrastructure provider
(where any data served can be proven to derive from some finalized block of some consensus instance with a known static public key).
§Persistence
The Voter caches all data required to participate in consensus to avoid any disk reads on
on the critical path. To enable recovery, the Voter writes valid messages it receives from
consensus and messages it generates to a write-ahead log (WAL) implemented by commonware_storage::journal::segmented::variable::Journal.
Before sending a message, the Journal sync is invoked to prevent inadvertent Byzantine behavior
on restart (especially in the case of unclean shutdown).
Modules§
- signing_
scheme - Signing scheme implementations for
simplex. - types
- Types used in crate::simplex.
Structs§
Functions§
- select_
leader - Selects the leader for a given round using scheme-provided randomness seed when available.