LCOV - code coverage report
Current view: top level - discof/failover - fd_failover_proto.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 99 99 100.0 %
Date: 2026-11-12 04:25:03 Functions: 12 12 100.0 %

          Line data    Source code
       1             : #include "fd_failover_proto.h"
       2             : 
       3             : #include "../../ballet/ed25519/fd_ed25519.h"
       4             : #include "../../ballet/sha256/fd_sha256.h"
       5             : #include "../../disco/keyguard/fd_keyguard.h"
       6             : 
       7             : FD_STATIC_ASSERT( sizeof(FD_KEYGUARD_FAILOVER_CLIENT_DOMAIN)-1UL==FD_KEYGUARD_FAILOVER_DOMAIN_SZ, client_proof_domain );
       8             : FD_STATIC_ASSERT( sizeof(FD_KEYGUARD_FAILOVER_SERVER_DOMAIN)-1UL==FD_KEYGUARD_FAILOVER_DOMAIN_SZ, server_proof_domain );
       9             : 
      10             : int
      11             : fd_failover_hello_check( fd_failover_hello_t const * self,
      12          54 :                          fd_failover_hello_t const * peer ) {
      13          54 :   if( FD_UNLIKELY( self->version!=peer->version ) )                                return FD_FAILOVER_HELLO_ERR_VERSION;
      14          54 :   if( FD_UNLIKELY( self->holds>1 || peer->holds>1 ) )                              return FD_FAILOVER_HELLO_ERR_HOLDS;
      15          54 :   if( FD_UNLIKELY( self->mode!=FD_FAILOVER_MODE_ALPENGLOW ||
      16          54 :                    self->mode!=peer->mode ) )                                      return FD_FAILOVER_HELLO_ERR_MODE;
      17          36 :   if( FD_UNLIKELY( !self->boot_id || !peer->boot_id ) )                            return FD_FAILOVER_HELLO_ERR_BOOT_ID;
      18          36 :   if( FD_UNLIKELY( !fd_memeq( self->staked_pubkey, peer->staked_pubkey, 32UL ) ) ) return FD_FAILOVER_HELLO_ERR_STAKED;
      19          27 :   if( FD_UNLIKELY( self->boot_id==peer->boot_id ) )                                return FD_FAILOVER_HELLO_ERR_SELF;
      20          24 :   if( FD_UNLIKELY( self->holds && peer->holds ) )                                  return FD_FAILOVER_HELLO_ERR_BOTH_HOLD;
      21          21 :   return FD_FAILOVER_HELLO_OK;
      22          24 : }
      23             : 
      24             : void
      25             : fd_failover_admission_hash( fd_failover_admission_start_t const *     start,
      26             :                             uchar const *                            client_hello,
      27             :                             fd_failover_admission_challenge_t const * challenge,
      28           6 :                             uchar                                    out[ 32 ] ) {
      29           6 :   fd_sha256_t sha[1];
      30           6 :   fd_sha256_init( sha );
      31           6 :   fd_sha256_append( sha, start,        sizeof(*start)       );
      32           6 :   fd_sha256_append( sha, client_hello, start->client_hello_sz );
      33           6 :   fd_sha256_append( sha, challenge,    sizeof(*challenge)   );
      34           6 :   fd_sha256_fini( sha, out );
      35           6 : }
      36             : 
      37             : void
      38             : fd_failover_response_hash( uchar const   transcript[ 32 ],
      39             :                            uchar const   client_proof[ 64 ],
      40             :                            uchar const * server_flight,
      41             :                            ushort        server_flight_sz,
      42           6 :                            uchar         out[ 32 ] ) {
      43           6 :   fd_sha256_t sha[1];
      44           6 :   fd_sha256_init( sha );
      45           6 :   fd_sha256_append( sha, transcript,        32UL                     );
      46           6 :   fd_sha256_append( sha, client_proof,      64UL                     );
      47           6 :   fd_sha256_append( sha, &server_flight_sz, sizeof(server_flight_sz) );
      48           6 :   fd_sha256_append( sha, server_flight,     server_flight_sz         );
      49           6 :   fd_sha256_fini( sha, out );
      50           6 : }
      51             : 
      52             : void
      53             : fd_failover_proof_msg( uchar       out[ FD_KEYGUARD_FAILOVER_PROOF_SZ ],
      54             :                        int         server,
      55          12 :                        uchar const transcript[ 32 ] ) {
      56          12 :   fd_memcpy( out, server ? FD_KEYGUARD_FAILOVER_SERVER_DOMAIN : FD_KEYGUARD_FAILOVER_CLIENT_DOMAIN,
      57          12 :              FD_KEYGUARD_FAILOVER_DOMAIN_SZ );
      58          12 :   fd_memcpy( out+FD_KEYGUARD_FAILOVER_DOMAIN_SZ, transcript, 32UL );
      59          12 : }
      60             : 
      61             : int
      62             : fd_failover_handoff_request_decode( fd_failover_handoff_request_t * out,
      63             :                                     uchar const *                   payload,
      64          90 :                                     ulong                           payload_sz ) {
      65          90 :   if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_handoff_request_t) ) ) return 0;
      66          87 :   fd_failover_handoff_request_t request;
      67          87 :   fd_memcpy( &request, payload, sizeof(request) );
      68          87 :   if( FD_UNLIKELY( !request.handoff_id || !request.target_boot_id ) ) return 0;
      69          84 :   *out = request;
      70          84 :   return 1;
      71          87 : }
      72             : 
      73             : int
      74             : fd_failover_handoff_result_decode( fd_failover_handoff_result_t * out,
      75             :                                    uchar const *                  payload,
      76          24 :                                    ulong                          payload_sz ) {
      77          24 :   if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_handoff_result_t) ) ) return 0;
      78          21 :   fd_failover_handoff_result_t result;
      79          21 :   fd_memcpy( &result, payload, sizeof(result) );
      80          21 :   if( FD_UNLIKELY( !result.handoff_id ) ) return 0;
      81          18 :   *out = result;
      82          18 :   return 1;
      83          21 : }
      84             : 
      85             : ulong
      86             : fd_failover_demoted_encode( uchar *       out,
      87             :                             ulong         handoff_id,
      88             :                             ulong         target_boot_id,
      89             :                             ulong         last_vote_slot,
      90             :                             uchar const * state,
      91          42 :                             ulong         state_sz ) {
      92          42 :   if( FD_UNLIKELY( !state_sz || state_sz>FD_FAILOVER_ALPENGLOW_STATE_MAX ) ) return 0UL;
      93             : 
      94          42 :   fd_failover_demoted_t demoted = {
      95          42 :     .handoff_id     = handoff_id,
      96          42 :     .target_boot_id = target_boot_id,
      97          42 :     .last_vote_slot = last_vote_slot,
      98          42 :     .mode           = (uchar)FD_FAILOVER_MODE_ALPENGLOW,
      99          42 :     .state_len      = (ushort)state_sz,
     100          42 :   };
     101          42 :   fd_memcpy( out, &demoted, sizeof(demoted) );
     102          42 :   fd_memcpy( out+sizeof(demoted), state, state_sz );
     103          42 :   return sizeof(demoted)+state_sz;
     104          42 : }
     105             : 
     106             : int
     107             : fd_failover_demoted_decode( fd_failover_demoted_t * out,
     108             :                             uchar const *           payload,
     109          39 :                             ulong                   payload_sz ) {
     110          39 :   if( FD_UNLIKELY( payload_sz<sizeof(fd_failover_demoted_t) ||
     111          39 :                    payload_sz>FD_FAILOVER_DEMOTED_PAYLOAD_MAX ) ) return 0;
     112             : 
     113          39 :   fd_failover_demoted_t demoted;
     114          39 :   fd_memcpy( &demoted, payload, sizeof(demoted) );
     115             : 
     116          39 :   ulong state_sz = payload_sz-sizeof(fd_failover_demoted_t);
     117          39 :   if( FD_UNLIKELY( (ulong)demoted.state_len!=state_sz ||
     118          39 :                    !state_sz || state_sz>FD_FAILOVER_ALPENGLOW_STATE_MAX ||
     119          39 :                    demoted.mode!=(uchar)FD_FAILOVER_MODE_ALPENGLOW ||
     120          39 :                    demoted.last_vote_slot==FD_FAILOVER_SLOT_NULL ) ) return 0;
     121             : 
     122          30 :   *out = demoted;
     123          30 :   return 1;
     124          39 : }
     125             : 
     126             : ulong
     127             : fd_failover_promote_ack_encode( uchar * out,
     128          15 :                                 ulong   handoff_id ) {
     129          15 :   fd_failover_promote_ack_t ack = { .handoff_id=handoff_id };
     130          15 :   fd_memcpy( out, &ack, sizeof(ack) );
     131          15 :   return sizeof(ack);
     132          15 : }
     133             : 
     134             : ulong
     135             : fd_failover_promote_rejected_encode( uchar * out,
     136             :                                      ulong   handoff_id,
     137           6 :                                      uchar   reason ) {
     138           6 :   if( FD_UNLIKELY( reason==(uchar)FD_FAILOVER_REJECT_NONE || reason>=(uchar)FD_FAILOVER_REJECT_CNT ) ) return 0UL;
     139           6 :   fd_failover_promote_rejected_t rej = { .handoff_id=handoff_id, .reason=reason };
     140           6 :   fd_memcpy( out, &rej, sizeof(rej) );
     141           6 :   return sizeof(rej);
     142           6 : }
     143             : 
     144             : int
     145             : fd_failover_promote_ack_decode( fd_failover_promote_ack_t * out,
     146             :                                 uchar const *               payload,
     147          12 :                                 ulong                       payload_sz ) {
     148          12 :   if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_promote_ack_t) ) ) return 0;
     149          12 :   fd_memcpy( out, payload, sizeof(fd_failover_promote_ack_t) );
     150          12 :   return 1;
     151          12 : }
     152             : 
     153             : int
     154             : fd_failover_promote_rejected_decode( fd_failover_promote_rejected_t * out,
     155             :                                      uchar const *                    payload,
     156           3 :                                      ulong                            payload_sz ) {
     157           3 :   if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_promote_rejected_t) ) ) return 0;
     158           3 :   fd_failover_promote_rejected_t rej;
     159           3 :   fd_memcpy( &rej, payload, sizeof(rej) );
     160           3 :   if( FD_UNLIKELY( rej.reason==(uchar)FD_FAILOVER_REJECT_NONE || rej.reason>=(uchar)FD_FAILOVER_REJECT_CNT ) ) return 0;
     161           3 :   *out = rej;
     162           3 :   return 1;
     163           3 : }

Generated by: LCOV version 1.14