LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_precompiles.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 228 0.0 %
Date: 2025-09-16 04:29:32 Functions: 0 4 0.0 %

          Line data    Source code
       1             : #include "fd_precompiles.h"
       2             : #include "../fd_bank.h"
       3             : #include "../fd_executor_err.h"
       4             : #include "../../../ballet/keccak256/fd_keccak256.h"
       5             : #include "../../../ballet/ed25519/fd_ed25519.h"
       6             : #include "../../../ballet/secp256k1/fd_secp256k1.h"
       7             : #include "../../../ballet/secp256r1/fd_secp256r1.h"
       8             : 
       9             : /* Docs:
      10             :    https://docs.solana.com/developing/runtime-facilities/programs#ed25519-program
      11             :    https://docs.solana.com/developing/runtime-facilities/programs#secp256k1-program */
      12             : 
      13             : /* There are 3 precompiles and 2 ways to serialize data.
      14             :    The most recent one seems are ed25519 and secp256r1 with 2 bytes per instruction,
      15             :    that works better with JS sdk even though it consumes a few bytes. */
      16             : struct __attribute__((packed)) fd_precompile_sig_offsets {
      17             :   ushort sig_offset;
      18             :   ushort sig_instr_idx;
      19             :   ushort pubkey_offset;
      20             :   ushort pubkey_instr_idx;
      21             :   ushort msg_offset;
      22             :   ushort msg_data_sz;
      23             :   ushort msg_instr_idx;
      24             : };
      25             : typedef struct fd_precompile_sig_offsets fd_ed25519_signature_offsets_t;
      26             : typedef struct fd_precompile_sig_offsets fd_secp256r1_signature_offsets_t;
      27             : 
      28             : struct __attribute__((packed)) fd_precompile_one_byte_idx_sig_offsets {
      29             :   ushort sig_offset;
      30             :   uchar  sig_instr_idx;
      31             :   ushort pubkey_offset;
      32             :   uchar  pubkey_instr_idx;
      33             :   ushort msg_offset;
      34             :   ushort msg_data_sz;
      35             :   uchar  msg_instr_idx;
      36             : };
      37             : typedef struct fd_precompile_one_byte_idx_sig_offsets fd_secp256k1_signature_offsets_t;
      38             : 
      39             : /*
      40             :   Common
      41             : */
      42             : 
      43           0 : #define SIGNATURE_SERIALIZED_SIZE         (64UL)
      44           0 : #define SIGNATURE_OFFSETS_SERIALIZED_SIZE (14UL)
      45           0 : #define SIGNATURE_OFFSETS_START            (2UL)
      46             : #define DATA_START (SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START)
      47             : 
      48             : /*
      49             :   Custom
      50             : */
      51             : 
      52           0 : #define ED25519_PUBKEY_SERIALIZED_SIZE              (32UL)
      53             : 
      54           0 : #define SECP256R1_PUBKEY_SERIALIZED_SIZE            (33UL)
      55             : 
      56           0 : #define SECP256K1_PUBKEY_SERIALIZED_SIZE            (20UL)
      57           0 : #define SECP256K1_SIGNATURE_OFFSETS_SERIALIZED_SIZE (11UL)
      58           0 : #define SECP256K1_SIGNATURE_OFFSETS_START            (1UL)
      59             : #define SECP256K1_DATA_START (SECP256K1_SIGNATURE_OFFSETS_SERIALIZED_SIZE + SECP256K1_SIGNATURE_OFFSETS_START)
      60             : 
      61             : FD_STATIC_ASSERT( sizeof( fd_ed25519_signature_offsets_t )==SIGNATURE_OFFSETS_SERIALIZED_SIZE, fd_ballet );
      62             : FD_STATIC_ASSERT( sizeof( fd_secp256k1_signature_offsets_t )==SECP256K1_SIGNATURE_OFFSETS_SERIALIZED_SIZE, fd_ballet );
      63             : 
      64             : /*
      65             :   Common code
      66             : */
      67             : 
      68             : /* fd_precompile_get_instr_data fetches data across instructions.
      69             :    In Agave, the 2 precompiles have slightly different behavior:
      70             :    1. Ed25519 has 16-bit instr index vs Secp256k1 has 8-bit
      71             :    2. Ed25519 accepts instr index==0xFFFF as a special value to indicate
      72             :       the current instruction, Secp256k1 doesn't have this feature
      73             :    3. Ed25519 always return InvalidDataOffsets, while Secp256k1 can
      74             :       return InvalidDataOffsets or InvalidSignature
      75             :    All these differences are completely useless, so we unify the logic.
      76             :    We handle the special case of index==0xFFFF as in Ed25519.
      77             :    We handle errors as in Secp256k1. */
      78             : static inline int
      79             : fd_precompile_get_instr_data( fd_exec_instr_ctx_t * ctx,
      80             :                               ushort                index,
      81             :                               ushort                offset,
      82             :                               ushort                sz,
      83           0 :                               uchar const **        res ) {
      84           0 :   uchar const * data;
      85           0 :   ulong         data_sz;
      86             :   /* The special value index==USHORT_MAX means current instruction.
      87             :      This feature has been introduced for ed25519, but not for secp256k1 where
      88             :      index is 1-byte only.
      89             :      So, fortunately, we can use the same function.
      90             :      https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L161-L163
      91             :      https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L1018 */
      92           0 :   if( index==USHORT_MAX ) {
      93             : 
      94             :     /* Use current instruction data */
      95           0 :     data    = ctx->instr->data;
      96           0 :     data_sz = ctx->instr->data_sz;
      97             : 
      98           0 :   } else {
      99             : 
     100           0 :     if( FD_UNLIKELY( index>=ctx->txn_ctx->instr_info_cnt ) )
     101           0 :       return FD_EXECUTOR_PRECOMPILE_ERR_DATA_OFFSET;
     102             : 
     103           0 :     fd_instr_info_t const * instr = &ctx->txn_ctx->instr_infos[ index ];
     104           0 :     data    = instr->data;
     105           0 :     data_sz = instr->data_sz;
     106             : 
     107           0 :   }
     108             : 
     109           0 :   if( FD_UNLIKELY( (ulong)offset+(ulong)sz > data_sz ) )  /* (offset+sz) in [0,2^17) */
     110           0 :     return FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE;
     111             : 
     112           0 :   *res = data + offset;
     113           0 :   return 0;
     114           0 : }
     115             : 
     116             : /*
     117             :   Ed25519
     118             : */
     119             : 
     120             : int
     121           0 : fd_precompile_ed25519_verify( fd_exec_instr_ctx_t * ctx ) {
     122             : 
     123           0 :   uchar const * data    = ctx->instr->data;
     124           0 :   ulong         data_sz = ctx->instr->data_sz;
     125             : 
     126             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L90-L96
     127             :      note: this part is really silly and in fact in leaves out the edge case [0, 0].
     128             : 
     129             :      Our implementation does the following:
     130             :      1. assert that there's enough data to deser 1+ fd_ed25519_sig_offsets
     131             :         (in particular, data[0] is accessible)
     132             :         - in the unlikely case, check for the Agave edge case
     133             :      2. if data[0]==0 return
     134             :      3. compute and check expected size */
     135           0 :   if( FD_UNLIKELY( data_sz < DATA_START ) ) {
     136           0 :     if( FD_UNLIKELY( data_sz == 2 && data[0] == 0 ) ) {
     137           0 :       return FD_EXECUTOR_INSTR_SUCCESS;
     138           0 :     }
     139           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     140           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     141           0 :   }
     142             : 
     143           0 :   ulong sig_cnt = data[0];
     144           0 :   if( FD_UNLIKELY( sig_cnt==0 ) ) {
     145           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     146           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     147           0 :   }
     148             : 
     149             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L97-L103 */
     150           0 :   ulong expected_data_size = sig_cnt * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START;
     151           0 :   if( FD_UNLIKELY( data_sz < expected_data_size ) ) {
     152           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     153           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     154           0 :   }
     155             : 
     156           0 :   ulong off = SIGNATURE_OFFSETS_START;
     157           0 :   for( ulong i = 0; i < sig_cnt; ++i ) {
     158           0 :     fd_ed25519_signature_offsets_t const * sigoffs = (const fd_ed25519_signature_offsets_t *) (data + off);
     159           0 :     off += SIGNATURE_OFFSETS_SERIALIZED_SIZE;
     160             : 
     161             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L110-L112 */
     162             :     // ???
     163             : 
     164             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L114-L121 */
     165           0 :     uchar const * sig = NULL;
     166           0 :     int err = fd_precompile_get_instr_data( ctx,
     167           0 :                                             sigoffs->sig_instr_idx,
     168           0 :                                             sigoffs->sig_offset,
     169           0 :                                             SIGNATURE_SERIALIZED_SIZE,
     170           0 :                                             &sig );
     171           0 :     if( FD_UNLIKELY( err ) ) {
     172           0 :       ctx->txn_ctx->custom_err = (uint)err;
     173           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     174           0 :     }
     175             : 
     176             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L123-L124
     177             :        Note: we parse the signature as part of fd_ed25519_verify.
     178             :        Because of this, the return error code might be different from Agave in some edge cases. */
     179             : 
     180             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L126-L133 */
     181           0 :     uchar const * pubkey = NULL;
     182           0 :     err = fd_precompile_get_instr_data( ctx,
     183           0 :                                         sigoffs->pubkey_instr_idx,
     184           0 :                                         sigoffs->pubkey_offset,
     185           0 :                                         ED25519_PUBKEY_SERIALIZED_SIZE,
     186           0 :                                         &pubkey );
     187           0 :     if( FD_UNLIKELY( err ) ) {
     188           0 :       ctx->txn_ctx->custom_err = (uint)err;
     189           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     190           0 :     }
     191             : 
     192             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L135-L136
     193             :        Note: we parse the public key as part of fd_ed25519_verify.
     194             :        Because of this, the return error code might be different from Agave in some edge cases. */
     195             : 
     196             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L138-L145 */
     197           0 :     uchar const * msg = NULL;
     198           0 :     ushort msg_sz = sigoffs->msg_data_sz;
     199           0 :     err = fd_precompile_get_instr_data( ctx,
     200           0 :                                         sigoffs->msg_instr_idx,
     201           0 :                                         sigoffs->msg_offset,
     202           0 :                                         msg_sz,
     203           0 :                                         &msg );
     204           0 :     if( FD_UNLIKELY( err ) ) {
     205           0 :       ctx->txn_ctx->custom_err = (uint)err;
     206           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     207           0 :     }
     208             : 
     209             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/ed25519_instruction.rs#L147-L149 */
     210           0 :     fd_sha512_t sha[1];
     211           0 :     if( FD_UNLIKELY( fd_ed25519_verify( msg, msg_sz, sig, pubkey, sha )!=FD_ED25519_SUCCESS ) ) {
     212           0 :       ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE;
     213           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     214           0 :     }
     215           0 :   }
     216             : 
     217           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     218           0 : }
     219             : 
     220             : /*
     221             :   Secp256K1
     222             : */
     223             : 
     224             : int
     225           0 : fd_precompile_secp256k1_verify( fd_exec_instr_ctx_t * ctx ) {
     226             : 
     227           0 :   uchar const * data    = ctx->instr->data;
     228           0 :   ulong         data_sz = ctx->instr->data_sz;
     229             : 
     230             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L934-L947
     231             :      see comment in ed25519, here the special case is [0] instead of [0, 0] */
     232           0 :   if( FD_UNLIKELY( data_sz < SECP256K1_DATA_START ) ) {
     233           0 :     if( FD_UNLIKELY( data_sz == 1 && data[0] == 0 ) ) {
     234           0 :       return FD_EXECUTOR_INSTR_SUCCESS;
     235           0 :     }
     236           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     237           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     238           0 :   }
     239             : 
     240             :   /* https://github.com/anza-xyz/agave/blob/574bae8fefc0ed256b55340b9d87b7689bcdf222/sdk/src/secp256k1_instruction.rs#L938-L947 */
     241           0 :   ulong sig_cnt = data[0];
     242           0 :   if( FD_UNLIKELY( sig_cnt==0 && data_sz>1 ) ) {
     243           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     244           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     245           0 :   }
     246             : 
     247             :   /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L948-L953 */
     248           0 :   ulong expected_data_size = sig_cnt * SECP256K1_SIGNATURE_OFFSETS_SERIALIZED_SIZE + SECP256K1_SIGNATURE_OFFSETS_START;
     249           0 :   if( FD_UNLIKELY( data_sz < expected_data_size ) ) {
     250           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     251           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     252           0 :   }
     253             : 
     254           0 :   ulong off = SECP256K1_SIGNATURE_OFFSETS_START;
     255           0 :   for( ulong i = 0; i < sig_cnt; ++i ) {
     256           0 :     fd_secp256k1_signature_offsets_t const * sigoffs = (const fd_secp256k1_signature_offsets_t *) (data + off);
     257           0 :     off += SECP256K1_SIGNATURE_OFFSETS_SERIALIZED_SIZE;
     258             : 
     259             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L960-L961 */
     260             :     // ???
     261             : 
     262             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L963-L973
     263             :        Note: for whatever reason, Agave returns InvalidInstructionDataSize instead of InvalidDataOffsets.
     264             :        We just return the err as is. */
     265           0 :     uchar const * sig = NULL;
     266           0 :     int err = fd_precompile_get_instr_data( ctx,
     267           0 :                                             sigoffs->sig_instr_idx,
     268           0 :                                             sigoffs->sig_offset,
     269           0 :                                             SIGNATURE_SERIALIZED_SIZE + 1, /* extra byte is recovery id */
     270           0 :                                             &sig );
     271           0 :     if( FD_UNLIKELY( err ) ) {
     272           0 :       ctx->txn_ctx->custom_err = (uint)err;
     273           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     274           0 :     }
     275             : 
     276             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L975-L981
     277             :        Note: we parse the signature and recovery id as part of fd_secp256k1_recover.
     278             :        Because of this, the return error code might be different from Agave in some edge cases. */
     279           0 :     int recovery_id = (int)sig[SIGNATURE_SERIALIZED_SIZE]; /* extra byte is recovery id */
     280             : 
     281             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L983-L989 */
     282           0 :     uchar const * eth_address = NULL;
     283           0 :     err = fd_precompile_get_instr_data( ctx,
     284           0 :                                         sigoffs->pubkey_instr_idx,
     285           0 :                                         sigoffs->pubkey_offset,
     286           0 :                                         SECP256K1_PUBKEY_SERIALIZED_SIZE,
     287           0 :                                         &eth_address );
     288           0 :     if( FD_UNLIKELY( err ) ) {
     289           0 :       ctx->txn_ctx->custom_err = (uint)err;
     290           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     291           0 :     }
     292             : 
     293             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L991-L997 */
     294           0 :     uchar const * msg = NULL;
     295           0 :     ushort msg_sz = sigoffs->msg_data_sz;
     296           0 :     err = fd_precompile_get_instr_data( ctx,
     297           0 :                                         sigoffs->msg_instr_idx,
     298           0 :                                         sigoffs->msg_offset,
     299           0 :                                         msg_sz,
     300           0 :                                         &msg );
     301           0 :     if( FD_UNLIKELY( err ) ) {
     302           0 :       ctx->txn_ctx->custom_err = (uint)err;
     303           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     304           0 :     }
     305             : 
     306             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L999-L1001 */
     307           0 :     uchar msg_hash[ FD_KECCAK256_HASH_SZ ];
     308           0 :     fd_keccak256_hash( msg, msg_sz, msg_hash );
     309             : 
     310             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L1003-L1008 */
     311           0 :     uchar pubkey[64];
     312           0 :     if ( FD_UNLIKELY( fd_secp256k1_recover( pubkey, msg_hash, sig, recovery_id ) == NULL ) ) {
     313           0 :       ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE;
     314           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     315           0 :     }
     316             : 
     317             :     /* https://github.com/anza-xyz/agave/blob/v1.18.12/sdk/src/secp256k1_instruction.rs#L1009-L1013 */
     318           0 :     uchar pubkey_hash[ FD_KECCAK256_HASH_SZ ];
     319           0 :     fd_keccak256_hash( pubkey, 64, pubkey_hash );
     320             : 
     321           0 :     if( FD_UNLIKELY( memcmp( eth_address, pubkey_hash+(FD_KECCAK256_HASH_SZ-SECP256K1_PUBKEY_SERIALIZED_SIZE), SECP256K1_PUBKEY_SERIALIZED_SIZE ) ) ) {
     322           0 :       ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE;
     323           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     324           0 :     }
     325           0 :   }
     326             : 
     327           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     328           0 : }
     329             : 
     330             : /*
     331             :   Secp256r1
     332             : */
     333             : 
     334             : #ifdef FD_HAS_S2NBIGNUM
     335             : int
     336           0 : fd_precompile_secp256r1_verify( fd_exec_instr_ctx_t * ctx ) {
     337           0 :   if( FD_UNLIKELY( !FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, enable_secp256r1_precompile ) ) ) {
     338           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
     339           0 :   }
     340             : 
     341           0 :   uchar const * data    = ctx->instr->data;
     342           0 :   ulong         data_sz = ctx->instr->data_sz;
     343             : 
     344             :   /* ... */
     345           0 :   if( FD_UNLIKELY( data_sz < DATA_START ) ) {
     346           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     347           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     348           0 :   }
     349             : 
     350           0 :   ulong sig_cnt = data[0];
     351           0 :   if( FD_UNLIKELY( sig_cnt==0UL ) ) {
     352           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     353           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     354           0 :   }
     355             : 
     356             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/precompiles/src/secp256r1.rs#L30 */
     357           0 :   if( FD_UNLIKELY( sig_cnt>8UL ) ) {
     358           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     359           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     360           0 :   }
     361             : 
     362             :   /* ... */
     363           0 :   ulong expected_data_size = sig_cnt * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START;
     364           0 :   if( FD_UNLIKELY( data_sz < expected_data_size ) ) {
     365           0 :     ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_INSTR_DATA_SIZE;
     366           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     367           0 :   }
     368             : 
     369           0 :   ulong off = SIGNATURE_OFFSETS_START;
     370           0 :   for( ulong i = 0; i < sig_cnt; ++i ) {
     371           0 :     fd_secp256r1_signature_offsets_t const * sigoffs = (const fd_secp256r1_signature_offsets_t *) (data + off);
     372           0 :     off += SIGNATURE_OFFSETS_SERIALIZED_SIZE;
     373             : 
     374             :     /* ... */
     375           0 :     uchar const * sig = NULL;
     376           0 :     int err = fd_precompile_get_instr_data( ctx,
     377           0 :                                             sigoffs->sig_instr_idx,
     378           0 :                                             sigoffs->sig_offset,
     379           0 :                                             SIGNATURE_SERIALIZED_SIZE,
     380           0 :                                             &sig );
     381           0 :     if( FD_UNLIKELY( err ) ) {
     382           0 :       ctx->txn_ctx->custom_err = (uint)err;
     383           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     384           0 :     }
     385             : 
     386             :     /* ... */
     387           0 :     uchar const * pubkey = NULL;
     388           0 :     err = fd_precompile_get_instr_data( ctx,
     389           0 :                                         sigoffs->pubkey_instr_idx,
     390           0 :                                         sigoffs->pubkey_offset,
     391           0 :                                         SECP256R1_PUBKEY_SERIALIZED_SIZE,
     392           0 :                                         &pubkey );
     393           0 :     if( FD_UNLIKELY( err ) ) {
     394           0 :       ctx->txn_ctx->custom_err = (uint)err;
     395           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     396           0 :     }
     397             : 
     398             :     /* ... */
     399           0 :     uchar const * msg = NULL;
     400           0 :     ushort msg_sz = sigoffs->msg_data_sz;
     401           0 :     err = fd_precompile_get_instr_data( ctx,
     402           0 :                                         sigoffs->msg_instr_idx,
     403           0 :                                         sigoffs->msg_offset,
     404           0 :                                         msg_sz,
     405           0 :                                         &msg );
     406           0 :     if( FD_UNLIKELY( err ) ) {
     407           0 :       ctx->txn_ctx->custom_err = (uint)err;
     408           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     409           0 :     }
     410             : 
     411             :     /* ... */
     412           0 :     fd_sha256_t sha[1];
     413           0 :     if( FD_UNLIKELY( fd_secp256r1_verify( msg, msg_sz, sig, pubkey, sha )!=FD_SECP256R1_SUCCESS ) ) {
     414           0 :       ctx->txn_ctx->custom_err = FD_EXECUTOR_PRECOMPILE_ERR_SIGNATURE;
     415           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     416           0 :     }
     417           0 :   }
     418             : 
     419           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     420           0 : }
     421             : #else
     422             : int
     423             : fd_precompile_secp256r1_verify( FD_PARAM_UNUSED fd_exec_instr_ctx_t * ctx ) {
     424             :   return FD_EXECUTOR_INSTR_ERR_FATAL;
     425             : }
     426             : #endif

Generated by: LCOV version 1.14