Work towards adding leader rotation to the book

This commit is contained in:
Greg Fitzgerald 2018-11-16 16:25:29 -07:00
parent f4b9e93b11
commit a17f9bd0f4
3 changed files with 449 additions and 0 deletions

13
art/leader-scheduler.bob Normal file
View File

@ -0,0 +1,13 @@
validator action
+----+ ----------------
| | L1 | E1
| +----+ / \ vote(E1)
| | L2 | E2 x
| +----+ / \ / \ vote(E2)
time | | L3 | E3 x E3' x
| +----+ / \ / \ / \ / \ slash(E3)
| | L4 | x x E4 x x x x x
| +----+ | | | | | | | | vote(E4)
v | L5 | xx xx xx E5 xx xx xx xx
+----+ hang on to E4 and E5 for more...

View File

@ -0,0 +1,330 @@
<svg class="bob" font-family="arial" font-size="14" height="208" width="768" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="triangle" markerHeight="8" markerWidth="8" orient="auto" refX="4" refY="2" viewBox="0 0 8 4">
<polygon fill="black" points="0,0 0,4 8,2 0,0"/>
</marker>
<marker id="clear_triangle" markerHeight="10" markerWidth="10" orient="auto" refX="1" refY="7" viewBox="0 0 20 14">
<polygon fill="none" points="2,2 2,12 18,7 2,2" stroke="black" stroke-width="2"/>
</marker>
<marker id="circle" markerHeight="5" markerWidth="5" orient="auto" refX="10" refY="10" viewBox="0 0 20 20">
<circle cx="10" cy="10" fill="black" r="8"/>
</marker>
<marker id="square" markerHeight="5" markerWidth="5" orient="auto" refX="10" refY="10" viewBox="0 0 20 20">
<rect fill="black" height="20" width="20" x="0" y="0"/>
</marker>
<marker id="open_circle" markerHeight="10" markerWidth="10" orient="auto" refX="10" refY="10" viewBox="0 0 20 20">
<circle cx="10" cy="10" fill="white" r="4" stroke="black" stroke-width="2"/>
</marker>
<marker id="big_open_circle" markerHeight="20" markerWidth="20" orient="auto" refX="20" refY="20" viewBox="0 0 40 40">
<circle cx="20" cy="20" fill="white" r="6" stroke="black" stroke-width="2"/>
</marker>
</defs>
<style type="text/css">
line,path {
stroke: black;
stroke-width: 2;
stroke-opacity: 1;
fill-opacity: 1;
stroke-linecap: round;
stroke-linejoin: miter;
}
line.dashed {
stroke-dasharray: 5;
}
circle.solid {
fill:black;
stroke: black;
stroke-width: 2;
stroke-opacity: 1;
fill-opacity: 1;
stroke-linecap: round;
stroke-linejoin: miter;
}
circle.open {
fill:none;
stroke: black;
stroke-width: 2;
stroke-opacity: 1;
fill-opacity: 1;
stroke-linecap: round;
stroke-linejoin: miter;
}
tspan.head{
fill: none;
stroke: none;
}
</style>
<rect fill="white" height="208" width="768" x="0" y="0"/>
<g>
<line marker-end="url(#triangle)" x1="76" x2="76" y1="32" y2="172"/>
</g>
<g>
<line x1="124" x2="124" y1="24" y2="56"/>
<line x1="124" x2="164" y1="24" y2="24"/>
<line x1="124" x2="124" y1="56" y2="88"/>
<line x1="124" x2="164" y1="56" y2="56"/>
<line x1="124" x2="124" y1="88" y2="120"/>
<line x1="124" x2="164" y1="88" y2="88"/>
<line x1="124" x2="124" y1="120" y2="152"/>
<line x1="124" x2="164" y1="120" y2="120"/>
<line x1="124" x2="124" y1="152" y2="184"/>
<line x1="124" x2="164" y1="152" y2="152"/>
<line x1="124" x2="164" y1="184" y2="184"/>
<line x1="164" x2="164" y1="24" y2="56"/>
<line x1="164" x2="164" y1="56" y2="88"/>
<line x1="164" x2="164" y1="88" y2="120"/>
<line x1="164" x2="164" y1="120" y2="152"/>
<line x1="164" x2="164" y1="152" y2="184"/>
</g>
<g>
<line x1="188" x2="188" y1="144" y2="160"/>
</g>
<g>
<line x1="200" x2="208" y1="128" y2="112"/>
</g>
<g>
<line x1="224" x2="236" y1="112" y2="136"/>
</g>
<g>
<line x1="232" x2="240" y1="96" y2="80"/>
</g>
<g>
<line x1="236" x2="236" y1="144" y2="160"/>
</g>
<g>
<line x1="260" x2="260" y1="144" y2="160"/>
</g>
<g>
<line x1="264" x2="272" y1="64" y2="48"/>
</g>
<g>
<line x1="272" x2="280" y1="80" y2="96"/>
</g>
<g>
<line x1="272" x2="280" y1="128" y2="112"/>
</g>
<g>
<line x1="304" x2="316" y1="112" y2="136"/>
</g>
<g>
<line x1="316" x2="316" y1="144" y2="160"/>
</g>
<g>
<line x1="348" x2="360" y1="136" y2="112"/>
</g>
<g>
<line x1="348" x2="348" y1="144" y2="160"/>
</g>
<g>
<line x1="368" x2="376" y1="96" y2="80"/>
</g>
<g>
<line x1="376" x2="384" y1="48" y2="64"/>
</g>
<g>
<line x1="376" x2="388" y1="112" y2="136"/>
</g>
<g>
<line x1="388" x2="388" y1="144" y2="160"/>
</g>
<g>
<line x1="416" x2="424" y1="80" y2="96"/>
</g>
<g>
<line x1="420" x2="420" y1="144" y2="160"/>
</g>
<g>
<line x1="436" x2="420" y1="104" y2="136"/>
</g>
<g>
<line x1="448" x2="460" y1="112" y2="136"/>
</g>
<g>
<line x1="460" x2="460" y1="144" y2="160"/>
</g>
<g>
<line x1="512" x2="640" y1="24" y2="24"/>
</g>
<g>
<text x="17" y="108">
time
</text>
</g>
<g>
<text x="137" y="44">
L1
</text>
</g>
<g>
<text x="137" y="76">
L2
</text>
</g>
<g>
<text x="137" y="108">
L3
</text>
</g>
<g>
<text x="137" y="140">
L4
</text>
</g>
<g>
<text x="137" y="172">
L5
</text>
</g>
<g>
<text x="185" y="140">
x
</text>
</g>
<g>
<text x="185" y="172">
xx
</text>
</g>
<g>
<text x="209" y="108">
E3
</text>
</g>
<g>
<text x="225" y="172">
xx
</text>
</g>
<g>
<text x="249" y="76">
E2
</text>
</g>
<g>
<text x="257" y="140">
E4
</text>
</g>
<g>
<text x="257" y="172">
xx
</text>
</g>
<g>
<text x="289" y="108">
x
</text>
</g>
<g>
<text x="305" y="172">
E5
</text>
</g>
<g>
<text x="313" y="44">
E1
</text>
</g>
<g>
<text x="337" y="172">
xx
</text>
</g>
<g>
<text x="361" y="108">
E3&#39;
</text>
</g>
<g>
<text x="377" y="172">
xx
</text>
</g>
<g>
<text x="393" y="76">
x
</text>
</g>
<g>
<text x="409" y="172">
xx
</text>
</g>
<g>
<text x="449" y="172">
xx
</text>
</g>
<g>
<text x="513" y="12">
validator
</text>
</g>
<g>
<text x="513" y="60">
vote(E1)
</text>
</g>
<g>
<text x="513" y="92">
vote(E2)
</text>
</g>
<g>
<text x="513" y="124">
slash(E3)
</text>
</g>
<g>
<text x="513" y="156">
vote(E4)
</text>
</g>
<g>
<text x="513" y="188">
hang
</text>
</g>
<g>
<text x="553" y="188">
on
</text>
</g>
<g>
<text x="577" y="188">
to
</text>
</g>
<g>
<text x="593" y="12">
action
</text>
</g>
<g>
<text x="601" y="188">
E4
</text>
</g>
<g>
<text x="625" y="188">
and
</text>
</g>
<g>
<text x="657" y="188">
E5
</text>
</g>
<g>
<text x="681" y="188">
for
</text>
</g>
<g>
<text x="713" y="188">
more...
</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

