LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_precompiles.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 167 234 71.4 %
Date: 2024-11-13 11:58:15 Functions: 3 4 75.0 %

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

Generated by: LCOV version 1.14