$$ \newcommand \PSfunction {\textbf{function }} \newcommand \PSreturn {\textbf{return }} \newcommand \PSendfunction {\textbf{end function}} \newcommand \PSswitch {\textbf{switch }} \newcommand \PScase {\textbf{case }} \newcommand \PSdefault {\textbf{default}} \newcommand \PSendswitch {\textbf{end switch}} \newcommand \PSfor {\textbf{for }} \newcommand \PSendfor {\textbf{end for}} \newcommand \PSwhile {\textbf{while }} \newcommand \PSendwhile {\textbf{end while}} \newcommand \PSdo {\textbf{ do}} \newcommand \PSif {\textbf{if }} \newcommand \PSelseif {\textbf{else if }} \newcommand \PSelse {\textbf{else}} \newcommand \PSthen {\textbf{ then}} \newcommand \PSendif {\textbf{end if}} \newcommand \PSnot {\textbf{not }} \newcommand \PScomment {\qquad \small \textsf} $$
$$ \newcommand \VRF {\mathrm{VRF}} \newcommand \Prove {\mathrm{Prove}} \newcommand \ProofToHash {\mathrm{ProofToHash}} \newcommand \Secrets {\mathrm{Secrets}} \newcommand \Rerand {\mathrm{Rerand}} $$
Seed Calculation
The cryptographic seed is a source of randomness for many internal operations inside the protocol.
A formal definition of the seed can be found in the normative specification.
This section provides an engineering and implementation-oriented way of conceptualizing the seed computation, to ease its understanding.
The following algorithm makes heavy use of \( \VRF \) specific functions. For more information on their definition and internal work, refer to the Algorand Cryptographic Primitive Specification.
Notation
For the seed calculation algorithm, consider the following notation:
SYMBOL | DESCRIPTION |
---|---|
\( I \) | Player address |
\( L \) | Ledger (blocks and present sate) |
\( r \) | Current protocol round |
\( p \) | Current protocol period |
\( \delta_s \) | Seed lookback (rounds) |
\( \delta_r \) | Seed refresh interval (rounds) |
\( L[r - n] \) | Block \( r - n \) of the ledger |
\( L[r - n]_Q \) | Seed of the block \( r - n \) of the ledger |
\( H(x) \) | Hash of \( x \) |
\( \VRF \) | Verifiable Random Function |
\( \VRF.\Prove \) | Computes the proof \( y \) of the \( \VRF \) |
\( \VRF.\ProofToHash \) | Computes the hash of \( y \) |
\( Q \) | Randomness seed |
Algorithm
For the seed calculation algorithm, consider the following pseudocode:
\( \textbf{Algorithm 1} \text{: Compute Seed and Proof} \)
$$ \begin{aligned} &\text{1: } \PSfunction \mathrm{ComputeSeedAndProof}(I) \\ &\text{2: } \quad \PSif p = 0 \PSthen \\ &\text{3: } \quad \quad y \gets \VRF.\Prove(\Secrets(I)_{\text{VRFkey}}, L[r - \delta_s]_Q) \\ &\text{4: } \quad \quad \alpha \gets H(I || \VRF.\ProofToHash(y)) \\ &\text{5: } \quad \PSelse \\ &\text{6: } \quad \quad y \gets 0 \\ &\text{6: } \quad \quad \alpha \gets H(L[r - \delta_s]_Q) \\ &\text{7: } \quad \PSendif \\ &\text{9: } \quad \PSif r \bmod (\delta_s\delta_r) < \delta_s \PSthen \\ &\text{10:} \quad \quad Q \gets H(\alpha || H(L[r - \delta_s \delta_r])) \\ &\text{11:} \quad \PSelse \\ &\text{12:} \quad \quad Q \gets H(\alpha) \\ &\text{13:} \quad \PSendif \\ &\text{14:} \quad \PSreturn (Q, y) \\ &\text{15: } \PSendfunction \end{aligned} $$
⚙️ IMPLEMENTATION
Seed computation reference implementation.
The function takes as input the address \( I \) of an online player who will be computing the seed \( Q \).
Note that the player needs to have registered participation keys on the node computing the seed, so as for the \( \Secrets(I) \) call (Algorithm 1, line 3) to retrieve available \( \VRF \) secrets generated during that registration process.
For more information on the types of keys a player has to use, refer to the Algorand Participation Key Specification.
The function computes the cryptographic seed appended to the block candidate for round \( r \), which will be used (if said block candidate is committed) as a source of randomness for the \( \VRF \) in a future round.
The seed is computed according to whether the function is called in the first period of the round, \( p = 0 \), or not.
The function also computes the proof \( y \), bundled up with the block inside a proposal structure (for broadcasting), and used by nodes receiving the proposal as part of the proposal validation process.
Example
The following is an example of seed computation in three adjacent blocks, chosen to show both branches of the Algorithm 1 execution, according to \( r \bmod \delta_s\delta_r \) condition, also known as re-randomization.
Noting that:
- \( \delta_s = 2 \),
- \( \delta_r = 80 \).
We define \( \Rerand(r) = r \bmod \delta_s\delta_r \).
When \( \Rerand(r) < \delta_s \) we say we are re-randomizing the seed \( Q \) for the round \( r \).
📎 EXAMPLE
Take the process for a player with address \( I \) at the first consensus attempt of the round (\( p = 0 \)).
- Let’s consider round \( r_a = 48182880 \), as
$$ \Rerand(r_a) = 48182880 \bmod 160 = 0 < \delta_s $$
The computation is:
- Get the seed \( Q \) for round \( r_a - \delta_s = (48182880 - 2) = 48182878 \),
- Construct a \( \VRF \) proof \( y \) with that seed,
- Convert the \( \VRF \) proof \( y \) to a \( \VRF \) proof hash (named \( \VRF_h \)),
- Hash the object \( \{I || \VRF_h\} \) (named \( \alpha \)),
- Lookup the block digest of the old round \( r_a - \delta_s\delta_r = 48182880 - 160 = 48182720 \) (named \( H_\text{old}\)),
- Calculate the final seed by hashing the object \( \{\alpha, H_\text{old} \} \).
- This process will be the same for \( r_b = 48182881 \) as
$$ \Rerand(r_b) = 48182881 \bmod 160 = 1 < \delta_s $$
- For the round \( r_c = 48182882 \), since
$$ Rerand(r_c) = 48182882 \bmod 160 = 2 \ge \delta_s $$
The computation is:
- Get the seed \( Q \) for round \( r_c - \delta_s = (48182882 - 2) = 48182880 \),
- Construct a \( \VRF \) proof \( y \) with that seed,
- Convert the \( \VRF \) proof \( y \) to a \( \VRF \) proof hash (named \( \VRF_h \)),
- Hash the object \( \{I || \VRF_h\} \) (named \( \alpha \)),
- Calculate the final seed by hashing \( \alpha \).
- This process will be the same for rounds \( 48182883, \ldots, 48183039 \) as
$$ \Rerand(48182883, \ldots, 48183039) > \delta_s. $$
If during the execution of consensus for a given round, a period \( p > 0 \) is observed (i.e., the protocol is performing a new consensus attempt for the same round), steps 2-3-4 change calculating \( \alpha \) by hashing the seed of a round \( r - \delta_s \) (instead of the object \( \{I || \VRF_h\}\ \)). This condition occurs when another proposal for the same round has to be created. In this case, to avoid the possibility of seed manipulation by malicious proposers, their input is excluded from the computation (as the process uses a seed that is \( \delta_s \) rounds in the past, outside potential attacker’s influence).