LCOV - code coverage report
Current view: top level - disco/keyguard - fd_keyguard_authorize.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 36 252 14.3 %
Date: 2026-07-04 05:35:33 Functions: 2 9 22.2 %

          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 ) 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           0 :   (void)authority;
     197             : 
     198           0 :   static const uchar disc1[ 8 ] = { FD_BUNDLE_CRANK_DISC_INIT_TIP_DISTR };
     199           0 :   static const uchar disc2[ 8 ] = { FD_BUNDLE_CRANK_DISC_CHANGE_TIP_RCV };
     200           0 :   static const uchar disc3[ 8 ] = { FD_BUNDLE_CRANK_DISC_CHANGE_BLK_BLD };
     201             : 
     202           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     203             : 
     204             :   /* We know that this check is not tight enough to prevent signing of
     205             :      transactions with virtually arbitrary effect.  Currently, we take this
     206             :      trade-off to avoid complex transaction parsing logic in keyguard. */
     207             : 
     208           0 :   switch( sz ) {
     209           0 :     case (FD_BUNDLE_CRANK_2_SZ-65UL):
     210           0 :       return fd_memeq( data+FD_BUNDLE_CRANK_2_IX1_DISC_OFF-65UL, disc2, 8UL ) &&
     211           0 :              fd_memeq( data+FD_BUNDLE_CRANK_2_IX2_DISC_OFF-65UL, disc3, 8UL );
     212           0 :     case (FD_BUNDLE_CRANK_3_SZ-65UL):
     213           0 :       return fd_memeq( data+FD_BUNDLE_CRANK_3_IX1_DISC_OFF-65UL, disc1, 8UL ) &&
     214           0 :              fd_memeq( data+FD_BUNDLE_CRANK_3_IX2_DISC_OFF-65UL, disc2, 8UL ) &&
     215           0 :              fd_memeq( data+FD_BUNDLE_CRANK_3_IX3_DISC_OFF-65UL, disc3, 8UL );
     216           0 :     default:
     217           0 :       return 0;
     218           0 :   }
     219           0 : }
     220             : 
     221             : static int
     222             : fd_keyguard_authorize_ping( fd_keyguard_authority_t const * authority,
     223             :                             uchar const *                   data,
     224             :                             ulong                           sz,
     225           0 :                             int                             sign_type ) {
     226           0 :   (void)authority;
     227           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     228           0 :   if( sz != 32 ) return 0;
     229           0 :   if( 0!=memcmp( data, "SOLANA_PING_PONG", 16 ) ) return 0;
     230           0 :   return 1;
     231           0 : }
     232             : 
     233             : static int
     234             : fd_keyguard_authorize_pong( fd_keyguard_authority_t const * authority,
     235             :                             uchar const *                   data,
     236             :                             ulong                           sz,
     237           0 :                             int                             sign_type ) {
     238           0 :   (void)authority;
     239           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_SHA256_ED25519 ) return 0;
     240           0 :   if( sz != 48 ) return 0;
     241           0 :   if( 0!=memcmp( data, "SOLANA_PING_PONG", 16 ) ) return 0;
     242           0 :   return 1;
     243           0 : }
     244             : 
     245             : static int
     246             : fd_keyguard_authorize_gossip_prune( fd_keyguard_authority_t const * authority,
     247             :                                     uchar const *                   data,
     248             :                                     ulong                           sz,
     249           0 :                                     int                             sign_type ) {
     250           0 :   if( FD_UNLIKELY( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) ) return 0;
     251             :   /* Prune messages always start with the prefix followed by the pubkey. */
     252           0 :   if( sz<66UL ) return 0;
     253           0 :   if( FD_LOAD( ulong, data )!=18UL ) return 0;
     254           0 :   if( 0!=memcmp( data+8UL, "\xffSOLANA_PRUNE_DATA",     18 ) ) return 0;
     255           0 :   if( 0!=memcmp( authority->identity_pubkey, data+26UL, 32 ) ) return 0;
     256           0 :   return 1;
     257           0 : }
     258             : 
     259             : static int
     260             : fd_keyguard_authorize_repair( fd_keyguard_authority_t const * authority,
     261             :                               uchar const *                   data,
     262             :                               ulong                           sz,
     263           0 :                               int                             sign_type ) {
     264             : 
     265           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     266           0 :   if( sz<80 ) return 0;
     267             : 
     268           0 :   uint          discriminant = fd_uint_load_4( data );
     269           0 :   uchar const * sender       = data+4;
     270             : 
     271           0 :   if( discriminant< 8 ) return 0; /* window_index is min ID */
     272           0 :   if( discriminant>11 ) return 0; /* ancestor_hashes is max ID */
     273             : 
     274           0 :   if( 0!=memcmp( authority->identity_pubkey, sender, 32 ) ) return 0;
     275             : 
     276           0 :   return 1;
     277           0 : }
     278             : 
     279             : static int
     280             : fd_keyguard_authorize_tls_cv( fd_keyguard_authority_t const * authority FD_PARAM_UNUSED,
     281             :                               uchar const *                   data,
     282             :                               ulong                           sz,
     283           0 :                               int                             sign_type ) {
     284           0 :   if( FD_UNLIKELY( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) ) return 0;
     285           0 :   if( FD_UNLIKELY( sz != 130 ) ) return 0;
     286             : 
     287             :   /* validate client prefix against fd_tls */
     288           0 :   return fd_memeq( fd_tls13_cli_sign_prefix, data, sizeof(fd_tls13_cli_sign_prefix) );
     289           0 : }
     290             : 
     291             : int
     292             : fd_keyguard_payload_authorize( fd_keyguard_authority_t const * authority,
     293             :                                uchar const *                   data,
     294             :                                ulong                           sz,
     295             :                                int                             role,
     296           3 :                                int                             sign_type ) {
     297             : 
     298           3 :   if( sz > FD_KEYGUARD_SIGN_REQ_MTU ) {
     299           0 :     FD_LOG_WARNING(( "oversz signing request (role=%d sz=%lu)", role, sz ));
     300           0 :     return 0;
     301           0 :   }
     302             : 
     303             :   /* Identify payload type */
     304             : 
     305           3 :   ulong payload_mask = fd_keyguard_payload_match( data, sz, sign_type );
     306           3 :   int   match_cnt    = fd_ulong_popcnt( payload_mask );
     307           3 :   if( FD_UNLIKELY( payload_mask==0UL ) ) {
     308           0 :     FD_LOG_WARNING(( "unrecognized payload type (role=%#x)", (uint)role ));
     309           0 :   }
     310             : 
     311           3 :   int is_ambiguous = match_cnt != 1;
     312             : 
     313             :   /* We know that gossip, repair request/response message are
     314             :      ambiguous, so allow them to collide here. */
     315           3 :   int is_gossip_repair =
     316           3 :     0==( payload_mask &
     317           3 :         (~( FD_KEYGUARD_PAYLOAD_GOSSIP |
     318           3 :             FD_KEYGUARD_PAYLOAD_REPAIR ) ) );
     319             :   /* Also allow ambiguities between shred and gossip ping messages
     320             :      until shred sign type is fixed... */
     321           3 :   int is_shred_ping =
     322           3 :     0==( payload_mask &
     323           3 :         (~( FD_KEYGUARD_PAYLOAD_SHRED |
     324           3 :             FD_KEYGUARD_PAYLOAD_PING  ) ) );
     325             : 
     326           3 :   if( FD_UNLIKELY( is_ambiguous && !is_gossip_repair && !is_shred_ping ) ) {
     327           0 :     FD_LOG_WARNING(( "ambiguous payload type (role=%#x mask=%#lx)", (uint)role, payload_mask ));
     328           0 :   }
     329             : 
     330             :   /* Authorize each role */
     331             : 
     332           3 :   switch( role ) {
     333             : 
     334           3 :   case FD_KEYGUARD_ROLE_TXSEND: {
     335           3 :     int txn_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_TXN )) &&
     336           3 :                  fd_keyguard_authorize_vote_txn( authority, data, sz, sign_type );
     337           3 :     int tls_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_TLS_CV )) &&
     338           3 :                  fd_keyguard_authorize_tls_cv( authority, data, sz, sign_type );
     339           3 :     if( FD_UNLIKELY( !txn_ok && !tls_ok ) ) {
     340           3 :       FD_LOG_WARNING(( "unauthorized payload type for send (mask=%#lx)", payload_mask ));
     341           3 :       return 0;
     342           3 :     }
     343           0 :     return 1;
     344           3 :   }
     345             : 
     346           0 :   case FD_KEYGUARD_ROLE_GOSSIP: {
     347           0 :     int ping_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PING )) &&
     348           0 :                     fd_keyguard_authorize_ping( authority, data, sz, sign_type );
     349           0 :     int pong_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PONG )) &&
     350           0 :                     fd_keyguard_authorize_pong( authority, data, sz, sign_type );
     351           0 :     int prune_ok  = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PRUNE )) &&
     352           0 :                     fd_keyguard_authorize_gossip_prune( authority, data, sz, sign_type );
     353           0 :     int gossip_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_GOSSIP )) &&
     354           0 :                     fd_keyguard_authorize_gossip( authority, data, sz, sign_type );
     355           0 :     if( FD_UNLIKELY( !ping_ok && !pong_ok && !prune_ok && !gossip_ok ) ) {
     356           0 :       FD_LOG_WARNING(( "unauthorized payload type for gossip (mask=%#lx)", payload_mask ));
     357           0 :       return 0;
     358           0 :     }
     359           0 :     return 1;
     360           0 :   }
     361             : 
     362           0 :   case FD_KEYGUARD_ROLE_REPAIR: {
     363           0 :     int ping_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PING )) &&
     364           0 :                     fd_keyguard_authorize_ping( authority, data, sz, sign_type );
     365           0 :     int pong_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PONG )) &&
     366           0 :                     fd_keyguard_authorize_pong( authority, data, sz, sign_type );
     367           0 :     int repair_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_REPAIR )) &&
     368           0 :                     fd_keyguard_authorize_repair( authority, data, sz, sign_type );
     369           0 :     if( FD_UNLIKELY( !ping_ok && !pong_ok && !repair_ok ) ) {
     370           0 :       FD_LOG_WARNING(( "unauthorized payload type for repair (mask=%#lx)", payload_mask ));
     371           0 :       return 0;
     372           0 :     }
     373           0 :     return 1;
     374           0 :   }
     375             : 
     376           0 :   case FD_KEYGUARD_ROLE_LEADER:
     377           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_SHRED ) ) {
     378           0 :       FD_LOG_WARNING(( "unauthorized payload type for leader (mask=%#lx)", payload_mask ));
     379           0 :       return 0;
     380           0 :     }
     381             :     /* no further restrictions on shred */
     382           0 :     return 1;
     383             : 
     384           0 :   case FD_KEYGUARD_ROLE_BUNDLE:
     385           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_BUNDLE ) ) {
     386           0 :       FD_LOG_WARNING(( "unauthorized payload type for bundle (mask=%#lx)", payload_mask ));
     387           0 :       return 0;
     388           0 :     }
     389             :     /* no further restrictions on bundle */
     390           0 :     return 1;
     391             : 
     392           0 :   case FD_KEYGUARD_ROLE_EVENT:
     393           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_EVENT ) ) {
     394           0 :       FD_LOG_WARNING(( "unauthorized payload type for event (mask=%#lx)", payload_mask ));
     395           0 :       return 0;
     396           0 :     }
     397             :     /* no further restrictions on event */
     398           0 :     return 1;
     399             : 
     400           0 :   case FD_KEYGUARD_ROLE_BUNDLE_CRANK:
     401           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_TXN ) ) {
     402           0 :       FD_LOG_WARNING(( "unauthorized payload type for crank bundle (mask=%#lx)", payload_mask ));
     403           0 :       return 0;
     404           0 :     }
     405           0 :     return fd_keyguard_authorize_bundle_crank_txn( authority, data, sz, sign_type );
     406             : 
     407           0 :   case FD_KEYGUARD_ROLE_RSERVE: {
     408           0 :     int rserve_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PING )) &&
     409           0 :                     fd_keyguard_authorize_ping( authority, data, sz, sign_type );
     410           0 :     if( FD_UNLIKELY( !rserve_ok ) ) {
     411           0 :       FD_LOG_WARNING(( "unauthorized payload type for rserve (mask=%#lx)", payload_mask ));
     412           0 :       return 0;
     413           0 :     }
     414           0 :     return 1;
     415           0 :   }
     416             : 
     417           0 :   default:
     418           0 :     FD_LOG_WARNING(( "unsupported role=%#x", (uint)role ));
     419           0 :     return 0;
     420           3 :   }
     421           3 : }

Generated by: LCOV version 1.14