106
src/leader_scheduler.md Normal file
View File

@ -0,0 +1,106 @@
# Leader Rotation
A property of any permissionless blockchain is that the entity choosing the next block is randomly selected. In proof of stake systems,
that entity is typically called the "leader" or "block producer." In Solana, we call it the leader. Under the hood, a leader is
simply a mode of the fullnode. A fullnode runs as either a leader or validator. In this chapter, we describe how a fullnode determines
what node is the leader, how that mechanism may choose different leaders at the same time, and if so, how the system converges in response.
## Leader Seed Generation
Leader selection is decided via a random seed. The process is as follows:
1. Periodically, at a specific PoH tick count, select the signatures of the votes that made up the last supermajority
2. Concatenate the signatures
3. Hash the resulting string for `N` counts
4. The resulting hash is the random seed for `M` counts, `M` leader periods, where M > N
## Leader Rotation
1. The leader is chosen via a random seed generated from stake weights and votes (the leader schedule)
2. The leader is rotated every `T` PoH ticks (leader period), according to the leader schedule
3. The schedule is applicable for `M` voting rounds
Leader's transmit for a count of `T` PoH ticks. When `T` is reached all the validators should switch to the next scheduled leader. To schedule leaders, the supermajority + `M` nodes are shuffled using the above calculated random seed.
All `T` ticks must be observed from the current leader for that part of PoH to be accepted by the network. If `T` ticks (and any intervening transactions) are not observed, the network optimistically fills in the `T` ticks, and continues with PoH from the next leader.
## Partitions, Forks
Forks can arise at PoH tick counts that correspond to leader rotations, because leader nodes may or may not have observed the previous leader's data. These empty ticks are generated by all nodes in the network at a network-specified rate for hashes/per/tick `Z`.
There are only two possible versions of the PoH during a voting period: PoH with `T` ticks and entries generated by the current leader, or PoH with just ticks. The "just ticks" version of the PoH can be thought of as a virtual ledger, one that all nodes in the network can derive from the last tick in the previous period.
Validators can ignore forks at other points (e.g. from the wrong leader), or slash the leader responsible for the fork.
Validators vote on the longest chain that contains their previous vote, or a longer chain if the lockout on their previous vote has expired.
#### Validator's View
##### Time Progression
The diagram below represents a validator's view of the PoH stream with possible forks over time. L1, L2, etc. are leader periods, and `E`s represent entries from that leader during that leader's period. The `x`s represent ticks only, and time flows downwards in the diagram.
<img alt="Leader scheduler" src="img/leader-scheduler.svg" class="center"/>
Note that an `E` appearing on 2 branches at the same period is a slashable condition, so a validator observing `L3` and `L3'` can slash L3 and safely choose `x` for that period. Once a validator observes a supermajority vote on any branch, other branches can be discarded below that tick count. For any period, validators need only consider a single "has entries" chain or a "ticks only" chain.
##### Time Division
It's useful to consider leader rotation over PoH tick count as time division of the job of encoding state for the network. The following table presents the above tree of forks as a time-divided ledger.
leader period | L1 | L2 | L3 | L4 | L5
-------|----|----|----|----|----
data | E1| E2 | E3 | E4 | E5
ticks to prev | | | | x | xx
Note that only data from leader L3 will be accepted during leader period L3.
Data from L3 may include "catchup" ticks back to a period other than L2 if L3
did not observe L2's data. L4 and L5's transmissions include the "ticks to
prev" PoH entries.
This arrangement of the network data streams permits nodes to save exactly this
to the ledger for replay, restart, and checkpoints.
#### Leader's View
When a new leader begins a period, it must first transmit any PoH (ticks)
required to link the new period with the most recently observed and voted
period.
## Examples
### Small Partition
1. Network partition M occurs for 10% of the nodes
2. The larger partition K, with 90% of the stake weight continues to operate as
normal
3. M cycles through the ranks until one of them is leader, generating ticks for
periods where the leader is in K.
4. M validators observe 10% of the vote pool, finality is not reached.
5. M and K re-connect.
6. M validators cancel their votes on M, which has not reached finality, and
re-cast on K (after their vote lockout on M).
### Leader Timeout
1. Next rank leader node V observes a timeout from current leader A, fills in
A's period with virtual ticks and starts sending out entries.
2. Nodes observing both streams keep track of the forks, waiting for: a. their
vote on leader A to expire in order to be able to vote on B b. a
supermajority on A's period
3. If a occurs, leader B's period is filled with ticks, if b occurs, A's period
is filled with ticks
4. Partition is resolved just like in the [Small Partition](#small-parition) above
## Network Variables
`M` - number of nodes outside the supermajority to whom leaders broadcast their
PoH for validation
`N` - number of voting rounds for which a leader schedule is considered before
a new leader schedule is used
`T` - number of PoH ticks per leader period (also voting period)
`Z` - number of hashes per PoH tick