A variable having type .
An array of elements each of type .
An matrix having elements of type .
The identity matrix.
An array of matrices.
A bit .
An array of bits.
A prime field element .
An integer in .
A non-negative integer.
A positive integer.
The range of integers . Note that .
The range of integers .
Note: all arrays and matrices are indexed starting at zero. An array of elements has indices .
Returns the element of array . When the notation is cumbersome is used instead.
Returns a slice of the array : .
Concatenates two arrays and , of types and respectively, producing an array of type . The above is equivalent to writing .
Creates an array using list comprehension; each element of the array is the output of the expression at each element of the input sequence (e.g. ).
Element-wise field addition of two equally lengthed vectors of field elements . The above is equivalent to writing .
Reverses the elements of a vector , i.e. the first element of is the last element of .
Returns the value of matrix at row column .
Returns the row of matrix .
Returns the column of matrix .
Returns a submatrix of which excludes 's first row and first column (here is an matrix).
Matrix-matrix multiplication of two matrices of field elements and which produces a matrix of type . Note that where the dot product uses field multiplication.
The inverse of a square matrix, i.e. returns the matrix such that .
Vector-matrix multiplication of a row vector of field elements with a matrix of field elements , note that and . The product is a row vector of length (the number of matrix columns). The element of the product vector is the dot product of and the column of . Note that dot products use field multiplication.
Matrix-vector multiplication of a volumn vector and matrix , note that and . The product is a column vector whose length is equal to the number of rows of . The element of the product vector is the dot product of the row of with . Note that dot products use field multiplication.
Note: when is symmetric (the row of equals the column of ), i.e. the row vector-matrix product and matrix-column vector product contain the same elements when is symmetric.
Addition in of two field elements and .
Exponentiation in of a field element to an integer power .
Bitwise XOR.
XOR's all values of a sequence. The above is equivalent to writing .
A bit array can be written as an array or as a bitstring . The leftmost bit of the bitstring corresponds to the first bit in the array.
Note: the leftmost digit of an integer is the most significant, thus a right-shift by bits is defined: .
Converts an integer into its -bit binary representation. The most-significant bit () is first (leftmost) in the produced bit array . The above is equivalent to writing . For example, .
Converts a bit array into a unsigned (non-negative) integer where the first bit in is the most significant (). The above is equivalent to writing .
The prime field modulus.
The security level measured in bits. Poseidon allows for 80, 128, and 256-bit security levels.
The width of a Poseidon instance; the length in field elements of an instance's internal array. The width is equal to the preimage length plus the output length, where output length is equal to the number of field elements required to achieve the targeted security level in a field of size . Stated another way, each field element in a Poseidon digest provides and additional bits of security.
A Poseidon instance. Each instance is fully specified using this parameter triple.
The S-box function's exponent , where . Poseidon allows for exponents -1, 3, and 5.
The number of full rounds. is even.
The number of partial rounds.
The total number of rounds
Half the number of full rounds.
The index of a round.
The round index for a first-half full round.
The round index for a second-half full round.
The round index for a partial round.
A Poseidon instance's internal state array of field elements which are transformed in each round.
The round constants for an unoptimized Poseidon instance.
The round constants for round for an unoptimized Poseidon instance, that are added to before round 's S-boxes.
The round constants for an optimized Poseidon instance. There are no constants associated with the last full round .
The round constants that are added to Poseidon's array before the S-boxes in the first round of an optimized Poseidon instance.
The round constants that are added to Poseidon's array after the S-boxes in round in an optimized Poseidon instance. Partial rounds have a single round constant, full rounds (excluding the last) have constants. The last full round has no round constants.
The MDS matrix for a Poseidon instance.
The pre-sparse matrix used in MDS mixing for the last first-half full round () of an optimized Poseidon instance.
An array of sparse matrices used in MDS mixing for the partial rounds of the optimized Poseidon algorithm.
The parameter triple fully specifies a unique instance of Poseidon (a hash function that uses the same constants and parameters and performs the same operations). All other Poseidon parameters and constants are derived from the instantiation parameters.
The S-box exponent is derived from the field modulus such that and .
The round numbers and are derived from the field size and security level .
The are derived from .
The MDS matrix is derived from the width .
The allowed preimage sizes are .
The total number of operations executed per hash is determined by the width and number of rounds .
Note: the following are the Poseidon instantiation parameters used within Filecoin and do not represent all possible Poseidon instances.
The Poseidon prime field modulus in base-10 and base-16. Filecoin uses BLS12-381's scalar field as the Poseidon prime field , i.e. is the order of BLS12-381's prime order subgroup . The bit-length of is bits.
Filecoin targets the 128-bit security level.
The size in field elements of Poseidon's internal state; equal to the preimage length (a Filecoin Merkle tree arity) plus 1 for the digest length (the number of field elements required to target the -bit security level via a 256-bit prime ). Filecoin's Poseidon instances take preimages of varying lengths (2, 4, 8, and 11 field elements) and always return one field element.
The S-box function's exponent. It is required that is relatively prime to , which is true for Filecoin's choice of .
The Poseidon round numbers are the number of full and partial rounds for a Poseidon instance . The round numbers are chosen such that they minimize the total number of S-boxes:
while providing security against known attacks (statistical, interpolation, and Gröbner basis).
The number of full and partial rounds, both are positive integers and is even.
and are calculated using either the Python script calc_round_numbers.py
or the neptune
Rust library, denoted . Both methods calculate the round numbers via brute-force; by iterating over all reasonable values for and and choosing the pair that satisfies the security inequalities (provided below) while minimizing the number of S-boxes.
The round numbers and are chosen such that they satisfy the following inequalities. The symbol is used to indicate that an inequality simplifies when Filecoin's Poseidon parameters and are plugged in.
Equivalent to writing (Appendix C.1.1 in the Poseidon paper). This is always satisfied for Filecoin's choice of and .
The minimum necessary to prevent statistical attacks (Eq. 2 Section 5.5.1 in the Poseidon paper where and for ).
The minimum number of total rounds necessary to prevent interpolation attacks (Eq. 3 Section 5.5.2 of the Poseidon paper).
The minimum number of total rounds required to prevent against Gaussian elimination attacks (both equations must be satisfied, Eq. 5 from Section 5.5.2 of the Poseidon paper).
Note: this section gives the round constants for only the unoptimized Poseidon algorithm.
For each Poseidon instance an array containing field elements is generated ( field elements per round ) using the Grain-LFSR stream cipher whose 80-bit state is initialized to , an encoding of the Poseidon instance.
The round constants for round for an unoptimized Poseidon instance.
Specifies the field type as prime or binary. Filecoin always uses a prime field , however Poseidon also can be instantiated using a binary field .
Specifies the S-box exponent . Filecoin uses .
The bit-length of the field modulus.
Initializes the Grain-LFSR stream cipher which is used to derive for a Poseidon instance .
The MDS matrix for a Poseidon instance of width . The superscript denotes a multiplicative inverse . The MDS matrix is invertible and symmetric.
Every preimage hashed is associated with a hash type to encode the Poseidon application, note that is specified per preimage and does not specify a Poseidon instance.
Filecoin uses two hash types and to designate a preimage as being for a Merkle tree of arity or being for no specific application, but having a length .
The determines the and used for a preimage, which give the first element of Poseidon's initial state:
The allowed hash types in which to hash a preimage for a Poseidon instance . It is required that .
Encodes the Poseidon application within the first Poseidon initial state element for a preimage.
The padding that is applied to Poseidon's initial state. A of results in no applied padding; a of pads the last elements of Poseidon's initial to zero.
The Posiedon hash function takes a preimage of prime field elements to a single field element. Poseidon operates on an internal state of field elements which, in the unoptimized algorithm, are transformed over number of rounds of: round constant addition, S-boxes, and MDS matrix mixing. Once all rounds have been performed, Poseidon outputs the second element of the state.
A Posiedon hash function is instantiated by a parameter triple which sets the prime field, the security level, and the size of Poseidon's internal state buffer . From the remaining Poseidon parameters are computed , i.e. the S-box exponent, the round numbers, the round constants, and the MDS matrix.
The S-box function is defined as:
The is initialized to the concatenation of the , , and :
Every round begins with field additions of the with that round's constants :
If is a full round, i.e. or , the S-box function is applied to each element of :
otherwise, if is a partial round , the S-box function is applied to the first element exclusively:
Once the S-boxes have been applied for a round, the is transformed via vector-matrix multiplication with the MDS matrix :
After rounds of the above procedure, Poseidon outputs the digest .
Filecoin's rust library neptune
implements the Poseidon hash function. The library differentiates between unoptimized and optimized Poseidon using the terms correct and static respectively.
The primary differences between the two versions are:
For a given Poseidon instance the optimized and unoptimized algorithms will produce the same output when provided with the same input.
Given the round constants and MDS matrix for a Poseidon instance, we are able to derive round constants for the corresponding optimized Poseidon instance.
The round constants for a Poseidon instance's optimized hashing algorithm. Each full round is associated with round constants, while each partial round is associated with one constant.
Algorithm Comments:
Note: denotes a row vector-matrix multiplication which outputs a row vector.
Line 2. The first round constants are unchanged. Note that both and are used in the first optimized round .
Lines 3-4. For each first-half full round, transform the round constants into .
Line 5. Create a variable to store the round constants for the partial rounds (in reverse order).
Line 6. Create and initialize a variable that is transformed and added to in each loop iteration.
Lines 7-11. For each partial round (starting from the greatest partial round index and proceeding to the least ) transform into , take its first element as a partial round constant, then perform element-wise addition with . The value of at the end of the loop iteration is:
Line 12. Set the last first-half full round's constants using the final value of .
Line 13. Set the partial round constants.
Lines 14-15. Set the remaining full round constants.
The first constants in are added to prior to applying the S-box in the first round round .
For each round excluding the last , is added to the Poseidon after that round's S-box has been applied.
A sparse matrix is a square matrix whose first row and first column are utilized and where all other entries are the identity matrix :
The MDS matrix is factored into a non-sparse matrix and an array of sparse matrices (one matrix per partial round). is used in MDS mixing for the last first-half full round . Each matrix of is used in MDS mixing for a partial round. The first sparse matrix is used in the first partial round () and the last sparse matrix is used in the last partial round ().
The pre-sparse matrix (a non-sparse matrix) used in MDS mixing for the last full round of the first-half . Like the MDS matrix , the pre-sparse matrix is symmetric.
The array of sparse matrices that is factored into, which are used for MDS mixing in the optimized partial rounds.
Algorithm Comments:
Line 1. An array containing the sparse matrices that is factored into.
Line 2. A matrix that is repeatedly factored into a non-sparse matrix and a sparse matrix , i.e. .
Lines 3-6. In each loop iteration we factor into and . The first loop iteration calculates the sparse matrix used in MDS mixing for last partial round . The last loop iteration calculates the sparse matrix used in MDS mixing for the first partial round (i.e. ).
Line 6. is a matrix-matrix multiplication which produces a matrix.
The function factors a non-sparse matrix into a non-sparse matrix and sparse matrix such that .
Algorithm Comments:
Line 1. is a submatrix of which excludes 's first row and first column.
Line 2. is a copy of where 's first row and first column have been replaced with .
Line 3. is a column vector whose values are the first column of excluding 's first row.
Line 4. is the matrix-column vector product of and .
Line 5. is a sparse matrix whose first row is the first row of , remaining first column is , and remaining entries are the identity matrix.
The optimized Poseidon hash function is instantiated in the same way as the unoptimized algorithm, however the optimized Poseidon algorithm requires the additional precomputation of round constants , a pre-sparse matrix , and sparse matrices .
Prior to the first round , the is initialized and added to the pre-first round constants :
For each full round of the first-half : the S-box function is applied to each element of , the output of each S-box is added to the associated round constant in , and MDS mixing occurs between and the MDS matrix (when ) or the pre-sparse matrix (when ).
For each partial round the S-box function is applied to the first element, the round constant is added to the first element, and MDS mixing occurs between the and the sparse matrix (the partial round is associated with sparse matrix where ):
The second half of full rounds proceed in the same way as the first half of full rounds except that all MDS mixing uses the MDS matrix and that the last round does not add round constants into .
After performing rounds, Poseidon outputs the digest .
Algorithm Comments:
Line 1. Initialize the .
Line 2. Adds the pre- round constants.
Lines 3-4. Performs all but the last first-half of full rounds .
Line 5. Performs the last first-half full round .
Lines 6-8. Performs the partial rounds . Mixing in the partial round, where , is done using the sparse matrix .
Lines 9-10. Performs all but the last second-half full rounds .
Line 11. Performs the last second-half rull round .