Minimmit: Fast Finality with Even Faster Blocks
Over the last few months, there has been renewed interest in developing propose-and-vote consensus protocols that reach finality after just one round of voting (~100-200ms). "Two-Phase" protocols, not without tradeoff, only remain safe if a Byzantine adversary controls less than ~20% of stake (rather than the ~33% tolerance typically considered). Concerned primarily with addressing this drop in fault tolerance, recent constructions propose augmenting Byzantine fault tolerance with crash fault tolerance to retain some path to finality under a "blended" ~33% assumption. Minimmit, a new propose-and-vote construction below, optimizes for a different goal: minimizing block time.

Background
In March, Matter Labs released ChonkyBFT: Consensus Protocol of ZKsync. In May, Offchain Labs released Kudzu: Fast and Simple High-Throughput BFT and Anza Labs released Alpenglow at Solana Accelerate. And just a few days ago, Supra Research and Espresso Systems released Hydrangea: A Fast and Simple Consensus Protocol for High-Throughput Blockchains.
All capable of propose-and-vote confirmation in ~100-200ms, this cohort of new constructions primarily differs in the technique employed to finalize blocks if faults exceed ~20% of stake (when comprised of at most f Byzantine faults and p crash faults). Finalizing quickly via some "fast path" when replicas are honest and online, these constructions fallback to a "slow path" that resembles the "Three-Phase" protocols commonly deployed today.

Minimmit: Fast Finality with Even Faster Blocks
Today, we are excited to share a different take on propose-and-vote consensus: Minimmit: Fast Finality with Even Faster Blocks. Like the constructions above, Minimmit delivers minimal confirmation latency under the ~20% Byzantine fault assumption. Unlike those constructions, however, it optimizes for view latency instead of f+ confirmation robustness. In an alto-like configuration (with 50 uniformly distributed validators), we expect a Minimmit-powered blockchain to reach 130ms block time and 250ms finality. In a regionally-biased configuration, we expect Minimmit to deliver 50ms block time and 100ms finality.

