LCOV - code coverage report
Current view: top level - flamenco/vm/syscall - fd_vm_syscall_big_mod_exp.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 73 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 5 0.0 %

          Line data    Source code
       1             : #include "fd_vm_syscall.h"
       2             : 
       3             : #if FD_HAS_S2NBIGNUM
       4             : 
       5             : #include "../../../ballet/bigint/fd_big_mod_exp.h"
       6             : 
       7             : /* sol_big_mod_exp (SIMD-0529): result = (base ^ exponent) mod modulus.
       8             : 
       9             :    All operands and the result are little-endian unsigned integers; the
      10             :    modulus must be odd and > 1.  The computation lives in ballet
      11             :    (fd_big_mod_exp, wrapping s2n-bignum); this file handles the syscall
      12             :    ABI: reading params, validating, the compute-unit cost model, and
      13             :    writing the result.
      14             : 
      15             :    The syscall is gated behind the enable_big_mod_exp_syscall feature
      16             :    (registration in fd_vm_syscall.c); if it runs, the feature is active. */
      17             : 
      18             : /* SIMD-0529 cost-model constants. */
      19             : #define FD_BIG_MOD_EXP_BASE_CU                           (50UL)
      20           0 : #define FD_BIG_MOD_EXP_MULT_COMPLEXITY_CONSTANT          (22UL)
      21           0 : #define FD_BIG_MOD_EXP_SETUP_MULTIPLICATIONS             (12UL)
      22           0 : #define FD_BIG_MOD_EXP_MULTIPLICATIONS_PER_EXPONENT_WORD (80UL)
      23           0 : #define FD_BIG_MOD_EXP_CU_DIVISOR                        ( 4UL)
      24           0 : #define FD_BIG_MOD_EXP_MOD_REDUCTION_CU_DIVISOR          (15UL)
      25             : 
      26             : /* BigModExpParams as laid out in VM memory (repr(C), 48 bytes, 8-byte
      27             :    aligned).  Pointers are VM virtual addresses. */
      28             : struct fd_vm_big_mod_exp_params {
      29             :   ulong base;          /* vaddr */
      30             :   ulong base_len;
      31             :   ulong exponent;      /* vaddr */
      32             :   ulong exponent_len;
      33             :   ulong modulus;       /* vaddr */
      34             :   ulong modulus_len;
      35             : };
      36             : typedef struct fd_vm_big_mod_exp_params fd_vm_big_mod_exp_params_t;
      37             : 
      38             : /* mult_complexity per SIMD-0529 */
      39             : static inline ulong
      40           0 : fd_big_mod_exp_mult_complexity( ulong operand_words ) {
      41           0 :   return operand_words*operand_words + FD_BIG_MOD_EXP_MULT_COMPLEXITY_CONSTANT;
      42           0 : }
      43             : 
      44             : /* adjusted_exponent_length per SIMD-0529 (EIP-198 form), over the
      45             :    little-endian exponent exp[0,exp_len). */
      46             : static ulong
      47             : fd_big_mod_exp_adjusted_exponent_length( uchar const * exp,
      48           0 :                                          ulong         exp_len ) {
      49           0 :   if( exp_len<=32UL ) {
      50             :     /* highest set bit index (0-based) over the whole value; 0 if zero */
      51           0 :     for( ulong i=exp_len; i-->0UL; ) {
      52           0 :       if( exp[i] ) return i*8UL + (ulong)fd_ulong_find_msb( (ulong)exp[i] );
      53           0 :     }
      54           0 :     return 0UL;
      55           0 :   }
      56             :   /* exp_len>32 */
      57           0 :   ulong base_term = 8UL*( exp_len-32UL );
      58           0 :   ulong lo        = exp_len-32UL;
      59           0 :   for( ulong i=exp_len; i-->lo; ) {
      60           0 :     if( exp[i] ) return base_term + (i-lo)*8UL + (ulong)fd_ulong_find_msb( (ulong)exp[i] );
      61           0 :   }
      62           0 :   return base_term;
      63           0 : }
      64             : 
      65             : /* decoded exponent == 1 (little-endian) */
      66             : static inline int
      67             : fd_big_mod_exp_exponent_is_one( uchar const * exp,
      68           0 :                                 ulong         exp_len ) {
      69           0 :   if( FD_UNLIKELY( exp_len==0UL ) ) return 0;
      70           0 :   if( exp[0]!=1U ) return 0;
      71           0 :   for( ulong i=1UL; i<exp_len; i++ ) if( exp[i] ) return 0;
      72           0 :   return 1;
      73           0 : }
      74             : 
      75             : /* SIMD-0529 operation cost, i.e. what is charged on top of the flat
      76             :    FD_BIG_MOD_EXP_BASE_CU. */
      77             : static ulong
      78             : fd_big_mod_exp_operation_cost( uchar const * exp,
      79             :                                ulong         exp_len,
      80             :                                ulong         base_len,
      81           0 :                                ulong         mod_len ) {
      82           0 :   ulong operand_words    = ( fd_ulong_max( base_len, mod_len ) + 7UL ) / 8UL;
      83           0 :   ulong mult_complexity  = fd_big_mod_exp_mult_complexity( operand_words );
      84           0 :   if( fd_big_mod_exp_exponent_is_one( exp, exp_len ) ) {
      85             :     /* a single modular reduction of the base */
      86           0 :     return (mult_complexity + FD_BIG_MOD_EXP_MOD_REDUCTION_CU_DIVISOR - 1UL)
      87           0 :          / FD_BIG_MOD_EXP_MOD_REDUCTION_CU_DIVISOR;
      88           0 :   }
      89           0 :   ulong exponent_words  = fd_big_mod_exp_adjusted_exponent_length( exp, exp_len ) / 64UL + 1UL;
      90           0 :   ulong multiplications = FD_BIG_MOD_EXP_SETUP_MULTIPLICATIONS
      91           0 :                         + FD_BIG_MOD_EXP_MULTIPLICATIONS_PER_EXPONENT_WORD*exponent_words;
      92             :   /* operand_words<=64 and exponent_words<=64, so the product is below 2^25 */
      93           0 :   return (mult_complexity*multiplications + FD_BIG_MOD_EXP_CU_DIVISOR - 1UL)
      94           0 :        / FD_BIG_MOD_EXP_CU_DIVISOR;
      95           0 : }
      96             : 
      97             : int
      98             : fd_vm_syscall_sol_big_mod_exp( /**/  void *  _vm,
      99             :                                /**/  ulong   params_vaddr,
     100             :                                /**/  ulong   result_vaddr,
     101             :                                FD_PARAM_UNUSED ulong r3,
     102             :                                FD_PARAM_UNUSED ulong r4,
     103           0 :                                FD_PARAM_UNUSED ulong r5 ) {
     104           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     105             : 
     106             :   /* Charge the flat base cost up front, before any translation that could
     107             :      fail without being paid for. */
     108           0 :   FD_VM_CU_UPDATE( vm, FD_BIG_MOD_EXP_BASE_CU );
     109             : 
     110             :   /* Read the params record (48B, 8-byte aligned). */
     111           0 :   fd_vm_big_mod_exp_params_t const * params =
     112           0 :     (fd_vm_big_mod_exp_params_t const *)FD_VM_MEM_HADDR_LD(
     113           0 :         vm, params_vaddr, FD_VM_ALIGN_RUST_U64, sizeof(fd_vm_big_mod_exp_params_t) );
     114             : 
     115           0 :   ulong base_len = params->base_len;
     116           0 :   ulong exp_len  = params->exponent_len;
     117           0 :   ulong mod_len  = params->modulus_len;
     118             : 
     119             :   /* Length validation rejects only operands over the maximum; mod_len==0 is
     120             :      deliberately allowed through. */
     121           0 :   if( FD_UNLIKELY( base_len>FD_BIG_MOD_EXP_MAX_BYTES ||
     122           0 :                    exp_len >FD_BIG_MOD_EXP_MAX_BYTES ||
     123           0 :                    mod_len >FD_BIG_MOD_EXP_MAX_BYTES ) ) {
     124           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_LENGTH );
     125           0 :     return FD_VM_SYSCALL_ERR_INVALID_LENGTH;
     126           0 :   }
     127             : 
     128             :   /* Translate the exponent and charge before translating the base and modulus. */
     129           0 :   uchar const * exp = exp_len ? FD_VM_MEM_HADDR_LD( vm, params->exponent, FD_VM_ALIGN_RUST_U8, exp_len ) : (uchar const *)"";
     130             : 
     131           0 :   FD_VM_CU_UPDATE( vm, fd_big_mod_exp_operation_cost( exp, exp_len, base_len, mod_len ) );
     132             : 
     133           0 :   uchar const * base = base_len ? FD_VM_MEM_HADDR_LD( vm, params->base,    FD_VM_ALIGN_RUST_U8, base_len ) : (uchar const *)"";
     134           0 :   uchar const * mod  = mod_len  ? FD_VM_MEM_HADDR_LD( vm, params->modulus, FD_VM_ALIGN_RUST_U8, mod_len  ) : (uchar const *)"";
     135             : 
     136             :   /* An empty, zero, one or even modulus fails here, having been charged. */
     137           0 :   if( FD_UNLIKELY( !fd_big_mod_exp_modulus_is_valid( mod, mod_len ) ) ) {
     138           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     139           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE;
     140           0 :   }
     141             : 
     142           0 :   uchar * out = FD_VM_MEM_HADDR_ST( vm, result_vaddr, FD_VM_ALIGN_RUST_U8, mod_len );
     143             : 
     144           0 :   int err = fd_big_mod_exp( out, base, base_len, exp, exp_len, mod, mod_len );
     145           0 :   if( FD_UNLIKELY( err!=FD_BIG_MOD_EXP_SUCCESS ) ) {
     146           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     147           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE;
     148           0 :   }
     149             : 
     150           0 :   vm->reg[0] = 0UL;
     151           0 :   return FD_VM_SUCCESS;
     152           0 : }
     153             : 
     154             : #endif /* FD_HAS_S2NBIGNUM */

Generated by: LCOV version 1.14