Line data Source code
1 : #ifndef HEADER_fd_src_ballet_bn254_fd_bn254_scalar_h 2 : #define HEADER_fd_src_ballet_bn254_fd_bn254_scalar_h 3 : 4 : /* Implementation of the BN254 scalar field, based on fiat-crypto. 5 : 6 : This covers 2 main use cases: 7 : - scalar validation, used e.g. in BN254 point scalar mul 8 : - scalar arithmetic, used e.g. to compute Poseidon hash 9 : 10 : The primary consumer is Firedancer VM (Solana syscalls). 11 : Therefore, input is little endian and already aligned. */ 12 : 13 : #include "../fd_ballet_base.h" 14 : #include "../bigint/fd_uint256.h" 15 : #include "../fiat-crypto/bn254_scalar_64.c" 16 : 17 : /* The implementation is based on fiat-crypto. 18 : Unfortunately mul is dramatically slow on gcc, so we reimplemented 19 : it in ballet/bigint/uint256_mul.h, based on uint128. 20 : When uint128 is not available we fall back on fiat-crypto. */ 21 : #define USE_FIAT_CRYPTO_MUL !FD_HAS_INT128 22 : 23 : /* fd_bn254_scalar represents a scalar as a buffer of 32 bytes, 24 : or equivalently (on little endian platforms) an array of 4 ulong. */ 25 : typedef fd_uint256_t fd_bn254_scalar_t; 26 : 27 : /* const r, used to validate a scalar field element. 28 : NOT Montgomery. 29 : 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 */ 30 : static const fd_bn254_scalar_t fd_bn254_const_r[1] = {{{ 31 : 0x43e1f593f0000001, 0x2833e84879b97091, 0xb85045b68181585d, 0x30644e72e131a029, 32 : }}}; 33 : 34 : /* const 1/r for CIOS mul */ 35 : static const ulong fd_bn254_const_r_inv = 0xC2E1F593EFFFFFFFUL; 36 : 37 : FD_PROTOTYPES_BEGIN 38 : 39 : /* fd_bn254_scalar_validate validates that the input scalar s 40 : is between 0 and r-1, included. 41 : This function works on 32-byte input buffer with no memory 42 : copies (assuming both platform and input are little endian). */ 43 : static inline int 44 294 : fd_bn254_scalar_validate( fd_bn254_scalar_t const * s ) { 45 294 : return fd_uint256_cmp( s, fd_bn254_const_r ) < 0; 46 294 : } 47 : 48 : static inline fd_bn254_scalar_t * 49 : fd_bn254_scalar_from_mont( fd_bn254_scalar_t * r, 50 63 : fd_bn254_scalar_t const * a ) { 51 63 : fiat_bn254_scalar_from_montgomery( r->limbs, a->limbs ); 52 63 : return r; 53 63 : } 54 : 55 : static inline fd_bn254_scalar_t * 56 : fd_bn254_scalar_to_mont( fd_bn254_scalar_t * r, 57 288 : fd_bn254_scalar_t const * a ) { 58 288 : fiat_bn254_scalar_to_montgomery( r->limbs, a->limbs ); 59 288 : return r; 60 288 : } 61 : 62 : static inline fd_bn254_scalar_t * 63 : fd_bn254_scalar_add( fd_bn254_scalar_t * r, 64 : fd_bn254_scalar_t const * a, 65 208716 : fd_bn254_scalar_t const * b ) { 66 208716 : fiat_bn254_scalar_add( r->limbs, a->limbs, b->limbs ); 67 208716 : return r; 68 208716 : } 69 : 70 : #if USE_FIAT_CRYPTO_MUL 71 : 72 : static inline fd_bn254_scalar_t * 73 : fd_bn254_scalar_mul( fd_bn254_scalar_t * r, 74 : fd_bn254_scalar_t const * a, 75 : fd_bn254_scalar_t const * b ) { 76 : fiat_bn254_scalar_mul( r->limbs, a->limbs, b->limbs ); 77 : return r; 78 : } 79 : 80 : static inline fd_bn254_scalar_t * 81 : fd_bn254_scalar_sqr( fd_bn254_scalar_t * r, 82 : fd_bn254_scalar_t const * a ) { 83 : fiat_bn254_scalar_square( r->limbs, a->limbs ); 84 : return r; 85 : } 86 : 87 : #else 88 : 89 : FD_UINT256_FP_MUL_IMPL(fd_bn254_scalar, fd_bn254_const_r, fd_bn254_const_r_inv) 90 : 91 : static inline fd_bn254_scalar_t * 92 : fd_bn254_scalar_sqr( fd_bn254_scalar_t * r, 93 12846 : fd_bn254_scalar_t const * a ) { 94 12846 : return fd_bn254_scalar_mul( r, a, a ); 95 12846 : } 96 : 97 : #endif 98 : 99 : FD_PROTOTYPES_END 100 : 101 : #endif /* HEADER_fd_src_ballet_bn254_fd_bn254_scalar_h */