Consensus protocol overview
Gummiworm’s consensus protocol is split into two cycles:
-
In the fast-paced consensus cycle, the head peers collectively produce and soft-confirm block briefs, one at a time, for newly received user requests.
-
In the slow-paced consensus cycle, the coil operators join the head operators to hard-confirm the effects derived from soft-confirmed block briefs, for whole block stacks at a time.
Splitting consensus in this way provides several advantages:
-
Each block brief contains all the essential decisions that define a block, and the block’s effects are deterministically derived from the block brief. The fast consensus’ focus on block briefs means that users and peers can quickly find out about user requests’ outcomes without slowing down for the derivative/ratifying activity of the slow-consensus.
-
Each block brief requires just one signature from each head peer to be soft-confirmed, so it can always be soft-confirmed in a single signing round. This is perfect for the fast consensus cycle.
- By contrast, due to L1 blockchain limitations, each block effect needs a separate set of signatures from the head and coil peers. These effect signatures can be gathered in parallel, but atomicity sometimes requires two signing rounds to hard-confirm a block’s effects. It’s better to do these signing rounds in the slow consensus cycle.
-
Gummiworm’s network topology and information flow requires all head peers to be connected with each other and responsive at all times. However, coil peers have laxer connectivity and responsiveness requirements. Fast consensus cycle need not slow down for coil peers, while slow consensus gains increased security from involving them.
-
Hard-confirming whole block stacks at a time avoids a lot of redundant signatures. For instance, a block stack of 1000 minor blocks can be hard-confirmed by multi-signing just the last block’s evacuation commitment, which supersedes all the preceding evacuation commitments in the stack.
Leadership schedule
Gummiworm’s configuration sequentially numbers the head peers, starting from zero.
Gummiworm’s leadership schedule assigns a leader to each block number based on the head peer numbers, in round-robin fashion:
type BlockNumber = NonNegativeInteger
type BlockStackNumber = NonNegativeInteger
type HeadPeerNumber = NonNegativeInteger
const isFastLeader = (
blockNum: BlockNumber,
headPeerNum: HeadPeerNumber,
nHeadPeers: NonNegativeInteger,
): boolean => blockNum % nHeadPeers === headPeerNum
const isSlowLeader = (
blockStackNum: BlockStackNumber,
headPeerNum: HeadPeerNumber,
nHeadPeers: NonNegativeInteger,
): boolean => blockStackNum % nHeadPeers === headPeerNumFor example, with five head peers numbered alphabetically (Alice = 0, Bob = 1, …, Erin = 4), the schedule rotates leadership through the peers in order. At any moment, exactly one peer is the leader; the next-in-line peer is the candidate that will become the leader on the next rotation:
Fast consensus uses this schedule to select which head peer produces the current block brief.
Slow consensus uses this schedule to select which head peer defines the current block stack.
Fast and slow consensus each rotate through the leadership schedule independently: at any given time, the fast consensus leader is not necessarily the same as the slow consensus leader.