LCOV - code coverage report
Current view: top level - disco/keyguard - fd_keyguard_authorize.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 66 279 23.7 %
Date: 2026-09-17 04:28:31 Functions: 3 11 27.3 %

          Line data    Source code
       1             : #include "fd_keyguard.h"
       2             : #include "fd_keyguard_client.h"
       3             : #include "../bundle/fd_bundle_crank_constants.h"
       4             : #include "../../flamenco/runtime/fd_system_ids.h"
       5             : #include "../../flamenco/gossip/fd_gossip_value.h"
       6             : #include "../../ballet/txn/fd_compact_u16.h"
       7             : #include "../../waltz/tls/fd_tls.h"
       8             : /* manually include just fd_features_generated.h so we can get
       9             :    FD_FEATURE_SET_ID without anything else that we don't need. */
      10             : #define HEADER_fd_src_flamenco_features_fd_features_h
      11             : #include "../../flamenco/features/fd_features_generated.h"
      12             : #undef HEADER_fd_src_flamenco_features_fd_features_h
      13             : 
      14             : struct fd_keyguard_sign_req {
      15             :   fd_keyguard_authority_t * authority;
      16             : };
      17             : 
      18             : typedef struct fd_keyguard_sign_req fd_keyguard_sign_req_t;
      19             : 
      20             : static int
      21             : fd_keyguard_authorize_vote_txn( fd_keyguard_authority_t const * authority,
      22             :                                 uchar const *                   data,
      23             :                                 ulong                           sz,
      24           3 :                                 int                             sign_type ) {
      25           3 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
      26           3 :   if( sz > FD_TXN_MTU_V0 ) return 0;
      27             :   /* Each vote transaction may have 1 or 2 signers.  The first byte in
      28             :      the transaction message is the number of signers. */
      29           3 :   ulong off = 0UL;
      30           3 :   uchar signer_cnt = data[off];
      31           3 :   if( signer_cnt!=1 && signer_cnt!=2 ) return 0;
      32           3 :   if( signer_cnt==1 && sz<=140 ) return 0;
      33           3 :   if( signer_cnt==2 && sz<=172 ) return 0;
      34             :   /* The authority's public key will be the first listed account in the
      35             :      transaction message. */
      36             : 
      37             :   /* r/o signers = 1 when there are 2 signers and 1 otherwise. */
      38           0 :   off++;
      39           0 :   if( data[off]!=signer_cnt-1 ) return 0;
      40             : 
      41             :   /* There will always be 1 r/o unsigned account. */
      42           0 :   off++;
      43           0 :   if( data[off]!=1 ) return 0;
      44             : 
      45             :   /* The only accounts should be the 1 or 2 signers, the vote account,
      46             :      and the vote program.  The number of accounts is represented as a
      47             :      compact u16. */
      48           0 :   off++;
      49           0 :   ulong bytes = fd_cu16_dec_sz( data+off, 3UL );
      50           0 :   if( bytes!=1UL ) return 0;
      51           0 :   ulong acc_cnt = 2UL + signer_cnt;
      52           0 :   if( data[off]!=acc_cnt ) return 0;
      53             : 
      54             :   /* The first account should always be the authority's public key. */
      55           0 :   off++;
      56           0 :   ulong acct_off = off;
      57           0 :   if( memcmp( authority->identity_pubkey, data + acct_off, 32 ) ) return 0;
      58             : 
      59             :   /* Each transaction account key is listed out and is followed by a 32
      60             :      byte blockhash.  The instruction count is after this. */
      61           0 :   off += (acc_cnt+1) * 32;
      62           0 :   bytes = fd_cu16_dec_sz( data+off, 3UL );
      63           0 :   uchar instr_cnt = data[ off ];
      64           0 :   if( bytes!=1UL ) return 0;
      65           0 :   if( instr_cnt!=1 ) return 0;
      66             : 
      67             :   /* The program id will be the first byte of the instruction payload
      68             :      and should be the vote program. */
      69           0 :   off++;
      70           0 :   uchar program_id = data[ off ];
      71           0 :   if( program_id != acc_cnt-1 ) return 0;
      72           0 :   ulong program_acct_off = 4UL + (program_id * 32UL);
      73           0 :   if( memcmp( &fd_solana_vote_program_id, data+program_acct_off, 32 ) ) return 0;
      74             : 
      75           0 :   off++;
      76           0 :   bytes = fd_cu16_dec_sz( data+off, 3UL );
      77           0 :   if( bytes!=1UL ) return 0;
      78             : 
      79             :   /* Vote account count will always be 2.  One byte is used to list the
      80             :      account count for the transaction and 1 byte for each account. */
      81           0 :   if( data[ off ]!=2 ) return 0;
      82           0 :   off += 3UL;
      83             : 
      84             :   /* Move the cursor forward by the instruction data size.  The first
      85             :      byte of the instruction data will be the discriminant.  Only allow
      86             :      tower sync vote instructions (14). */
      87           0 :   bytes = fd_cu16_dec_sz( data+off, 3UL );
      88           0 :   off += bytes;
      89           0 :   if( data[off]!=14 ) return 0;
      90             : 
      91           0 :   return 1;
      92           0 : }
      93             : 
      94             : static int
      95             : fd_keyguard_authorize_gossip( fd_keyguard_authority_t const * authority,
      96             :                               uchar const *                   data,
      97             :                               ulong                           sz,
      98           0 :                               int                             sign_type ) {
      99           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     100             : 
     101             :   /* Every gossip message contains a 4 byte enum variant tag (at the
     102             :      beginning of the message) and a 32 byte public key (at an arbitrary
     103             :      location). */
     104           0 :   if( sz<36UL        ) return 0;
     105           0 :   if( sz>1188UL-64UL ) return 0;
     106             : 
     107           0 :   uint tag = FD_LOAD( uint, data );
     108           0 :   ulong origin_off = ULONG_MAX;
     109           0 :   switch( tag ) {
     110           0 :     case FD_GOSSIP_VALUE_VOTE:
     111           0 :       origin_off = 1UL;
     112           0 :       if( sz<4UL+1UL+32UL+FD_TXN_MIN_SERIALIZED_SZ+8UL ) return 0;
     113           0 :       ulong sig_cnt = data[ 4UL+1UL+32UL ];
     114           0 :       if( (sig_cnt==0UL) | (sig_cnt>2UL) ) return 0;
     115           0 :       ulong vote_off = 4UL+1UL+32UL+1UL+64UL*sig_cnt;
     116           0 :       if( !fd_keyguard_authorize_vote_txn( authority, data+vote_off, sz-(vote_off+8UL), FD_KEYGUARD_SIGN_TYPE_ED25519 ) )
     117           0 :         return 0;
     118           0 :       break;
     119           0 :     case FD_GOSSIP_VALUE_CONTACT_INFO:
     120           0 :       origin_off = 0UL;
     121             :       /* Contact info is pretty tough to parse.  The best we can do is
     122             :          check the feature set and client ID.
     123             :          min sz
     124             :           4B      tag
     125             :          32B      origin
     126             :           1B-10B  wallclock
     127             :           8B      outset
     128             :           2B      shred version
     129             :           1B-3B   major version
     130             :           1B-3B   minor version
     131             :           1B-3B   patch version
     132             :           4B      commit
     133             :           4B      feature set
     134             :           1B-3B   client ID
     135             :           1B-3B   unique addr cnt
     136             :           ???     IP addresses
     137             :           1B-3B   socket cnt
     138             :           ???     ports
     139             :           1B-3B   extension len
     140             :           ...
     141             : 
     142             :         Total: 62B+
     143             :          */
     144           0 :       if( sz<62UL     ) return 0;
     145           0 :       ulong off = 4UL+32UL;
     146           0 :       for( ulong i=0UL; i<10UL; i++ ) if( !(data[ off++ ]&0x80) ) break;
     147           0 :       off += 8UL+2UL;
     148             :       /* off<56, so we're still safe here */
     149           0 :       if( sz<off+15UL ) return 0;
     150           0 :       for( ulong i=0UL; i<3UL;  i++ ) if( !(data[ off++ ]&0x80) ) break;
     151           0 :       for( ulong i=0UL; i<3UL;  i++ ) if( !(data[ off++ ]&0x80) ) break;
     152           0 :       for( ulong i=0UL; i<3UL;  i++ ) if( !(data[ off++ ]&0x80) ) break;
     153           0 :       if( sz<off+12UL ) return 0;
     154           0 :       uint  commit      = FD_LOAD( uint, data+off ); off += 4UL;
     155           0 :       uint  feature_set = FD_LOAD( uint, data+off ); off += 4UL;
     156           0 :       uchar client_id   = data[ off ];
     157           0 :       (void)commit; /* Checking commit introduces a circular dependency between disco and app :'( */
     158           0 :       if( feature_set!=FD_FEATURE_SET_ID ) return 0;
     159           0 :       if( client_id  !=5                 ) return 0; /* FD_GOSSIP_CONTACT_INFO_CLIENT_FIREDANCER */
     160             : 
     161           0 :       break;
     162           0 :     case FD_GOSSIP_VALUE_DUPLICATE_SHRED:
     163           0 :       origin_off = 2UL;
     164           0 :       if( sz< 4UL+65UL           ) return 0;
     165           0 :       ulong chunk_len = FD_LOAD( ulong, data+4UL+57UL );
     166           0 :       if( sz!=4UL+65UL+chunk_len ) return 0;
     167           0 :       break;
     168             : 
     169             :     /* We don't sign these yet. */
     170           0 :     case FD_GOSSIP_VALUE_NODE_INSTANCE:   /* origin_off = 0UL; break; */ return 0;
     171           0 :     case FD_GOSSIP_VALUE_SNAPSHOT_HASHES: /* origin_off = 0UL; break; */ return 0;
     172             : 
     173             :     /* We refuse to serialize these */
     174           0 :     case FD_GOSSIP_VALUE_LEGACY_CONTACT_INFO:
     175           0 :     case FD_GOSSIP_VALUE_LOWEST_SLOT:
     176           0 :     case FD_GOSSIP_VALUE_LEGACY_SNAPSHOT_HASHES:
     177           0 :     case FD_GOSSIP_VALUE_ACCOUNT_HASHES:
     178           0 :     case FD_GOSSIP_VALUE_EPOCH_SLOTS:
     179           0 :     case FD_GOSSIP_VALUE_LEGACY_VERSION:
     180           0 :     case FD_GOSSIP_VALUE_VERSION:
     181           0 :     case FD_GOSSIP_VALUE_RESTART_LAST_VOTED_FORK_SLOTS:
     182           0 :     case FD_GOSSIP_VALUE_RESTART_HEAVIEST_FORK:
     183           0 :     default:
     184           0 :                                           return 0;
     185           0 :   }
     186           0 :   if( sz<sizeof(uint)+origin_off+32UL ) return 0;
     187             : 
     188           0 :   return fd_memeq( authority->identity_pubkey, data+sizeof(uint)+origin_off, 32UL );
     189           0 : }
     190             : 
     191             : static int
     192             : fd_keyguard_authorize_bundle_crank_txn( fd_keyguard_authority_t const * authority,
     193             :                                         uchar const *                   data,
     194             :                                         ulong                           sz,
     195           0 :                                         int                             sign_type ) {
     196             : 
     197           0 :   static const uchar crank_2_mask[ FD_BUNDLE_CRANK_2_SZ ] = { FD_BUNDLE_CRANK_2_MASK };
     198           0 :   static const uchar crank_2_vals[ FD_BUNDLE_CRANK_2_SZ ] = { FD_BUNDLE_CRANK_2_VALS };
     199           0 :   static const uchar crank_3_mask[ FD_BUNDLE_CRANK_3_SZ ] = { FD_BUNDLE_CRANK_3_MASK };
     200           0 :   static const uchar crank_3_vals[ FD_BUNDLE_CRANK_3_SZ ] = { FD_BUNDLE_CRANK_3_VALS };
     201             : 
     202           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     203             : 
     204           0 :   int matches_mask = 1;
     205           0 :   switch( sz ) {
     206           0 :     case (FD_BUNDLE_CRANK_2_SZ-65UL):
     207           0 :       for( ulong i=0UL; i<FD_BUNDLE_CRANK_2_SZ-65UL; i++ ) {
     208           0 :         if( crank_2_mask[i+65UL] ) matches_mask &= data[i]==crank_2_vals[i+65UL];
     209           0 :       }
     210           0 :       break;
     211           0 :     case (FD_BUNDLE_CRANK_3_SZ-65UL):
     212           0 :       for( ulong i=0UL; i<FD_BUNDLE_CRANK_3_SZ-65UL; i++ ) {
     213           0 :         if( crank_3_mask[i+65UL] ) matches_mask &= data[i]==crank_3_vals[i+65UL];
     214           0 :       }
     215           0 :       if( !fd_memeq( data+FD_BUNDLE_CRANK_TIP_DISTRIBUTION_OFFSET-65UL, authority->tip_distribution_program, 32UL ) ) return 0;
     216           0 :       break;
     217           0 :     default:
     218           0 :       return 0;
     219           0 :   }
     220           0 :   if( !matches_mask ) return 0;
     221             : 
     222           0 :   if( !fd_memeq( data+FD_BUNDLE_CRANK_SIGNER_OFFSET     -65UL, authority->identity_pubkey,     32UL ) ) return 0;
     223           0 :   if( !fd_memeq( data+FD_BUNDLE_CRANK_TIP_PAYMENT_OFFSET-65UL, authority->tip_payment_program, 32UL ) ) return 0;
     224             : 
     225           0 :   return 1;
     226           0 : }
     227             : 
     228             : static int
     229             : fd_keyguard_authorize_ping( fd_keyguard_authority_t const * authority,
     230             :                             uchar const *                   data,
     231             :                             ulong                           sz,
     232           0 :                             int                             sign_type ) {
     233           0 :   (void)authority;
     234           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     235           0 :   if( sz != 32 ) return 0;
     236           0 :   if( 0!=memcmp( data, "SOLANA_PING_PONG", 16 ) ) return 0;
     237           0 :   return 1;
     238           0 : }
     239             : 
     240             : static int
     241             : fd_keyguard_authorize_pong( fd_keyguard_authority_t const * authority,
     242             :                             uchar const *                   data,
     243             :                             ulong                           sz,
     244           0 :                             int                             sign_type ) {
     245           0 :   (void)authority;
     246           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_SHA256_ED25519 ) return 0;
     247           0 :   if( sz != 48 ) return 0;
     248           0 :   if( 0!=memcmp( data, "SOLANA_PING_PONG", 16 ) ) return 0;
     249           0 :   return 1;
     250           0 : }
     251             : 
     252             : static int
     253             : fd_keyguard_authorize_gossip_prune( fd_keyguard_authority_t const * authority,
     254             :                                     uchar const *                   data,
     255             :                                     ulong                           sz,
     256           0 :                                     int                             sign_type ) {
     257           0 :   if( FD_UNLIKELY( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) ) return 0;
     258             :   /* Prune messages always start with the prefix followed by the pubkey. */
     259           0 :   if( sz<66UL ) return 0;
     260           0 :   if( FD_LOAD( ulong, data )!=18UL ) return 0;
     261           0 :   if( 0!=memcmp( data+8UL, "\xffSOLANA_PRUNE_DATA",     18 ) ) return 0;
     262           0 :   if( 0!=memcmp( authority->identity_pubkey, data+26UL, 32 ) ) return 0;
     263           0 :   return 1;
     264           0 : }
     265             : 
     266             : static int
     267             : fd_keyguard_authorize_repair( fd_keyguard_authority_t const * authority,
     268             :                               uchar const *                   data,
     269             :                               ulong                           sz,
     270           0 :                               int                             sign_type ) {
     271             : 
     272           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     273           0 :   if( sz<80 ) return 0;
     274             : 
     275           0 :   uint          discriminant = fd_uint_load_4( data );
     276           0 :   uchar const * sender       = data+4;
     277             : 
     278           0 :   if( discriminant< 8 ) return 0; /* window_index is min ID */
     279           0 :   if( discriminant>14 ) return 0; /* shred_for_block_id is max ID */
     280             : 
     281           0 :   if( 0!=memcmp( authority->identity_pubkey, sender, 32 ) ) return 0;
     282             : 
     283           0 :   return 1;
     284           0 : }
     285             : 
     286             : static int
     287             : fd_keyguard_authorize_tls_cv( fd_keyguard_authority_t const * authority FD_PARAM_UNUSED,
     288             :                               uchar const *                   data,
     289             :                               ulong                           sz,
     290           0 :                               int                             sign_type ) {
     291           0 :   if( FD_UNLIKELY( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) ) return 0;
     292           0 :   if( FD_UNLIKELY( sz != 130 ) ) return 0;
     293             : 
     294             :   /* validate client prefix against fd_tls */
     295           0 :   return fd_memeq( fd_tls13_cli_sign_prefix, data, sizeof(fd_tls13_cli_sign_prefix) );
     296           0 : }
     297             : 
     298             : static int
     299             : fd_keyguard_authorize_tls_cv_srv( fd_keyguard_authority_t const * authority FD_PARAM_UNUSED,
     300             :                                   uchar const *                   data,
     301             :                                   ulong                           sz,
     302           0 :                                   int                             sign_type ) {
     303           0 :   if( FD_UNLIKELY( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) ) return 0;
     304           0 :   if( FD_UNLIKELY( sz != 130 ) ) return 0;
     305             : 
     306             :   /* validate server prefix against fd_tls */
     307           0 :   return fd_memeq( fd_tls13_srv_sign_prefix, data, sizeof(fd_tls13_srv_sign_prefix) );
     308           0 : }
     309             : 
     310             : static int
     311             : fd_keyguard_authorize_ag_vote( fd_keyguard_authority_t const * authority FD_PARAM_UNUSED,
     312             :                                uchar const *                   data      FD_PARAM_UNUSED,
     313             :                                ulong                           sz        FD_PARAM_UNUSED,
     314           6 :                                int                             sign_type ) {
     315           6 :   return sign_type==FD_KEYGUARD_SIGN_TYPE_BLS;
     316           6 : }
     317             : 
     318             : int
     319             : fd_keyguard_payload_authorize( fd_keyguard_authority_t const * authority,
     320             :                                uchar const *                   data,
     321             :                                ulong                           sz,
     322             :                                int                             role,
     323          30 :                                int                             sign_type ) {
     324             : 
     325          30 :   if( sz > FD_KEYGUARD_SIGN_REQ_MTU ) {
     326           0 :     FD_LOG_WARNING(( "oversz signing request (role=%d sz=%lu)", role, sz ));
     327           0 :     return 0;
     328           0 :   }
     329             : 
     330             :   /* Identify payload type */
     331             : 
     332          30 :   ulong payload_mask = fd_keyguard_payload_match( data, sz, sign_type );
     333          30 :   int   match_cnt    = fd_ulong_popcnt( payload_mask );
     334          30 :   if( FD_UNLIKELY( payload_mask==0UL ) ) {
     335          15 :     FD_LOG_WARNING(( "unrecognized payload type (role=%#x)", (uint)role ));
     336          15 :   }
     337             : 
     338          30 :   int is_ambiguous = match_cnt != 1;
     339             : 
     340             :   /* We know that gossip, repair request/response message are
     341             :      ambiguous, so allow them to collide here. */
     342          30 :   int is_gossip_repair =
     343          30 :     0==( payload_mask &
     344          30 :         (~( FD_KEYGUARD_PAYLOAD_GOSSIP |
     345          30 :             FD_KEYGUARD_PAYLOAD_REPAIR ) ) );
     346             :   /* Also allow ambiguities between shred and gossip ping messages
     347             :      until shred sign type is fixed... */
     348          30 :   int is_shred_ping =
     349          30 :     0==( payload_mask &
     350          30 :         (~( FD_KEYGUARD_PAYLOAD_SHRED |
     351          30 :             FD_KEYGUARD_PAYLOAD_PING  ) ) );
     352             : 
     353          30 :   if( FD_UNLIKELY( is_ambiguous && !is_gossip_repair && !is_shred_ping ) ) {
     354           0 :     FD_LOG_WARNING(( "ambiguous payload type (role=%#x mask=%#lx)", (uint)role, payload_mask ));
     355           0 :   }
     356             : 
     357             :   /* Authorize each role */
     358             : 
     359          30 :   switch( role ) {
     360             : 
     361           6 :   case FD_KEYGUARD_ROLE_TXSEND: {
     362           6 :     int txn_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_TXN )) &&
     363           6 :                  fd_keyguard_authorize_vote_txn( authority, data, sz, sign_type );
     364           6 :     int tls_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_TLS_CV )) &&
     365           6 :                  fd_keyguard_authorize_tls_cv( authority, data, sz, sign_type );
     366           6 :     if( FD_UNLIKELY( !txn_ok && !tls_ok ) ) {
     367           6 :       FD_LOG_WARNING(( "unauthorized payload type for send (mask=%#lx)", payload_mask ));
     368           6 :       return 0;
     369           6 :     }
     370           0 :     return 1;
     371           6 :   }
     372             : 
     373           3 :   case FD_KEYGUARD_ROLE_GOSSIP: {
     374           3 :     int ping_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PING )) &&
     375           3 :                     fd_keyguard_authorize_ping( authority, data, sz, sign_type );
     376           3 :     int pong_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PONG )) &&
     377           3 :                     fd_keyguard_authorize_pong( authority, data, sz, sign_type );
     378           3 :     int prune_ok  = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PRUNE )) &&
     379           3 :                     fd_keyguard_authorize_gossip_prune( authority, data, sz, sign_type );
     380           3 :     int gossip_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_GOSSIP )) &&
     381           3 :                     fd_keyguard_authorize_gossip( authority, data, sz, sign_type );
     382           3 :     if( FD_UNLIKELY( !ping_ok && !pong_ok && !prune_ok && !gossip_ok ) ) {
     383           3 :       FD_LOG_WARNING(( "unauthorized payload type for gossip (mask=%#lx)", payload_mask ));
     384           3 :       return 0;
     385           3 :     }
     386           0 :     return 1;
     387           3 :   }
     388             : 
     389           0 :   case FD_KEYGUARD_ROLE_REPAIR: {
     390           0 :     int pong_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PONG )) &&
     391           0 :                     fd_keyguard_authorize_pong( authority, data, sz, sign_type );
     392           0 :     int repair_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_REPAIR )) &&
     393           0 :                     fd_keyguard_authorize_repair( authority, data, sz, sign_type );
     394           0 :     if( FD_UNLIKELY( !pong_ok && !repair_ok ) ) {
     395           0 :       FD_LOG_WARNING(( "unauthorized payload type for repair (mask=%#lx)", payload_mask ));
     396           0 :       return 0;
     397           0 :     }
     398           0 :     return 1;
     399           0 :   }
     400             : 
     401           0 :   case FD_KEYGUARD_ROLE_LEADER:
     402           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_SHRED ) ) {
     403           0 :       FD_LOG_WARNING(( "unauthorized payload type for leader (mask=%#lx)", payload_mask ));
     404           0 :       return 0;
     405           0 :     }
     406             :     /* no further restrictions on shred */
     407           0 :     return 1;
     408             : 
     409           0 :   case FD_KEYGUARD_ROLE_BUNDLE:
     410           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_BUNDLE ) ) {
     411           0 :       FD_LOG_WARNING(( "unauthorized payload type for bundle (mask=%#lx)", payload_mask ));
     412           0 :       return 0;
     413           0 :     }
     414             :     /* no further restrictions on bundle */
     415           0 :     return 1;
     416             : 
     417           0 :   case FD_KEYGUARD_ROLE_EVENT:
     418           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_EVENT ) ) {
     419           0 :       FD_LOG_WARNING(( "unauthorized payload type for event (mask=%#lx)", payload_mask ));
     420           0 :       return 0;
     421           0 :     }
     422             :     /* no further restrictions on event */
     423           0 :     return 1;
     424             : 
     425           0 :   case FD_KEYGUARD_ROLE_BUNDLE_CRANK:
     426           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_TXN ) ) {
     427           0 :       FD_LOG_WARNING(( "unauthorized payload type for crank bundle (mask=%#lx)", payload_mask ));
     428           0 :       return 0;
     429           0 :     }
     430           0 :     return fd_keyguard_authorize_bundle_crank_txn( authority, data, sz, sign_type );
     431             : 
     432           0 :   case FD_KEYGUARD_ROLE_RSERVE: {
     433           0 :     int rserve_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PING )) &&
     434           0 :                     fd_keyguard_authorize_ping( authority, data, sz, sign_type );
     435           0 :     if( FD_UNLIKELY( !rserve_ok ) ) {
     436           0 :       FD_LOG_WARNING(( "unauthorized payload type for rserve (mask=%#lx)", payload_mask ));
     437           0 :       return 0;
     438           0 :     }
     439           0 :     return 1;
     440           0 :   }
     441             : 
     442          21 :   case FD_KEYGUARD_ROLE_VOTOR: {
     443          21 :     int tls_ok  = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_TLS_CV )) &&
     444          21 :                   ( fd_keyguard_authorize_tls_cv    ( authority, data, sz, sign_type ) ||
     445           0 :                     fd_keyguard_authorize_tls_cv_srv( authority, data, sz, sign_type ) );
     446          21 :     int vote_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_AG_VOTE )) &&
     447          21 :                   fd_keyguard_authorize_ag_vote( authority, data, sz, sign_type );
     448          21 :     if( FD_UNLIKELY( !tls_ok && !vote_ok ) ) {
     449          15 :       FD_LOG_WARNING(( "unauthorized payload type for votor (mask=%#lx)", payload_mask ));
     450          15 :       return 0;
     451          15 :     }
     452           6 :     return 1;
     453          21 :   }
     454             : 
     455           0 :   default:
     456           0 :     FD_LOG_WARNING(( "unsupported role=%#x", (uint)role ));
     457           0 :     return 0;
     458          30 :   }
     459          30 : }

Generated by: LCOV version 1.14