Line data Source code
1 : #ifndef HEADER_fd_src_ballet_bn254_fd_poseidon_h 2 : #define HEADER_fd_src_ballet_bn254_fd_poseidon_h 3 : 4 : /* Implementation of the Poseidon hash function over BN254 scalar field. 5 : Based on Rust light-poseidon v0.2.0: 6 : https://github.com/Lightprotocol/light-poseidon/blob/v0.2.0/light-poseidon/src/lib.rs#L377 7 : That is in turn based on Circom v2.0.x: 8 : https://github.com/iden3/circomlib/blob/v2.0.5/circuits/poseidon.circom */ 9 : 10 : #include "../fd_ballet_base.h" 11 : #include "./fd_bn254_scalar.h" 12 : 13 0 : #define FD_POSEIDON_HASH_SZ (32UL) 14 : #define FD_POSEIDON_MAX_WIDTH (12UL) 15 : 16 : /* Hash result. Actually a value in the bn254 field */ 17 : struct fd_poseidon_hash_result { 18 : uchar v[ FD_POSEIDON_HASH_SZ ]; 19 : }; 20 : typedef struct fd_poseidon_hash_result fd_poseidon_hash_result_t; 21 : 22 : struct FD_ALIGNED fd_poseidon { 23 : fd_bn254_scalar_t state[ 1+FD_POSEIDON_MAX_WIDTH ]; 24 : ulong cnt; /* How many elements have been appended total */ 25 : int big_endian; /* 0 little endian, 1 big endian */ 26 : }; 27 : typedef struct fd_poseidon fd_poseidon_t; 28 : 29 : struct fd_poseidon_par { 30 : fd_bn254_scalar_t const * ark; 31 : fd_bn254_scalar_t const * mds; 32 : fd_bn254_scalar_t const * ark_start; 33 : fd_bn254_scalar_t const * ark_partial; 34 : fd_bn254_scalar_t const * ark_end; 35 : fd_bn254_scalar_t const * pre_sparse_mds; 36 : fd_bn254_scalar_t const * sparse_mds_row; 37 : fd_bn254_scalar_t const * sparse_mds_col; 38 : }; 39 : typedef struct fd_poseidon_par fd_poseidon_par_t; 40 : 41 : FD_PROTOTYPES_BEGIN 42 : 43 : /* fd_poseidon_init starts a Poseidon calculation. 44 : pos is assumed to be a current local join to a Poseidon calculation 45 : state with no other concurrent operation that would modify the state 46 : while this is executing. Any preexisting state for an in-progress or 47 : recently completed calculation will be discarded. 48 : if big_endian>0 treats all inputs (append) and output (fini) as big endian, 49 : otherwise treats them all as little endian. 50 : Returns pos (on return, pos will have the state of a new in-progress 51 : calculation). */ 52 : 53 : fd_poseidon_t * 54 : fd_poseidon_init( fd_poseidon_t * pos, 55 : int const big_endian ); 56 : 57 : /* fd_poseidon_append adds sz bytes locally pointed to by data an 58 : in-progress Poseidon calculation. 59 : out is assumed to be valid (i.e. is a current local join to a Poseidon 60 : calculation state with no other concurrent operations that would modify 61 : the state while this is executing). out==NULL is ok to allow chaining: 62 : fd_poseidon_append( fd_poseidon_append( ... ) ) 63 : data points to the first of the sz bytes, and will be unmodified while 64 : this is running with no interest retained after return. 65 : data represents a bn254 scalar, i.e. a 256-bit bigint modulo a prime, 66 : and must be exactly 32 bytes long. 67 : Returns out on success, NULL in case of error: 68 : - if pos==NULL 69 : - if sz!=32 70 : - if data >= modulus 71 : - if fd_poseidon_append is called more than 12 times on the same pos 72 : 73 : Note: unlike other hash functions, each call to fd_poseidon_append 74 : attempts to append a new scalar to the current state. 75 : This implementation is modeled around Rust light-poseidon, that in 76 : turn is modeled around Circom implementation. 77 : It supports hashing a max of FD_POSEIDON_MAX_WIDTH elements. */ 78 : 79 : fd_poseidon_t * 80 : fd_poseidon_append( fd_poseidon_t * pos, 81 : uchar const * data, 82 : ulong sz ); 83 : 84 : /* fd_poseidon_fini finishes a Poseidon calculation. 85 : out is assumed to be valid (i.e. is a current local join to a Poseidon 86 : calculation state with no other concurrent operations that would modify 87 : the state while this is executing). out==NULL is ok to allow chaining: 88 : fd_poseidon_fini( fd_poseidon_append( ... ) ) 89 : hash points to the first byte of a 32-byte memory region where the 90 : result of the calculation should be stored. 91 : Returns hash, or NULL if pos==NULL (on return, there will be no calculation 92 : in-progress on pos and 32-byte buffer pointed to by hash will be populated 93 : with the calculation result). */ 94 : 95 : uchar * 96 : fd_poseidon_fini( fd_poseidon_t * pos, 97 : uchar hash[ FD_POSEIDON_HASH_SZ ] ); 98 : 99 : FD_PROTOTYPES_END 100 : 101 : #endif /* HEADER_fd_src_ballet_bn254_fd_poseidon_h */