While not yet peer-reviewed or fully implemented, we are releasing Minimmit under both an MIT and Apache-2 license for others to build with and build upon. Below, we provide a high-level summary of the specification and share some intuition about its correctness:
1. Introduction
Minimmit is a responsive, leader-based consensus protocol designed for simplicity and speed, tolerant of a Byzantine adversary that controls fewer than 20%
of replicas. Minimmit advances to the next view when a 40%
quorum is reached and finalizes blocks when an 80%
quorum is reached (after only a single round of voting). Minimmit can be instantiated with a number of practical optimizations to improve performance when deployed in production.
2. Model & Parameters
- Byzantine replicas:
≤ f
- Total replicas:
n ≥ 5f + 1
- Partial synchrony: every message arrives within
Δ
after an unknown global stabilization time (GST).
3. Quorums
L = n - 3f
(2f + 1
)Q = n - f
(4f + 1
)
There exists ≥ 1
honest replica in any Q
-set and L
-set intersection.
4. Message Types
Message | Purpose |
---|---|
genesis |
The genesis block. |
propose(c, v, (c', v')) |
Leader's proposal c for view v with parent c' in view v' . |
notarize(c, v) |
Vote to finalize block c in view v . |
nullify(v) |
Vote to advance to view v + 1 . |
notarization(c, v) |
Certificate of ≥ L notarize(c, v) messages for (c, v) . |
nullification(v) |
Certificate of ≥ L nullify(v) messages for view v . |
proof(v) |
Either a notarization(*, v) or a nullification(v) certificate. |
5. Initial Replica State
view = 0
notarized = ⊥ # the proposal this replica has notarized
nullified = false # whether this replica has nullified this view
timer = None # time until nullify if not yet nullified or notarized
messages = [] # list of messages this replica has seen
proofs = [] # list of proofs this replica has collected
6. External Functions
// Select the leader for view `v`
fn leader(v) -> L;
// Build a block on top of `c'`. This should pass `verify(c, c')`.
fn build(c') -> c;
// Verify whether `c` is valid given the parent `c'`. Anything produced by
// `build(c')` should pass `verify(c, c')`.
fn verify(c, c') -> bool;
7. Helpers
// Find a valid parent to build on
fn select_parent(v) -> (c', v') {
let i = v - 1;
while i >= 0 {
if notarization(c', i) ∈ proofs[i] {
// If there are multiple, pick any.
return (c', i);
}
if nullification(i) ∈ proofs[i] {
i -= 1;
continue;
}
return ⊥;
}
return genesis;
}
// Ensure there are proofs for all views between `v` and `v'`
fn valid_parent(v, (c', v')) -> bool {
let i = v - 1;
while i > v' {
if nullification(i) ∈ proofs[i] {
i -= 1;
continue;
}
return false;
}
return notarization(c', v') ∈ proofs[v']
}
// Enter view `next`
fn enter_view(next) {
if view >= next {
return;
}
view = next;
notarized = ⊥;
nullified = false;
timer = 2Δ;
}
// Record a message from a `replica`
fn record_message(replica, message) -> bool {
if replica ∉ messages[message.view] {
messages[message.view][replica] = [];
}
if message ∉ messages[message.view][replica] {
messages[message.view][replica].add(message);
return true;
}
return false;
}
// Prune data less than `view`
fn prune(view) {
messages.remove(m => m.view < view);
proofs.remove(p => p.view < view);
}
8. Protocol for View v
8.1. Propose
If the leader, propose.
- Upon entering view
v
, if identity is equal toleader(v)
:(c', v') = select_parent(v)
(if⊥
, return).c = build(c')
.notarized = c
.- Broadcast
propose(c, v, (c', v'))
.
Treat propose(c, v, (c', v'))
as a leader l
's notarize(c, v)
.
8.2. Notarize
Upon receipt of a first valid block proposal from leader, broadcast notarize(c, v)
.
- On receiving first
propose(c, v, (c', v'))
fromleader(v)
:- If
notarized != ⊥
ornullified
, return. - If
!valid_parent(v, (c', v'))
, return. - If
!verify(c, c')
, return. notarized = c
.- Broadcast
notarize(c, v)
.
- If
8.3. Nullify by Timeout
If timer
expires, broadcast nullify(v)
if not yet broadcasted notarize(c, v)
.
- On
timer
expiry:- If
notarized != ⊥
ornullified
, return. nullified = true
.- Broadcast
nullify(v)
.
- If
8.4. Notarization & Finalization
After L
messages, create and broadcast a notarization(c, v)
certificate. After Q
messages, finalize.
- On receiving
notarize(c, v)
from replicar
:- If
!record_message(r, notarize(c, v))
, return.
- If
- On observing
≥ L
notarize(c, v)
messages:- Assemble
notarization(c, v)
. - Add
notarization(c, v)
toproofs
. - Broadcast
notarization(c, v)
. enter_view(v + 1)
.
- Assemble
- On observing
≥ Q
notarize(c, v)
messages:- Finalize
c
and all of its ancestors. prune(v)
.
- Finalize
8.5. Nullification
After L
messages, create and broadcast a nullification(v)
certificate.
- On receiving
nullify(v)
from replicar
:- If
!record_message(r, nullify(v))
, return.
- If
- On observing
≥ L
nullify(v)
messages (or a singlenullification(v)
message):- Assemble
nullification(v)
. - Add
nullification(v)
toproofs
. - Broadcast
nullification(v)
. enter_view(v + 1)
.
- Assemble
8.6 Nullify by Contradiction
If you have already broadcast notarize(c, v)
for a c
that cannot be finalized directly, broadcast nullify(v)
to ensure some proof(v)
will exist in view v
.
- On observing messages from
≥ L
replicas of eithernullify(v)
ornotarize(*, v)
(wherenotarized != ⊥
andnotarized != *
):nullified = true
.- Broadcast
nullify(v)
.
9. Intuition
9.1 General
- A leader selected in
v + 1
may propose any blockc
that extends some knownnotarization(c', v')
as long as there existnullification(j)
proofs for all views in(v', v]
. Notably, this means that leaders are never required to re-propose a block from an earlier view and can only skip some block proposed in an earlier viewv
if there exists somenullification(v)
.
9.2 Safety
- Honest replicas may not broadcast a
notarize(c, v)
after first broadcasting anullify(v)
. - Honest replicas may broadcast a
nullify(v)
after first broadcasting anotarize(c, v)
.- To broadcast both a
notarize(c, v)
and anullify(v)
message, a replica must first see that it is impossible for the proposal that it notarized to reach a quorum ofQ
notarize(c, v)
messages. Otherwise, the replica is forbidden from broadcastingnullify(v)
, no matter how much time has passed. - A replica knows it is impossible for its notarized proposal
c
to reach the finalization quorumQ
once it has observedL
other replicas that conflict. A conflicting replica has broadcast either anullify(v)
message or anotarize(*, v)
message for a different proposal*
. - If a replica has seen
L
conflicting votes, at leastL - f
(i.e.f + 1
) are from honest replicas. Therefore, the maximum number ofnotarize(c, v)
it can receive isn - (f + 1)
, or4f
(strictly less thanQ
).
- To broadcast both a
- Suppose a correct leader broadcasts a block
c
and, after honest replicas broadcastnotarize(c, v)
, message delivery is disrupted, preventing any replica from receivingL
such messages. In this state, replicas have locked onc
for viewv
and cannot broadcast somenullify(v)
. Progress is stalled until network conditions improve, allowing anotarization(c, v)
to be assembled, which in turn allows replicas to enter viewv + 1
. - In any given view
v
, there may be multiplenotarization(*, v)
messages and onenullification(v)
. If there are multiplenotarization(*, v)
s, no block*
referenced by anotarization(*, v)
can be finalized inv
. If there exists somenullification(v)
, no block can be finalized inv
.
9.3 Liveness
- There exists at least one
proof(v)
for every viewv
. - After GST, all views with honest leaders will emit a
notarization
message before the timer of any honest replica expires. To see this is true, consider the following:- The first honest replica broadcasts some
proof(v - 1)
message to all replicas and enters viewv
at timet_0
. - The leader of view
v
will receive saidproof(v - 1)
message byt_0 + Δ
and broadcast somepropose(c, v, (c', v'))
message to all replicas. - All honest replicas will receive said
propose(c, v, (c', v'))
message byt_0 + 2Δ
and broadcast somenotarize(c, v)
message.
- The first honest replica broadcasts some
- Replicas enter
v + 1
as soon as they see someproof(v)
(as fast asL
messages). If the network is partitioned in two, replicas in each half of the partition may continue to enter successive views (on differentproof(v)
s) but will never finalize conflicting blocks. To bound the depth of forks in a partition, replicas can wait to enter some viewv + k
until they have seenQ
messages in viewv
. - A Byzantine leader could equivocate, sending a distinct proposal to each replica and causing them to broadcast a
notarize(*, v)
for different blocks. After a replica observes≥ L
notarize(*, v)
messages for some* != c
, it will then choose to broadcast anullify(v)
message. Eventually,L
nullify(v)
messages will be received and honest replicas will enterv + 1
(withinΔ
of the first honest replica). - Since at most
f
nodes are Byzantine or faulty, once an honest leader is assigned, it is possible for at leastQ
correct replicas to finalize a block (including all of its ancestors).
10. Extensions
Minimmit can be instantiated in several different ways to tune performance when deployed to production. Some examples are below:
- Use block digests (i.e.
c = hash(block)
) inpropose(c, v, (c', v'))
,notarize(c, v)
, andnotarization(c, v)
messages. - Employ BLS multi-signatures or BLS threshold signatures, like Threshold Simplex, to cap
notarization(c, v)
andnullification(v)
messages at a constant size regardless of the number of replicas. - Attach some recent set of
proof(v)
messages to eachpropose(c, v, (c', v'))
message (to ensure honest replicas that are not yet aware of recent proofs can still broadcast anotarize(c, v)
message for valid blocks). - If
≥ f + 1
notarize(c, v)
messages are observed for someproposal(c, v, (c', v'))
considered invalid, request the missingnotarization(c, v')
ornullification(v')
not found in ourproofs
(that prohibited us from broadcasting anotarize(c, v)
) from the peers that consider it valid. - If stuck in the same view
v
for timet_s
, re-broadcast someproof(v - 1)
(to ensure all correct replicas enterv
) and re-broadcastnotarized
(if not⊥
) andnullified
(if notfalse
). - Assemble and broadcast a
finalization(c, v)
message after finalizing somec
(i.e.≥ Q
notarize(c, v)
messages). This can both help lagging replicas catch up to the finalized tip and make it easier for downstream services to integrate. - Disseminate blocks using
(k,d)
-erasure codes, like DispersedSimplex, Kudzu, and Alpenglow, to avoid a leader broadcast bottleneck. Eachnotarize
message would be augmented with the relevant fragment.k
would be set to the number of replicas, andd
can be set asf+1
so that the replicas only have a bandwidth requirement of about ~5 times the size of the full block. If anotarization
exists, then at leastf+1
honest nodes have been distributed a fragment. This preventsByzantine
nodes from constructing anotarization
without honest nodes being able to reconstruct the block among themselves.d
can be set at higher values like2f+1
to halve the required bandwidth, but replicas would have to ignore any gossipednotarization
messages, instead making sure to gather the2f+1
notarize
messages themselves. - To punish equivocating leaders, treat
propose
messages for different blocks in the same view as a slashable offense. To incentivize performant leaders, issue a reward for any blockc
included in the canonical chain.
Have an idea to simplify, improve, or extend Minimmit? Open a PR or reach out at minimmit@commonware.xyz.