This is a part of research for an ongoing project, so this is more of
a braindump. Read the original Gasper paper here.
⚠ NOTE: This is a WIP ⚠
Gasper is the consensus protocol used by Ethereum. It’s composed of 2 gadgets:
Validators have 2 jobs: propose blocks and make attestations
V
, return single leaf
block B
to propose
B
C
slots, used to checkpoint for finality
(Casper!)
C=64
in production(B, i)
and (B, j)
for different
epochs i
and j
B
and epoch
j
, define EBB(B, j)
as function that gets
block in highest slot by epoch j
in chain(B)
j
in
chain(B)
LEBB(B) = max([EBB(B, j) for j in epochs])
(latest
EBB in chain(B)
)B
, EBB(B, 0) = genesis()
slot(B) = jC
for some j
, B
is EBB in all chains that include B
B
is last block in epoch j
,
it’s EBB for all chains that include B
B
to be EBB for blocks in different
epochs → why we have (B, j)
notationdef lmdGhost(G: view) -> block:
B = genesis() # genesis block
M = latestAttestations() # one attestation per validator
while B not in G.leaves:
B = argmax([weight(G, child, M) for child in B.children])
return B
i = jC+k
P
picked randomly for each slot and does runs
HLMD(view(P, i)) = B’
to propose B’
B’
has slot(B) = i
,
B’.parent = B
, newattests(B)
, and other
metadata
newattests(B)
is all attestations for B
and not included in newattests(B*)
for ancestor
B*
of B
B
seen but parents not,
newattests(B)
ignored
(i + ½)
, validator V
finds
B’ = HLMD(view(V, i+½))
and make attestation a
slot(a) = jC + k
block(a) = B’
⇒ a
attests to
block(a)
slot(block(a)) ≤ slot(a)
(A, j’) → (B, j)
(via checkpoint
edge)G
, a justified pair is
J(·)
= justified pairs for view(A, j’)
in J(G)
and checkpoint edge
from (A, j’) → (B, j)
⇒ (B, j)
in
J(G)
(B_gen, 0)
in J(G)
def protoHLMD(G: view) -> block:
(B_j, j) = getHighestEpochJustifiedPair(G)
B = B_j
M = latestAttestations()
while B not in G.leaves:
B = argmax([weight(G, child, M) for child in B.children])
return B
def HLMD(G: view) -> block:
(B_j, j) = max([J(l) for l in G.leaves]) # only leaves
B’ = [(B_j, j) in J(l) for l in G.leaves]
B = B_j, G’ = union([chain(b) for b in B’])
M = latestAttestations()
while B not in G’.leaves:
B = argmax([weight(G’, child, M) for child in B.children])
return B
B_l
stores state of its last justified
pairM
but NOT Casper attestations (frozen!)