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: 200 509 39.3 %
Date: 2026-02-28 05:18:01 Functions: 4 7 57.1 %

          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           0 :                                         /**/            ulong * _ret ) {
      15             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L871 */
      16           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      17           0 :   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           0 :   {
      23           0 :     if( FD_UNLIKELY(
      24           0 :       !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
      25           0 :       && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
      26           0 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
      27           0 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
      28           0 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
      29           0 :     ) ) {
      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           0 :   }
      34             : 
      35           0 :   uchar const * point = NULL;
      36           0 :   switch( curve_id ) {
      37             : 
      38           0 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
      39             : 
      40           0 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_EDWARDS_VALIDATE_POINT_COST );
      41           0 :     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           0 :     break;
      44             : 
      45           0 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
      46             : 
      47           0 :     FD_VM_CU_UPDATE( vm, FD_VM_CURVE_RISTRETTO_VALIDATE_POINT_COST );
      48           0 :     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           0 :     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           0 :   default:
      73             :     /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L919-L928 */
      74           0 :     if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
      75           0 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
      76           0 :       return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
      77           0 :     }
      78           0 :   }
      79             : 
      80           0 :   *_ret = ret;
      81           0 :   return FD_VM_SUCCESS;
      82           0 : }
      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          15 :                                   ulong * _ret ) {
      92             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L928 */
      93          15 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      94          15 :   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          15 :   {
     100          15 :     if( FD_UNLIKELY(
     101          15 :       !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
     102          15 :       && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
     103          15 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
     104          15 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
     105          15 :         || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
     106          15 :     ) ) {
     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          15 :   }
     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          30 : #define MATCH_ID_OP(crv_id,grp_op) ((crv_id << 4) | grp_op)
     123          15 : #define EDWARDS   FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS
     124          15 : #define RISTRETTO FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO
     125          15 : #define BLS_G1_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
     126          15 : #define BLS_G1_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
     127          15 : #define BLS_G2_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
     128          15 : #define BLS_G2_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE
     129             : 
     130          15 :   ulong cost = 0UL;
     131          15 :   ulong inputL_sz = 32UL;
     132          15 :   ulong inputR_sz = 32UL;
     133          15 :   switch( curve_id ) {
     134             : 
     135           0 :   case EDWARDS:
     136           0 :     switch( group_op ) {
     137             : 
     138           0 :     case FD_VM_SYSCALL_SOL_CURVE_ADD:
     139           0 :       cost = FD_VM_CURVE_EDWARDS_ADD_COST;
     140           0 :       break;
     141             : 
     142           0 :     case FD_VM_SYSCALL_SOL_CURVE_SUB:
     143           0 :       cost = FD_VM_CURVE_EDWARDS_SUBTRACT_COST;
     144           0 :       break;
     145             : 
     146           0 :     case FD_VM_SYSCALL_SOL_CURVE_MUL:
     147           0 :       cost = FD_VM_CURVE_EDWARDS_MULTIPLY_COST;
     148           0 :       break;
     149             : 
     150           0 :     default:
     151           0 :       goto invalid_error;
     152           0 :     }
     153           0 :     break;
     154             : 
     155          12 :   case RISTRETTO:
     156          12 :     switch( group_op ) {
     157             : 
     158           6 :     case FD_VM_SYSCALL_SOL_CURVE_ADD:
     159           6 :       cost = FD_VM_CURVE_RISTRETTO_ADD_COST;
     160           6 :       break;
     161             : 
     162           3 :     case FD_VM_SYSCALL_SOL_CURVE_SUB:
     163           3 :       cost = FD_VM_CURVE_RISTRETTO_SUBTRACT_COST;
     164           3 :       break;
     165             : 
     166           3 :     case FD_VM_SYSCALL_SOL_CURVE_MUL:
     167           3 :       cost = FD_VM_CURVE_RISTRETTO_MULTIPLY_COST;
     168           3 :       break;
     169             : 
     170           0 :     default:
     171           0 :       goto invalid_error;
     172          12 :     }
     173          12 :     break;
     174             : 
     175          12 : #if FD_HAS_BLST
     176             :   /* BLS12-381 G1 */
     177          12 :   case BLS_G1_BE:
     178           3 :   case BLS_G1_LE:
     179           3 :     switch( group_op ) {
     180             : 
     181           3 :     case FD_VM_SYSCALL_SOL_CURVE_ADD:
     182           3 :       cost = FD_VM_CURVE_BLS12_381_G1_ADD_COST;
     183           3 :       inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
     184           3 :       inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
     185           3 :       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           3 :     }
     202           3 :     break;
     203             : 
     204             :   /* BLS12-381 G2 */
     205           3 :   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           0 :   default:
     234           0 :     goto invalid_error;
     235          15 :   }
     236             : 
     237             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L944-L947 */
     238          30 :   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          45 :   uchar const * inputL = FD_VM_MEM_HADDR_LD( vm, left_input_addr,  FD_VM_ALIGN_RUST_POD_U8_ARRAY, inputL_sz );
     244          45 :   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          15 :   int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
     248          45 : #endif
     249             : 
     250          45 :   switch( MATCH_ID_OP( curve_id, group_op ) ) {
     251             : 
     252           0 :   case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
     253           0 :     fd_ed25519_point_t p0[1], p1[1], r[1];
     254           0 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
     255           0 :       goto soft_error;
     256           0 :     }
     257           0 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
     258           0 :       goto soft_error;
     259           0 :     }
     260             : 
     261           0 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     262           0 :     fd_ed25519_point_add( r, p0, p1 );
     263           0 :     fd_ed25519_point_tobytes( result, r );
     264           0 :     ret = 0UL;
     265           0 :     break;
     266           0 :   }
     267             : 
     268           0 :   case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
     269           0 :     fd_ed25519_point_t p0[1], p1[1], r[1];
     270           0 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
     271           0 :       goto soft_error;
     272           0 :     }
     273           0 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
     274           0 :       goto soft_error;
     275           0 :     }
     276             : 
     277           0 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     278           0 :     fd_ed25519_point_sub( r, p0, p1 );
     279           0 :     fd_ed25519_point_tobytes( result, r );
     280           0 :     ret = 0UL;
     281           0 :     break;
     282           0 :   }
     283             : 
     284           0 :   case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
     285           0 :     fd_ed25519_point_t p[1], r[1];
     286           0 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
     287           0 :       goto soft_error;
     288           0 :     }
     289           0 :     if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p, inputR ) ) ) {
     290           0 :       goto soft_error;
     291           0 :     }
     292             : 
     293           0 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     294           0 :     fd_ed25519_scalar_mul( r, inputL, p );
     295           0 :     fd_ed25519_point_tobytes( result, r );
     296           0 :     ret = 0UL;
     297           0 :     break;
     298           0 :   }
     299             : 
     300           6 :   case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
     301           6 :     fd_ristretto255_point_t p0[1], p1[1], r[1];
     302           6 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
     303           0 :       goto soft_error;
     304           0 :     }
     305           6 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
     306           0 :       goto soft_error;
     307           0 :     }
     308             : 
     309           6 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     310           6 :     fd_ristretto255_point_add( r, p0, p1 );
     311           6 :     fd_ristretto255_point_tobytes( result, r );
     312           6 :     ret = 0UL;
     313           6 :     break;
     314           6 :   }
     315             : 
     316           3 :   case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
     317           3 :     fd_ristretto255_point_t p0[1], p1[1], r[1];
     318           3 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
     319           0 :       goto soft_error;
     320           0 :     }
     321           3 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
     322           0 :       goto soft_error;
     323           0 :     }
     324             : 
     325           3 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     326           3 :     fd_ristretto255_point_sub( r, p0, p1 );
     327           3 :     fd_ristretto255_point_tobytes( result, r );
     328           3 :     ret = 0UL;
     329           3 :     break;
     330           3 :   }
     331             : 
     332           3 :   case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
     333           3 :     fd_ristretto255_point_t p[1], r[1];
     334           3 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
     335           0 :       goto soft_error;
     336           0 :     }
     337           3 :     if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p, inputR ) ) ) {
     338           0 :       goto soft_error;
     339           0 :     }
     340             : 
     341           3 :     uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     342           3 :     fd_ristretto255_scalar_mul( r, inputL, p );
     343           3 :     fd_ristretto255_point_tobytes( result, r );
     344           3 :     ret = 0UL;
     345           3 :     break;
     346           3 :   }
     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           3 :   case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
     354           3 :     uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
     355             :     /* Compute add */
     356           3 :     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           3 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     359           3 :       memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
     360           3 :       ret = 0UL; /* success */
     361           3 :     }
     362           3 :     break;
     363           3 :   }
     364             : 
     365             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1485 */
     366           3 :   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          45 :   }
     436             : 
     437          15 : soft_error:
     438          15 :   *_ret = ret;
     439          15 :   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           0 : invalid_error:
     449             :   /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1135-L1156 */
     450           0 :   if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
     451           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     452           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     453           0 :   }
     454           0 :   *_ret = 1UL;
     455           0 :   return FD_VM_SUCCESS;
     456           0 : }
     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           3 :                           ulong                cnt ) {
     475             :   /* Validate all scalars first (fast) */
     476           9 :   for( ulong i=0UL; i<cnt; i++ ) {
     477           6 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
     478           0 :       return NULL;
     479           0 :     }
     480           6 :   }
     481             : 
     482             :   /* Static allocation of a batch of decompressed points */
     483           3 :   fd_ed25519_point_t tmp[1];
     484           3 :   fd_ed25519_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
     485             : 
     486           3 :   fd_ed25519_point_set_zero( r );
     487           6 :   for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
     488           3 :     ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
     489             : 
     490             :     /* Decompress (and validate) points */
     491           9 :     for( ulong j=0UL; j<batch_cnt; j++ ) {
     492             :       //TODO: use fd_ed25519_point_frombytes_2x
     493           6 :       if( FD_UNLIKELY( !fd_ed25519_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
     494           0 :         return NULL;
     495           0 :       }
     496           6 :     }
     497             : 
     498           3 :     fd_ed25519_multi_scalar_mul( tmp, scalars, A, batch_cnt );
     499           3 :     fd_ed25519_point_add( r, r, tmp );
     500           3 :     points  += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
     501           3 :     scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
     502           3 :   }
     503             : 
     504           3 :   return r;
     505           3 : }
     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           3 :                             ulong                     cnt ) {
     515             :   /* Validate all scalars first (fast) */
     516           9 :   for( ulong i=0UL; i<cnt; i++ ) {
     517           6 :     if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
     518           0 :       return NULL;
     519           0 :     }
     520           6 :   }
     521             : 
     522             :   /* Static allocation of a batch of decompressed points */
     523           3 :   fd_ristretto255_point_t tmp[1];
     524           3 :   fd_ristretto255_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
     525             : 
     526           3 :   fd_ristretto255_point_set_zero( r );
     527           6 :   for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
     528           3 :     ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
     529             : 
     530             :     /* Decompress (and validate) points */
     531           9 :     for( ulong j=0UL; j<batch_cnt; j++ ) {
     532             :       //TODO: use fd_ristretto255_point_frombytes_2x
     533           6 :       if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
     534           0 :         return NULL;
     535           0 :       }
     536           6 :     }
     537             : 
     538           3 :     fd_ristretto255_multi_scalar_mul( tmp, scalars, A, batch_cnt );
     539           3 :     fd_ristretto255_point_add( r, r, tmp );
     540           3 :     points  += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
     541           3 :     scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
     542           3 :   }
     543             : 
     544           3 :   return r;
     545           3 : }
     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          15 :                                          ulong * _ret ) {
     557             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1129 */
     558          15 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     559          15 :   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          15 :   if( FD_UNLIKELY( points_len > 512 ) ) {
     563           3 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_LENGTH );
     564           3 :     return FD_VM_SYSCALL_ERR_INVALID_LENGTH; /* SyscallError::InvalidLength */
     565           3 :   }
     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          12 :   ulong base_cost = 0UL;
     571          12 :   ulong incremental_cost = 0UL;
     572          12 :   switch( curve_id ) {
     573           6 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
     574           6 :     base_cost = FD_VM_CURVE_EDWARDS_MSM_BASE_COST;
     575           6 :     incremental_cost = FD_VM_CURVE_EDWARDS_MSM_INCREMENTAL_COST;
     576           6 :     break;
     577             : 
     578           3 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
     579           3 :     base_cost = FD_VM_CURVE_RISTRETTO_MSM_BASE_COST;
     580           3 :     incremental_cost = FD_VM_CURVE_RISTRETTO_MSM_INCREMENTAL_COST;
     581           3 :     break;
     582             : 
     583           3 :   default:
     584             :     /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1262-L1271 */
     585           3 :     if( FD_UNLIKELY( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) ) {
     586           3 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
     587           3 :       return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     588           3 :     }
     589           0 :     goto soft_error;
     590          12 :   }
     591             : 
     592             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1155-L1164 */
     593           9 :   ulong cost = fd_ulong_sat_add(
     594           9 :     base_cost,
     595           9 :     fd_ulong_sat_mul(
     596           9 :       incremental_cost,
     597           9 :       fd_ulong_sat_sub( points_len, 1 )
     598           9 :     )
     599           9 :   );
     600           9 :   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           9 :   if ( FD_UNLIKELY( points_len==0 ) ) {
     607           3 :     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           3 :   }
     613             : 
     614             :   /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1166-L1178 */
     615          18 :   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          18 :   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           3 :   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           3 :     fd_ed25519_point_t _r[1];
     623           3 :     fd_ed25519_point_t * r = multi_scalar_mul_edwards( _r, scalars, points, points_len );
     624             : 
     625           3 :     if( FD_LIKELY( r ) ) {
     626           3 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     627           3 :       fd_ed25519_point_tobytes( result, r );
     628           3 :       ret = 0UL;
     629           3 :     }
     630           3 :     break;
     631           3 :   }
     632             : 
     633           3 :   case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO: {
     634           3 :     fd_ristretto255_point_t _r[1];
     635           3 :     fd_ristretto255_point_t * r = multi_scalar_mul_ristretto( _r, scalars, points, points_len );
     636             : 
     637           3 :     if( FD_LIKELY( r ) ) {
     638           3 :       uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
     639           3 :       fd_ristretto255_point_tobytes( result, r );
     640           3 :       ret = 0UL;
     641           3 :     }
     642           3 :     break;
     643           3 :   }
     644             : 
     645           3 :   default:
     646             :     /* COV: this can never happen because of the previous switch */
     647           0 :     return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
     648          18 :   }
     649             : 
     650           6 : soft_error:
     651           6 :   *_ret = ret;
     652           6 :   return FD_VM_SUCCESS;
     653          18 : }
     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_POINT_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_POINT_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