## 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

- Auto
- Light
- Dark

# 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 voter<r then13:return Ignore vote of past round14:end if15:if voter=r+1∧(votep>0∨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:ifp<votepthen44: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:elseifvotes>certthen55: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:

- Vote’s _period_ is not the _current node period_, the _period before_, or the _next period_, or

- Vote’s _period_ is the _next period_, and
  - Its _step_ is nextknextk with k≥1k≥1, or
- Vote’s _period_ is the _current node period_, and
  - Its _step_ is nextknextk with k≥1k≥1, and
  - Its _step_ is not the _current step_, the _step before_, or the _next step_, or
- Vote’s _period_ is the _period before_, and
  - Its _step_ is nextknextk with k≥1k≥1, and
  - Its _step_ distance is not one or less from the node’s _last finished step_.

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_:

- If the vote’s step is proposepropose, and the proposal corresponding to the proposal-value
vv has already been observed, the proposal is broadcast (that is, the node
performs a re-proposal payload broadcast).

- If the vote’s step is SoftSoft, and a softBundlesoftBundle has been
observed with the addition of the vote, the SortitionSortition sub-procedure
is run for every _online_ account managed by the node. Then, a CertCert vote
is cast for each account the lottery selects.

- If the vote’s step is CertCert, and observing the vote causes the node to
observe a CertBundleCertBundle for a proposal-value vv, then it checks if
the full proposal associated with the critical value has been observed. Simultaneous
observation of a CertBundleCertBundle for a value vv and of a proposal
equal to RetrieveProposal(v)RetrieveProposal(v) implies the associated entry is committable.
If the full proposal has not yet been observed, the node may stall and request the
full proposal from the network. Once the desired proposal can be committed, the
node proceeds to commit, start a new round, and garbage collects all transient
data from the round it just finished.

- Finally, if the vote is that of a _recovery step_ (s>certs>cert), and a
BundleBundle has been observed for a given proposal-value vv, then a
_new period_ is started, and the currently executing period-specific data is garbage
collected.
