LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_pubkey_utils.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 36 61 59.0 %
Date: 2025-03-20 12:08:36 Functions: 2 3 66.7 %

          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           0 :                             uchar                       out  [ static 32 ] ) {
      13             : 
      14           0 :   static char const pda_marker[] = {"ProgramDerivedAddress"};
      15             : 
      16           0 :   if( seed_sz>MAX_SEED_LEN ) {
      17           0 :     ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_MAX_SEED_LEN_EXCEEDED;
      18           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      19           0 :   }
      20             : 
      21           0 :   if( 0==memcmp( owner+11UL, pda_marker, 21UL ) ) {
      22           0 :     ctx->txn_ctx->custom_err = FD_PUBKEY_ERR_ILLEGAL_OWNER;
      23           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      24           0 :   }
      25             : 
      26           0 :   fd_sha256_t sha;
      27           0 :   fd_sha256_init( &sha );
      28             : 
      29           0 :   fd_sha256_append( &sha, base,  32UL    );
      30           0 :   fd_sha256_append( &sha, seed,  seed_sz );
      31           0 :   fd_sha256_append( &sha, owner, 32UL    );
      32             : 
      33           0 :   fd_sha256_fini( &sha, out );
      34             : 
      35           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      36           0 : }
      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_pubkey_t const * program_id, 
      41             :                       ulong               seeds_cnt, 
      42             :                       uchar **            seeds, 
      43             :                       ulong *             seed_szs,
      44             :                       uchar *             bump_seed, 
      45             :                       fd_pubkey_t *       out,
      46         189 :                       uint *              custom_err ) {
      47             :   /* https://github.com/anza-xyz/agave/blob/6ac4fe32e28d8ceb4085072b61fa0c6cb09baac1/sdk/program/src/pubkey.rs#L579-L581 */
      48         189 :   if( seeds_cnt + (bump_seed ? 1 : 0) > MAX_SEEDS ) { // In Agave, seeds_cnt includes the bump seed
      49           0 :     *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         189 :   fd_sha256_t sha = {0};
      56         189 :   fd_sha256_init( &sha );
      57         378 :   for ( ulong i=0UL; i<seeds_cnt; i++ ) {
      58         189 :     uchar * seed = *(seeds + i);
      59         189 :     if( FD_UNLIKELY( !seed ) ) {
      60           0 :       break;
      61           0 :     }
      62         189 :     fd_sha256_append( &sha, seed, seed_szs[i] );
      63         189 :   }
      64             :     
      65         189 :   if( bump_seed ) {
      66         189 :     fd_sha256_append( &sha, bump_seed, 1UL );
      67         189 :   }
      68         189 :   fd_sha256_append( &sha, program_id,              sizeof(fd_pubkey_t) );
      69         189 :   fd_sha256_append( &sha, "ProgramDerivedAddress", 21UL                );
      70             : 
      71         189 :   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         189 :   if( FD_UNLIKELY( fd_ed25519_point_validate( out->key ) ) ) {
      78          90 :     *custom_err = FD_PUBKEY_ERR_INVALID_SEEDS;
      79          90 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
      80          90 :   }
      81             : 
      82          99 :   return FD_PUBKEY_SUCCESS;
      83         189 : }
      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_pubkey_t const * program_id, 
      88             :                                 ulong               seeds_cnt, 
      89             :                                 uchar **            seeds, 
      90             :                                 ulong *             seed_szs,
      91             :                                 fd_pubkey_t *       out,
      92             :                                 uchar *             out_bump_seed,
      93          99 :                                 uint *              custom_err ) {
      94          99 :   uchar bump_seed[ 1UL ];
      95         189 :   for ( ulong i=0UL; i<256UL; ++i ) {
      96         189 :     bump_seed[ 0UL ] = (uchar)(255UL - i);
      97             : 
      98         189 :     fd_pubkey_t derived[ 1UL ];
      99         189 :     int err = fd_pubkey_derive_pda( program_id, seeds_cnt, seeds, seed_szs, bump_seed, derived, custom_err );
     100         189 :     if( err==FD_PUBKEY_SUCCESS ) {
     101             :       /* Stop looking if we have found a valid PDA */
     102          99 :       fd_memcpy( out, derived, sizeof(fd_pubkey_t) );
     103          99 :       fd_memcpy( out_bump_seed, bump_seed, 1UL );
     104          99 :       break;
     105          99 :     } else if( err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR && *custom_err!=FD_PUBKEY_ERR_INVALID_SEEDS ) { 
     106           0 :       return err;
     107           0 :     }
     108         189 :   }
     109             : 
     110             :   // Custom error may get set in fd_pubkey_derive_pda call
     111          99 :   *custom_err = UINT_MAX;
     112          99 :   return FD_PUBKEY_SUCCESS;
     113          99 : }

Generated by: LCOV version 1.14