Casper FFG votes are (essentially) of the form
vote(target, source), where
target is the checkpoint you’re voting for and
source is a justified ancestor of
source is handy for the safety proof. However,
source isn’t necessary to ensure safety, and I argue removing it - so votes were just of the form
vote(target) - would be a net win. Curious to hear what others think.
Main arguments I see for removing
It’s confusing. “Each validator votes for one branch at each height” is intuitive; “Each validator votes for one branch at each height, linking to a block at an earlier height” is not. Eg, this confused Matthew Green (and me).
It’s not necessary. As I argued in a recent post, safety can be ensured without
source. This also results in a simpler definition of a finalization vote (a boolean
finalize=trueflag included with votes, rather than an explicit reference to the immediate parent checkpoint), and a simpler slashing condition than the “no-spanning rule” - a “no-reneging rule”: “If you vote to finalize A, you can’t vote for conflicting B, unless 2/3 of voters (not including you) voted for ancestor B’ of B at height between A and B.”
As @dlubarov (in June) and @JustinDrake (this month) have argued, the no-spanning rule for
sourceis needlessly strict: it slashes more cases than needed to ensure safety. Eg, it slashes spanning votes even if (as Daniel noted) the spanned vote wasn’t a finalization vote, or (as I noted) if none of the four checkpoints conflict. Slashing more cases than necessary is gratuitous and confusing. Both Daniel and Justin proposed ways the no-spanning rule can be amended to be “tight” (not slash unnecessarily) without removing
source, but removing it is another, arguably more parsimonious solution to consider.
Making voters specify
sourcepointlessly opens the door to bizarre cases. Why let a voter specify a source 100 checkpoints old, if there are 99 more recent justified ones? Why allow the case where 2/3-ε vote for (t, s) and ε vote for (t, s’s parent), resulting in a failed vote for (t, s) rather than what is intuitively a successful 2/3 vote for t?
sourceshould really always be “the most recent ancestor of
targetthat I know to be justified”; letting voters choose any other source just creates opportunities for confusion and unnecessarily failed votes.
(EDIT: Another silly case we enable by making voters specify
source, courtesy of @danrobinson: votes with unjustified
sources. There is really no point to allowing these…)
Main arguments I see for keeping
Casper FFG works fine with
source. Why tinker with it now?
My proposed no-reneging slashing condition that doesn’t rely on source is more complicated to enforce, since “vote v2 spans v1” is easier to check than “vote v2’s target has no justified ancestor at height >v1”. (See discussion in my post.) So, I see this as a question of whether clearer, more parsimonious voting is worth the price of somewhat more elaborate slashing mechanics.
We all want Casper deployed, so now is not the time for cute new features or experimental variants. But I do think we should consider simplifications if they result in greater clarity and cleaner code (and if they work!). Eg: either removing source (as I advocate), or at least tightening up the no-spanning rule (as Justin and, I think, Daniel advocate).