LCOV - code coverage report
Current view: top level - flamenco/vm/syscall - fd_vm_syscall_curve.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 299 509 58.7 %
Date: 2026-03-19 18:19:27 Functions: 5 7 71.4 %

          Line data    Source code
       1             : #include "fd_vm_syscall.h"
       2             : #include "../../runtime/fd_bank.h"
       3             : #include "../../../ballet/ed25519/fd_curve25519.h"
       4             : #include "../../../ballet/ed25519/fd_ristretto255.h"
       5             : #include "../../../ballet/bls/fd_bls12_381.h"
       6             : 
       7             : int
       8             : fd_vm_syscall_sol_curve_validate_point( /**/            void *  _vm,
       9             :                                         /**/            ulong   curve_id,
      10             :                                         /**/            ulong   point_addr,
      11             :                                         FD_PARAM_UNUSED ulong   r3,
      12             :                                         FD_PARAM_UNUSED ulong   r4,
      13             :                                         FD_PARAM_UNUSED ulong   r5,
      14          91 :                                         /**/            ulong * _ret ) {
      15             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L871 */
      16          91 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      17          91 :   ulong     ret = 1UL; /* by default return Ok(1) == error */
      18             : 
      19             :   /* BLS12-381 syscalls are under feature gate enable_bls12_381_syscall.
      20             :      To clean up the feature gate after activation, just remove this block
      21             :      (the rest of the function will behave correctly). */
      22          91 :   {
      23          91 :     if( FD_UNLIKELY(
      24          91 :       !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
      25          91 :       && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
      26          91 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
      27          91 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
      28          91 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
      29          91 :     ) ) {
      30           0 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
      31           0 :       return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
      32           0 :     }
      33          91 :   }
      34             : 
      35          91 :   uchar const * point = NULL;
      36          91 :   switch( curve_id ) {
      37             : 
      38          44 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
      39             : 
      40          44 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_EDWARDS_VALIDATE_POINT_COST );
      41          43 :     point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
      42           0 :     ret = (ulong)!fd_ed25519_point_validate( point ); /* 0 if valid point, 1 if not */
      43          42 :     break;
      44             : 
      45          45 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
      46             : 
      47          45 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_RISTRETTO_VALIDATE_POINT_COST );
      48          44 :     point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
      49           0 :     ret = (ulong)!fd_ristretto255_point_validate( point ); /* 0 if valid point, 1 if not */
      50          43 :     break;
      51             : 
      52           0 : #if FD_HAS_BLST
      53           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE:
      54           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE: {
      55             : 
      56           0 :     int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
      57           0 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G1_VALIDATE_COST );
      58           0 :     point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
      59           0 :     ret = (ulong)!fd_bls12_381_g1_validate_syscall( point, big_endian ); /* 0 if valid point, 1 if not */
      60           0 :   } break;
      61             : 
      62           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE:
      63           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE: {
      64             : 
      65           0 :     int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
      66           0 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G2_VALIDATE_COST );
      67           0 :     point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
      68           0 :     ret = (ulong)!fd_bls12_381_g2_validate_syscall( point, big_endian ); /* 0 if valid point, 1 if not */
      69           0 :   } break;
      70           0 : #endif
      71             : 
      72           2 :   default:
      73             :     /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L919-L928 */
      74           2 :     if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
      75           1 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
      76           1 :       return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
      77           1 :     }
      78          91 :   }
      79             : 
      80          86 :   *_ret = ret;
      81          86 :   return FD_VM_SUCCESS;
      82          91 : }
      83             : 
      84             : int
      85             : fd_vm_syscall_sol_curve_group_op( void *  _vm,
      86             :                                   ulong   curve_id,
      87             :                                   ulong   group_op,
      88             :                                   ulong   left_input_addr,
      89             :                                   ulong   right_input_addr,
      90             :                                   ulong   result_point_addr,
      91         169 :                                   ulong * _ret ) {
      92             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L928 */
      93         169 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      94         169 :   ulong     ret = 1UL; /* by default return Ok(1) == error */
      95             : 
      96             :   /* BLS12-381 syscalls are under feature gate enable_bls12_381_syscall.
      97             :      To clean up the feature gate after activation, just remove this block
      98             :      (the rest of the function will behave correctly). */
      99         169 :   {
     100         169 :     if( FD_UNLIKELY(
     101         169 :       !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
     102         169 :       && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
     103         169 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
     104         169 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
     105         169 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
     106         169 :     ) ) {
     107           0 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     108           0 :       return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     109           0 :     }
     110         169 :   }
     111             : 
     112             :   /* Note: we don't strictly follow the Rust implementation, but instead combine
     113             :      common code across switch cases. Similar to fd_vm_syscall_sol_alt_bn128_group_op. */
     114             : 
     115             : /* MATCH_ID_OP allows us to unify 2 switch/case into 1.
     116             :    For better readability, we also temp define EDWARDS, RISTRETTO.
     117             : 
     118             :    The first time we check that both curve_id and group_op are valid
     119             :    with 2 nested switch/case. Using MATCH_ID_OP leads to undesidered
     120             :    edge cases. The second time, when we know that curve_id and group_op
     121             :    are correct, then we can use MATCH_ID_OP and a single switch/case. */
     122         290 : #define MATCH_ID_OP(crv_id,grp_op) ((crv_id << 4) | grp_op)
     123         169 : #define EDWARDS   FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS
     124         169 : #define RISTRETTO FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO
     125         169 : #define BLS_G1_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
     126         169 : #define BLS_G1_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
     127         169 : #define BLS_G2_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
     128         169 : #define BLS_G2_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE
     129             : 
     130         169 :   ulong cost = 0UL;
     131         169 :   ulong inputL_sz = 32UL;
     132         169 :   ulong inputR_sz = 32UL;
     133         169 :   switch( curve_id ) {
     134             : 
     135          83 :   case EDWARDS:
     136          83 :     switch( group_op ) {
     137             : 
     138          19 :     case FD_VM_SYSCALL_SOL_CURVE_ADD:
     139          19 :       cost = FD_VM_CURVE_EDWARDS_ADD_COST;
     140          19 :       break;
     141             : 
     142          18 :     case FD_VM_SYSCALL_SOL_CURVE_SUB:
     143          18 :       cost = FD_VM_CURVE_EDWARDS_SUBTRACT_COST;
     144          18 :       break;
     145             : 
     146          44 :     case FD_VM_SYSCALL_SOL_CURVE_MUL:
     147          44 :       cost = FD_VM_CURVE_EDWARDS_MULTIPLY_COST;
     148          44 :       break;
     149             : 
     150           2 :     default:
     151           2 :       goto invalid_error;
     152          83 :     }
     153          81 :     break;
     154             : 
     155          84 :   case RISTRETTO:
     156          84 :     switch( group_op ) {
     157             : 
     158          21 :     case FD_VM_SYSCALL_SOL_CURVE_ADD:
     159          21 :       cost = FD_VM_CURVE_RISTRETTO_ADD_COST;
     160          21 :       break;
     161             : 
     162          23 :     case FD_VM_SYSCALL_SOL_CURVE_SUB:
     163          23 :       cost = FD_VM_CURVE_RISTRETTO_SUBTRACT_COST;
     164          23 :       break;
     165             : 
     166          38 :     case FD_VM_SYSCALL_SOL_CURVE_MUL:
     167          38 :       cost = FD_VM_CURVE_RISTRETTO_MULTIPLY_COST;
     168          38 :       break;
     169             : 
     170           2 :     default:
     171           2 :       goto invalid_error;
     172          84 :     }
     173          82 :     break;
     174             : 
     175          82 : #if FD_HAS_BLST
     176             :   /* BLS12-381 G1 */
     177          82 :   case BLS_G1_BE:
     178           0 :   case BLS_G1_LE:
     179           0 :     switch( group_op ) {
     180             : 
     181           0 :     case FD_VM_SYSCALL_SOL_CURVE_ADD:
     182           0 :       cost = FD_VM_CURVE_BLS12_381_G1_ADD_COST;
     183           0 :       inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
     184           0 :       inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
     185           0 :       break;
     186             : 
     187           0 :     case FD_VM_SYSCALL_SOL_CURVE_SUB:
     188           0 :       cost = FD_VM_CURVE_BLS12_381_G1_SUB_COST;
     189           0 :       inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
     190           0 :       inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
     191           0 :       break;
     192             : 
     193           0 :     case FD_VM_SYSCALL_SOL_CURVE_MUL:
     194           0 :       cost = FD_VM_CURVE_BLS12_381_G1_MUL_COST;
     195             :       /* inputL_sz = 32UL // scalar */
     196           0 :       inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
     197           0 :       break;
     198             : 
     199           0 :     default:
     200           0 :       goto invalid_error;
     201           0 :     }
     202           0 :     break;
     203             : 
     204             :   /* BLS12-381 G2 */
     205           0 :   case BLS_G2_BE:
     206           0 :   case BLS_G2_LE:
     207           0 :     switch( group_op ) {
     208             : 
     209           0 :     case FD_VM_SYSCALL_SOL_CURVE_ADD:
     210           0 :       cost = FD_VM_CURVE_BLS12_381_G2_ADD_COST;
     211           0 :       inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
     212           0 :       inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
     213           0 :       break;
     214             : 
     215           0 :     case FD_VM_SYSCALL_SOL_CURVE_SUB:
     216           0 :       cost = FD_VM_CURVE_BLS12_381_G2_SUB_COST;
     217           0 :       inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
     218           0 :       inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
     219           0 :       break;
     220             : 
     221           0 :     case FD_VM_SYSCALL_SOL_CURVE_MUL:
     222           0 :       cost = FD_VM_CURVE_BLS12_381_G2_MUL_COST;
     223             :       /* inputL_sz = 32UL // scalar */
     224           0 :       inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
     225           0 :       break;
     226             : 
     227           0 :     default:
     228           0 :       goto invalid_error;
     229           0 :     }
     230           0 :     break;
     231           0 : #endif
     232             : 
     233           2 :   default:
     234           2 :     goto invalid_error;
     235         169 :   }
     236             : 
     237             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L944-L947 */
     238         320 :   FD_VM_CU_UPDATE( vm, cost );
     239             : 
     240             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L949-L958 */
     241             : 
     242             :   /* Note: left_input_addr is a point for add, sub, BUT it's a scalar for mul. */
     243         459 :   uchar const * inputL = FD_VM_MEM_HADDR_LD( vm, left_input_addr,  FD_VM_ALIGN_RUST_POD_U8_ARRAY, inputL_sz );
     244         441 :   uchar const * inputR = FD_VM_MEM_HADDR_LD( vm, right_input_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, inputR_sz );
     245             : 
     246           0 : #if FD_HAS_BLST
     247         145 :   int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
     248         441 : #endif
     249             : 
     250         441 :   switch( MATCH_ID_OP( curve_id, group_op ) ) {
     251             : 
     252          16 :   case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
     253          16 :     fd_ed25519_point_t p0[1], p1[1], r[1];
     254          16 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
     255           1 :       goto soft_error;
     256           1 :     }
     257          15 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
     258           1 :       goto soft_error;
     259           1 :     }
     260             : 
     261          14 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     262          13 :     fd_ed25519_point_add( r, p0, p1 );
     263          13 :     fd_ed25519_point_tobytes( result, r );
     264          13 :     ret = 0UL;
     265          13 :     break;
     266          14 :   }
     267             : 
     268          15 :   case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
     269          15 :     fd_ed25519_point_t p0[1], p1[1], r[1];
     270          15 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
     271           1 :       goto soft_error;
     272           1 :     }
     273          14 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
     274           1 :       goto soft_error;
     275           1 :     }
     276             : 
     277          13 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     278          12 :     fd_ed25519_point_sub( r, p0, p1 );
     279          12 :     fd_ed25519_point_tobytes( result, r );
     280          12 :     ret = 0UL;
     281          12 :     break;
     282          13 :   }
     283             : 
     284          41 :   case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
     285          41 :     fd_ed25519_point_t p[1], r[1];
     286          41 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
     287           4 :       goto soft_error;
     288           4 :     }
     289          37 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p, inputR ) ) ) {
     290           2 :       goto soft_error;
     291           2 :     }
     292             : 
     293          35 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     294          34 :     fd_ed25519_scalar_mul( r, inputL, p );
     295          34 :     fd_ed25519_point_tobytes( result, r );
     296          34 :     ret = 0UL;
     297          34 :     break;
     298          35 :   }
     299             : 
     300          18 :   case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
     301          18 :     fd_ristretto255_point_t p0[1], p1[1], r[1];
     302          18 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
     303           1 :       goto soft_error;
     304           1 :     }
     305          17 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
     306           1 :       goto soft_error;
     307           1 :     }
     308             : 
     309          16 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     310          15 :     fd_ristretto255_point_add( r, p0, p1 );
     311          15 :     fd_ristretto255_point_tobytes( result, r );
     312          15 :     ret = 0UL;
     313          15 :     break;
     314          16 :   }
     315             : 
     316          20 :   case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
     317          20 :     fd_ristretto255_point_t p0[1], p1[1], r[1];
     318          20 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
     319           1 :       goto soft_error;
     320           1 :     }
     321          19 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
     322           1 :       goto soft_error;
     323           1 :     }
     324             : 
     325          18 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     326          17 :     fd_ristretto255_point_sub( r, p0, p1 );
     327          17 :     fd_ristretto255_point_tobytes( result, r );
     328          17 :     ret = 0UL;
     329          17 :     break;
     330          18 :   }
     331             : 
     332          35 :   case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
     333          35 :     fd_ristretto255_point_t p[1], r[1];
     334          35 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
     335           5 :       goto soft_error;
     336           5 :     }
     337          30 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p, inputR ) ) ) {
     338          10 :       goto soft_error;
     339          10 :     }
     340             : 
     341          20 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     342          19 :     fd_ristretto255_scalar_mul( r, inputL, p );
     343          19 :     fd_ristretto255_point_tobytes( result, r );
     344          19 :     ret = 0UL;
     345          19 :     break;
     346          20 :   }
     347             : 
     348           0 : #if FD_HAS_BLST
     349             :   /* BLS12-381 G1 */
     350             : 
     351             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1453 */
     352           0 :   case MATCH_ID_OP( BLS_G1_BE, FD_VM_SYSCALL_SOL_CURVE_ADD ):
     353           0 :   case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
     354           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
     355             :     /* Compute add */
     356           0 :     if( FD_LIKELY( fd_bls12_381_g1_add_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
     357             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1474 */
     358           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     359           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     360           0 :       ret = 0UL; /* success */
     361           0 :     }
     362           0 :     break;
     363           0 :   }
     364             : 
     365             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1485 */
     366           0 :   case MATCH_ID_OP( BLS_G1_BE, FD_VM_SYSCALL_SOL_CURVE_SUB ):
     367           0 :   case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
     368           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
     369             :     /* Compute sub */
     370           0 :     if( FD_LIKELY( fd_bls12_381_g1_sub_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
     371           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     372           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     373           0 :       ret = 0UL; /* success */
     374           0 :     }
     375           0 :     break;
     376           0 :   }
     377             : 
     378             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1519 */
     379           0 :   case MATCH_ID_OP( BLS_G1_BE, FD_VM_SYSCALL_SOL_CURVE_MUL ):
     380           0 :   case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
     381           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
     382             :     /* Compute mul */
     383           0 :     if( FD_LIKELY( fd_bls12_381_g1_mul_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
     384           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     385           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     386           0 :       ret = 0UL; /* success */
     387           0 :     }
     388           0 :     break;
     389           0 :   }
     390             : 
     391             :   /* BLS12-381 G2 */
     392             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1566 */
     393           0 :   case MATCH_ID_OP( BLS_G2_BE, FD_VM_SYSCALL_SOL_CURVE_ADD ):
     394           0 :   case MATCH_ID_OP( BLS_G2_LE, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
     395           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
     396             :     /* Compute add */
     397           0 :     if( FD_LIKELY( fd_bls12_381_g2_add_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
     398           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     399           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     400           0 :       ret = 0UL; /* success */
     401           0 :     }
     402           0 :     break;
     403           0 :   }
     404             : 
     405             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1598 */
     406           0 :   case MATCH_ID_OP( BLS_G2_BE, FD_VM_SYSCALL_SOL_CURVE_SUB ):
     407           0 :   case MATCH_ID_OP( BLS_G2_LE, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
     408           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
     409             :     /* Compute sub */
     410           0 :     if( FD_LIKELY( fd_bls12_381_g2_sub_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
     411           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     412           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     413           0 :       ret = 0UL; /* success */
     414           0 :     }
     415           0 :     break;
     416           0 :   }
     417             : 
     418             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1632 */
     419           0 :   case MATCH_ID_OP( BLS_G2_BE, FD_VM_SYSCALL_SOL_CURVE_MUL ):
     420           0 :   case MATCH_ID_OP( BLS_G2_LE, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
     421           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
     422             :     /* Compute mul */
     423           0 :     if( FD_LIKELY( fd_bls12_381_g2_mul_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
     424           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     425           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     426           0 :       ret = 0UL; /* success */
     427           0 :     }
     428           0 :     break;
     429           0 :   }
     430           0 : #endif
     431             : 
     432           0 :   default:
     433             :     /* COV: this can never happen because of the previous switch */
     434           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     435         441 :   }
     436             : 
     437         139 : soft_error:
     438         139 :   *_ret = ret;
     439         139 :   return FD_VM_SUCCESS;
     440           0 : #undef MATCH_ID_OP
     441           0 : #undef EDWARDS
     442           0 : #undef RISTRETTO
     443           0 : #undef BLS_G1_BE
     444           0 : #undef BLS_G1_LE
     445           0 : #undef BLS_G2_BE
     446           0 : #undef BLS_G2_LE
     447             : 
     448           6 : invalid_error:
     449             :   /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1135-L1156 */
     450           6 :   if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
     451           3 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     452           3 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     453           3 :   }
     454           3 :   *_ret = 1UL;
     455           3 :   return FD_VM_SUCCESS;
     456           6 : }
     457             : 
     458             : /* multi_scalar_mul_edwards computes a MSM on curve25519.
     459             : 
     460             :    This function is equivalent to
     461             :    zk-token-sdk::edwards::multi_scalar_mul_edwards
     462             : 
     463             :    https://github.com/solana-labs/solana/blob/v1.17.7/zk-token-sdk/src/curve25519/edwards.rs#L116
     464             : 
     465             :    Specifically it takes as input byte arrays and takes care of scalars
     466             :    validation and points decompression.  It then invokes ballet MSM
     467             :    function fd_ed25519_multi_scalar_mul.  To avoid dynamic allocation,
     468             :    the full MSM is done in batches of FD_BALLET_CURVE25519_MSM_BATCH_SZ. */
     469             : 
     470             : static fd_ed25519_point_t *
     471             : multi_scalar_mul_edwards( fd_ed25519_point_t * r,
     472             :                           uchar const *        scalars,
     473             :                           uchar const *        points,
     474          68 :                           ulong                cnt ) {
     475             :   /* Validate all scalars first (fast) */
     476         203 :   for( ulong i=0UL; i<cnt; i++ ) {
     477         136 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
     478           1 :       return NULL;
     479           1 :     }
     480         136 :   }
     481             : 
     482             :   /* Static allocation of a batch of decompressed points */
     483          67 :   fd_ed25519_point_t tmp[1];
     484          67 :   fd_ed25519_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
     485             : 
     486          67 :   fd_ed25519_point_set_zero( r );
     487         133 :   for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
     488          67 :     ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
     489             : 
     490             :     /* Decompress (and validate) points */
     491         199 :     for( ulong j=0UL; j<batch_cnt; j++ ) {
     492             :       //TODO: use fd_ed25519_point_frombytes_2x
     493         133 :       if( FD_UNLIKELY( !fd_ed25519_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
     494           1 :         return NULL;
     495           1 :       }
     496         133 :     }
     497             : 
     498          66 :     fd_ed25519_multi_scalar_mul( tmp, scalars, A, batch_cnt );
     499          66 :     fd_ed25519_point_add( r, r, tmp );
     500          66 :     points  += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
     501          66 :     scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
     502          66 :   }
     503             : 
     504          66 :   return r;
     505          67 : }
     506             : 
     507             : /* multi_scalar_mul_ristretto computes a MSM on ristretto255.
     508             :    See multi_scalar_mul_edwards for details. */
     509             : 
     510             : static fd_ristretto255_point_t *
     511             : multi_scalar_mul_ristretto( fd_ristretto255_point_t * r,
     512             :                             uchar const *             scalars,
     513             :                             uchar const *             points,
     514          37 :                             ulong                     cnt ) {
     515             :   /* Validate all scalars first (fast) */
     516         110 :   for( ulong i=0UL; i<cnt; i++ ) {
     517          74 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
     518           1 :       return NULL;
     519           1 :     }
     520          74 :   }
     521             : 
     522             :   /* Static allocation of a batch of decompressed points */
     523          36 :   fd_ristretto255_point_t tmp[1];
     524          36 :   fd_ristretto255_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
     525             : 
     526          36 :   fd_ristretto255_point_set_zero( r );
     527          68 :   for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
     528          36 :     ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
     529             : 
     530             :     /* Decompress (and validate) points */
     531         100 :     for( ulong j=0UL; j<batch_cnt; j++ ) {
     532             :       //TODO: use fd_ristretto255_point_frombytes_2x
     533          68 :       if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
     534           4 :         return NULL;
     535           4 :       }
     536          68 :     }
     537             : 
     538          32 :     fd_ristretto255_multi_scalar_mul( tmp, scalars, A, batch_cnt );
     539          32 :     fd_ristretto255_point_add( r, r, tmp );
     540          32 :     points  += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
     541          32 :     scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
     542          32 :   }
     543             : 
     544          32 :   return r;
     545          36 : }
     546             : 
     547             : #undef BATCH_MAX
     548             : 
     549             : int
     550             : fd_vm_syscall_sol_curve_multiscalar_mul( void *  _vm,
     551             :                                          ulong   curve_id,
     552             :                                          ulong   scalars_addr,
     553             :                                          ulong   points_addr,
     554             :                                          ulong   points_len,
     555             :                                          ulong   result_point_addr,
     556         115 :                                          ulong * _ret ) {
     557             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1129 */
     558         115 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     559         115 :   ulong     ret = 1UL; /* by default return Ok(1) == error */
     560             : 
     561             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1143-L1151 */
     562         115 :   if( FD_UNLIKELY( points_len > 512 ) ) {
     563           2 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_LENGTH );
     564           2 :     return FD_VM_SYSCALL_ERR_INVALID_LENGTH; /* SyscallError::InvalidLength */
     565           2 :   }
     566             : 
     567             :   /* Note: we don't strictly follow the Rust implementation, but instead combine
     568             :      common code across switch cases. Similar to fd_vm_syscall_sol_alt_bn128_group_op. */
     569             : 
     570         113 :   ulong base_cost = 0UL;
     571         113 :   ulong incremental_cost = 0UL;
     572         113 :   switch( curve_id ) {
     573          71 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
     574          71 :     base_cost = FD_VM_CURVE_EDWARDS_MSM_BASE_COST;
     575          71 :     incremental_cost = FD_VM_CURVE_EDWARDS_MSM_INCREMENTAL_COST;
     576          71 :     break;
     577             : 
     578          40 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
     579          40 :     base_cost = FD_VM_CURVE_RISTRETTO_MSM_BASE_COST;
     580          40 :     incremental_cost = FD_VM_CURVE_RISTRETTO_MSM_INCREMENTAL_COST;
     581          40 :     break;
     582             : 
     583           2 :   default:
     584             :     /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1262-L1271 */
     585           2 :     if( FD_UNLIKELY( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) ) {
     586           1 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     587           1 :       return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     588           1 :     }
     589           1 :     goto soft_error;
     590         113 :   }
     591             : 
     592             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1155-L1164 */
     593         111 :   ulong cost = fd_ulong_sat_add(
     594         111 :     base_cost,
     595         111 :     fd_ulong_sat_mul(
     596         111 :       incremental_cost,
     597         111 :       fd_ulong_sat_sub( points_len, 1 )
     598         111 :     )
     599         111 :   );
     600         111 :   FD_VM_CU_UPDATE( vm, cost );
     601             : 
     602             :   /* Edge case points_len==0.
     603             :      Agave computes the MSM, that returns the point at infinity, and stores the result.
     604             :      This means that we have to mem map result, and then set the point at infinity,
     605             :      that is 0x0100..00 for Edwards and 0x00..00 for Ristretto. */
     606         109 :   if ( FD_UNLIKELY( points_len==0 ) ) {
     607           0 :     uchar * result = FD_VM_MEM_HADDR_ST( vm, result_point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     608           0 :     memset( result, 0, 32 );
     609           0 :     result[0] = curve_id==FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS ? 1 : 0;
     610           0 :     *_ret = 0;
     611           0 :     return FD_VM_SUCCESS;
     612           0 :   }
     613             : 
     614             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1166-L1178 */
     615         323 :   uchar const * scalars = FD_VM_MEM_HADDR_LD( vm, scalars_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, points_len*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ );
     616         317 :   uchar const * points  = FD_VM_MEM_HADDR_LD( vm, points_addr,  FD_VM_ALIGN_RUST_POD_U8_ARRAY, points_len*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     617             : 
     618           0 :   switch( curve_id ) {
     619             : 
     620          68 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS: {
     621             :     /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1180-L1189 */
     622          68 :     fd_ed25519_point_t _r[1];
     623          68 :     fd_ed25519_point_t * r = multi_scalar_mul_edwards( _r, scalars, points, points_len );
     624             : 
     625          68 :     if( FD_LIKELY( r ) ) {
     626          66 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     627          66 :       fd_ed25519_point_tobytes( result, r );
     628          66 :       ret = 0UL;
     629          66 :     }
     630          68 :     break;
     631          68 :   }
     632             : 
     633          68 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO: {
     634          37 :     fd_ristretto255_point_t _r[1];
     635          37 :     fd_ristretto255_point_t * r = multi_scalar_mul_ristretto( _r, scalars, points, points_len );
     636             : 
     637          37 :     if( FD_LIKELY( r ) ) {
     638          32 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     639          32 :       fd_ristretto255_point_tobytes( result, r );
     640          32 :       ret = 0UL;
     641          32 :     }
     642          37 :     break;
     643          37 :   }
     644             : 
     645          37 :   default:
     646             :     /* COV: this can never happen because of the previous switch */
     647           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     648         317 :   }
     649             : 
     650         106 : soft_error:
     651         106 :   *_ret = ret;
     652         106 :   return FD_VM_SUCCESS;
     653         317 : }
     654             : 
     655             : #if FD_HAS_BLST
     656             : 
     657             : int
     658             : fd_vm_syscall_sol_curve_decompress( /**/            void *  _vm,
     659             :                                     /**/            ulong   curve_id,
     660             :                                     /**/            ulong   point_addr,
     661             :                                     /**/            ulong   result_addr,
     662             :                                     FD_PARAM_UNUSED ulong   r4,
     663             :                                     FD_PARAM_UNUSED ulong   r5,
     664           0 :                                     /**/            ulong * _ret ) {
     665             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1118 */
     666           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     667           0 :   ulong     ret = 1UL; /* by default return Ok(1) == error */
     668             : 
     669           0 :   int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
     670             : 
     671           0 :   uchar const * point = NULL;
     672           0 :   switch( curve_id ) {
     673             : 
     674             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1137 */
     675           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE:
     676           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE: {
     677           0 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G1_DECOMPRESS_COST );
     678           0 :     point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_COMPRESSED_SZ );
     679           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
     680           0 :     if( FD_LIKELY( fd_bls12_381_g1_decompress_syscall( _result, point, big_endian )==0 ) ) {
     681             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1160 */
     682           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     683           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     684           0 :       ret = 0UL; /* success */
     685           0 :     }
     686           0 :   } break;
     687             : 
     688             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1171 */
     689           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE:
     690           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE: {
     691           0 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G2_DECOMPRESS_COST );
     692           0 :     point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_COMPRESSED_SZ );
     693           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
     694           0 :     if( FD_LIKELY( fd_bls12_381_g2_decompress_syscall( _result, point, big_endian )==0 ) ) {
     695           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     696           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
     697           0 :       ret = 0UL; /* success */
     698           0 :     }
     699           0 :   } break;
     700             : 
     701           0 :   default:
     702           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     703           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     704           0 :   }
     705             : 
     706           0 :   *_ret = ret;
     707           0 :   return FD_VM_SUCCESS;
     708           0 : }
     709             : 
     710             : int
     711             : fd_vm_syscall_sol_curve_pairing_map( /**/            void *  _vm,
     712             :                                      /**/            ulong   curve_id,
     713             :                                      /**/            ulong   num_pairs,
     714             :                                      FD_PARAM_UNUSED ulong   g1_points_addr,
     715             :                                      FD_PARAM_UNUSED ulong   g2_points_addr,
     716             :                                      FD_PARAM_UNUSED ulong   result_addr,
     717           0 :                                      /**/            ulong * _ret ) {
     718             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1804 */
     719           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     720           0 :   ulong     ret = 1UL; /* by default return Ok(1) == error */
     721             : 
     722           0 :   int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
     723             : 
     724           0 :   switch( curve_id ) {
     725             : 
     726             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1823 */
     727           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_BE:
     728           0 :   case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_LE: {
     729             : 
     730           0 :     ulong cost = fd_ulong_sat_add( FD_VM_CURVE_BLS12_381_PAIRING_BASE_COST,
     731           0 :       fd_ulong_sat_mul( FD_VM_CURVE_BLS12_381_PAIRING_INCR_COST,
     732           0 :         fd_ulong_sat_sub( num_pairs, 1 ) ) );
     733           0 :     FD_VM_CU_UPDATE( vm, cost );
     734             : 
     735           0 :     ulong total_g1_sz = fd_ulong_sat_mul( FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ, num_pairs );
     736           0 :     uchar const * g1_points = FD_VM_MEM_HADDR_LD( vm, g1_points_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, total_g1_sz );
     737             : 
     738           0 :     ulong total_g2_sz = fd_ulong_sat_mul( FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ, num_pairs );
     739           0 :     uchar const * g2_points = FD_VM_MEM_HADDR_LD( vm, g2_points_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, total_g2_sz );
     740             : 
     741           0 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_GT_ELE_SZ ];
     742           0 :     if( FD_LIKELY( fd_bls12_381_pairing_syscall( _result, g1_points, g2_points, num_pairs, big_endian )==0 ) ) {
     743             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1860 */
     744           0 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_GT_ELE_SZ );
     745           0 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_GT_ELE_SZ );
     746           0 :       ret = 0UL; /* success */
     747           0 :     }
     748           0 :   } break;
     749             : 
     750           0 :   default:
     751           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     752           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     753           0 :   }
     754             : 
     755           0 :   *_ret = ret;
     756           0 :   return FD_VM_SUCCESS;
     757           0 : }
     758             : 
     759             : #endif

Generated by: LCOV version 1.14