LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_pubkey_utils.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 54 61 88.5 %
Date: 2024-11-13 11:58:15 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "fd_pubkey_utils.h"
       2             : #include "fd_executor_err.h"
       3             : #include "../vm/syscall/fd_vm_syscall.h"
       4             : #include "../../ballet/ed25519/fd_curve25519.h"
       5             : 
       6             : int
       7             : fd_pubkey_create_with_seed( fd_exec_instr_ctx_t const * ctx,
       8             :                             uchar const                 base [ static 32 ],
       9             :                             char const *                seed,
      10             :                             ulong                       seed_sz,
      11             :                             uchar const                 owner[ static 32 ],
      12        4161 :                             uchar                       out  [ static 32 ] ) {
      13             : 
      14        4161 :   static char const pda_marker[] = {"ProgramDerivedAddress"};
      15             : 
      16        4161 :   if( seed_sz>MAX_SEED_LEN ) {
      17         159 :     ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_MAX_SEED_LEN_EXCEEDED;
      18         159 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      19         159 :   }
      20             : 
      21        4002 :   if( 0==memcmp( owner+11UL, pda_marker, 21UL ) ) {
      22          42 :     ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_ILLEGAL_OWNER;
      23          42 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      24          42 :   }
      25             : 
      26        3960 :   fd_sha256_t sha;
      27        3960 :   fd_sha256_init( &sha );
      28             : 
      29        3960 :   fd_sha256_append( &sha, base,  32UL    );
      30        3960 :   fd_sha256_append( &sha, seed,  seed_sz );
      31        3960 :   fd_sha256_append( &sha, owner, 32UL    );
      32             : 
      33        3960 :   fd_sha256_fini( &sha, out );
      34             : 
      35        3960 :   return FD_EXECUTOR_INSTR_SUCCESS;
      36        4002 : }
      37             : 
      38             : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/sdk/program/src/pubkey.rs#L578-L625 */
      39             : int
      40             : fd_pubkey_derive_pda( fd_exec_instr_ctx_t const * ctx,
      41             :                       fd_pubkey_t const *         program_id, 
      42             :                       ulong                       seeds_cnt, 
      43             :                       uchar **                    seeds, 
      44             :                       ulong *                     seed_szs,
      45             :                       uchar *                     bump_seed, 
      46         798 :                       fd_pubkey_t *               out ) {
      47             :   /* https://github.com/anza-xyz/agave/blob/6ac4fe32e28d8ceb4085072b61fa0c6cb09baac1/sdk/program/src/pubkey.rs#L579-L581 */
      48         798 :   if( seeds_cnt + (bump_seed ? 1 : 0) > MAX_SEEDS ) { // In Agave, seeds_cnt includes the bump seed
      49           0 :     ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_MAX_SEED_LEN_EXCEEDED;
      50           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      51           0 :   }
      52             :   /* TODO: This does not contain size checks for the seed as checked in
      53             :      https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/sdk/program/src/pubkey.rs#L586-L588 */
      54             :                       
      55         798 :   fd_sha256_t sha = {0};
      56         798 :   fd_sha256_init( &sha );
      57        1809 :   for ( ulong i=0UL; i<seeds_cnt; i++ ) {
      58        1011 :     uchar * seed = *(seeds + i);
      59        1011 :     if( FD_UNLIKELY( !seed ) ) {
      60           0 :       break;
      61           0 :     }
      62        1011 :     fd_sha256_append( &sha, seed, seed_szs[i] );
      63        1011 :   }
      64             :     
      65         798 :   if( bump_seed ) {
      66         798 :     fd_sha256_append( &sha, bump_seed, 1UL );
      67         798 :   }
      68         798 :   fd_sha256_append( &sha, program_id,              sizeof(fd_pubkey_t) );
      69         798 :   fd_sha256_append( &sha, "ProgramDerivedAddress", 21UL                );
      70             : 
      71         798 :   fd_sha256_fini( &sha, out );
      72             : 
      73             :   /* A PDA is valid if it is not a valid ed25519 curve point.
      74             :      In most cases the user will have derived the PDA off-chain, 
      75             :      or the PDA is a known signer. 
      76             :      https://github.com/anza-xyz/agave/blob/6ac4fe32e28d8ceb4085072b61fa0c6cb09baac1/sdk/program/src/pubkey.rs#L599-L601 */
      77         798 :   if( FD_UNLIKELY( fd_ed25519_point_validate( out->key ) ) ) {
      78         333 :     ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_INVALID_SEEDS;
      79         333 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      80         333 :   }
      81             : 
      82         465 :   return FD_PUBKEY_SUCCESS;
      83         798 : }
      84             : 
      85             : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/sdk/program/src/pubkey.rs#L477-L534 */
      86             : int
      87             : fd_pubkey_find_program_address( fd_exec_instr_ctx_t const * ctx,
      88             :                                 fd_pubkey_t const *         program_id, 
      89             :                                 ulong                       seeds_cnt, 
      90             :                                 uchar **                    seeds, 
      91             :                                 ulong *                     seed_szs,
      92             :                                 fd_pubkey_t *               out,
      93         162 :                                 uchar *                     out_bump_seed ) {
      94         162 :   uchar bump_seed[ 1UL ];
      95         423 :   for ( ulong i=0UL; i<256UL; ++i ) {
      96         423 :     bump_seed[ 0UL ] = (uchar)(255UL - i);
      97             : 
      98         423 :     fd_pubkey_t derived[ 1UL ];
      99         423 :     int err = fd_pubkey_derive_pda( ctx, program_id, seeds_cnt, seeds, seed_szs, bump_seed, derived );
     100         423 :     if( err==FD_PUBKEY_SUCCESS ) {
     101             :       /* Stop looking if we have found a valid PDA */
     102         162 :       fd_memcpy( out, derived, sizeof(fd_pubkey_t) );
     103         162 :       fd_memcpy( out_bump_seed, bump_seed, 1UL );
     104         162 :       break;
     105         261 :     } else if( err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR && ctx->txn_ctx->custom_err!=FD_PUBKEY_ERR_INVALID_SEEDS ) { 
     106           0 :       return err;
     107           0 :     }
     108         423 :   }
     109             : 
     110             :   // Custom error may get set in fd_pubkey_derive_pda call
     111         162 :   ctx->txn_ctx->custom_err = UINT_MAX;
     112         162 :   return FD_PUBKEY_SUCCESS;
     113         162 : }

Generated by: LCOV version 1.14