Vote Handler - Algorand Specifications

Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Algorand Specifications

The algorithms presented in this section abstract away a series of behaviors as a single vote handler for ease of understanding and to provide an implementation-agnostic engineering overview.

In the reference implementation, the vote verification and vote observation, although dependent on each other, are performed by separate processes.

Note that an equivocation vote is a pair of votes that differ only in their proposal values vv. In other words, given a player II and a node’s context tuple (r,p,s)(r,p,s), Equivocation(I,r,p,s)=(Vote(I,r,p,s,v1),Vote(I,r,p,s,v2))Equivocation(I,r,p,s)=(Vote(I,r,p,s,v1),Vote(I,r,p,s,v2)) for some v1≠v2v1≠v2.


Algorithm5: Handle VoteAlgorithm 5: Handle Vote

1: functionValidateVote(vote):2: ifnotVerifyVote(vote)then3: DisconnectFromPeer(SenderPeer(vote))4: returnIgnore invalid vote5: endif6: ifvotes=0∧(vote∈V∨IsEquivocation(vote))then7: returnIgnore vote, equivocation not allowed in proposal votes8: endif9: ifvotes>0∧IsSecondEquivocation(vote)then10:returnIgnore vote if it’s a second equivocation11:endif12:ifvoter<rthen13:returnIgnore vote of past round14:endif15:ifvoter=r+1∧(votep>0∨votes∈{next0,…,next249})then16:returnIgnore vote of next round if non-zero period or next-k step17:endif18:ifvoter=r∧(votep∉{p−1,p,p+1}∨(votep=p+1∧votes∈{next1,…,next249})∨(votep=p∧votes∈{next1,…,next249}∧votes∉{s−1,s,s+1})∨(votep=p−1∧votes∈{next1,…,next249}∧votes∉{s¯−1,s¯,s¯+1}))then19:returnIgnore vote20:endif21: endfunction1: function ValidateVote(vote):2: if not VerifyVote(vote) then3: DisconnectFromPeer(SenderPeer(vote))4: return Ignore invalid vote5: end if6: if votes=0∧(vote∈V∨IsEquivocation(vote)) then7: return Ignore vote, equivocation not allowed in proposal votes8: end if9: if votes>0∧IsSecondEquivocation(vote) then10:return Ignore vote if it’s a second equivocation11:end if12:if voter0∨votes∈{next0,…,next249}) then16:return Ignore vote of next round if non-zero period or next-k step17:end if18:if voter=r∧(votep∉{p−1,p,p+1}∨(votep=p+1∧votes∈{next1,…,next249})∨(votep=p∧votes∈{next1,…,next249}∧votes∉{s−1,s,s+1})∨(votep=p−1∧votes∈{next1,…,next249}∧votes∉{s¯−1,s¯,s¯+1})) then19:return Ignore vote20:end if21: end function

22: functionHandleVote(vote):23:ValidateVote(vote)Check the validity of the vote24:V←V∪voteObserve the vote25:Relay(vote)26:ifvotes=proposethen27:ifRetrieveProposal(votev)≠⊥then28:Broadcast(RetrieveProposal(votev))29:endif30:elseifvotes=softthen31:if∃v:Bundle(voter,votep,soft,v)⊂Vthen32:fora∈Ado33:credentials←Sortition(ask,r,p,cert)34:ifcredentialsj>0then35:Broadcast(Vote(aI,r,p,cert,v,credentials))36:endif37:endfor38:endif39:elseifvotes=certthen40:if∃v:Bundle(voter,votep,cert,v)⊂Vthen41:ifRetrieveProposal(v)=⊥then42:RequestProposal(v)43:ifpvotepthen44:pold←p45:StartNewPeriod(votep)46:GarbageCollect(r,pold)47:endif48:endif49:Commit(v)50:rold←r51:StartNewRound(voter+1)52:GarbageCollect(rold,p)53:endif54:elseifvotescertthen55:if∃v:Bundle(voter,votep,votes,v)⊂Vthen56:pold←p57:StartNewPeriod(votep+1)58:GarbageCollect(r,pold)59:endif60:endif61: endfunction22: function HandleVote(vote):23:ValidateVote(vote)Check the validity of the vote24:V←V∪voteObserve the vote25:Relay(vote)26:if votes=propose then27:if RetrieveProposal(votev)≠⊥ then28:Broadcast(RetrieveProposal(votev))29:end if30:else if votes=soft then31:if ∃v:Bundle(voter,votep,soft,v)⊂V then32:for a∈A do33:credentials←Sortition(ask,r,p,cert)34:if credentialsj>0 then35:Broadcast(Vote(aI,r,p,cert,v,credentials))36:end if37:end for38:end if39:else if votes=cert then40:if ∃v:Bundle(voter,votep,cert,v)⊂V then41:if RetrieveProposal(v)=⊥ then42:RequestProposal(v)43:if p<votep then44:pold←p45:StartNewPeriod(votep)46:GarbageCollect(r,pold)47:end if48:end if49:Commit(v)50:rold←r51:StartNewRound(voter+1)52:GarbageCollect(rold,p)53:end if54:else if votes>cert then55:if ∃v:Bundle(voter,votep,votes,v)⊂V then56:pold←p57:StartNewPeriod(votep+1)58:GarbageCollect(r,pold)59:end if60:end if61: end function

The vote handler is triggered when a node receives a message containing a vote for a given proposal value, round, period, or step.

It first performs a series of checks, and if the received vote passes all of them, then it is broadcast by all accounts selected as the appropriate committee members.

On Line 2, the ValidateVoteValidateVote function checks if the vote is valid. If invalid, this is considered adversarial behavior. Therefore, a node may disconnect from the vote sender node, retrieving the network ID of the original message sender with the ( SenderPeer \ helper network module function.

Equivocation votes on a proposal step are not allowed, so a check for this condition is performed (Line 6).

Furthermore, second equivocations are never allowed (Line 9).

Any votes for rounds before the current round are discarded (Line 12).

In the special case of receiving a message vote for a round immediately after the current round, the node observes it only if it is related to the first period (p=0p=0), in any of the following steps: proposal, soft, cert, late, down, or redo (ignoring votes for further periods p>0p>0 or for nextknextk steps).

Finally, the node checks that (Line 18) if the vote’s round is for the currently executing round, and one of the following:

Then the vote is ignored and discarded. Note that the equivocation vote verification uses the same verification functions, but verifies that both constituent votes are valid separately.

Once finished with the series of validation checks, the vote is observed, relayed, and then processed by the node according to its current context and the vote’s step: