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

          Line data    Source code
       1             : #ifndef HEADER_fd_src_discof_failover_fd_failover_proto_h
       2             : #define HEADER_fd_src_discof_failover_fd_failover_proto_h
       3             : 
       4             : /* Failover protocol messages and pure session transitions */
       5             : 
       6             : #include "../../util/fd_util_base.h"
       7             : #include "../../ballet/sha512/fd_sha512.h"
       8             : #include "../../disco/keyguard/fd_keyguard.h"
       9             : 
      10             : /* Protocol version */
      11          66 : #define FD_FAILOVER_VERSION (1U)
      12             : 
      13             : /* The default port for a handoff. */
      14         342 : #define FD_FAILOVER_DEFAULT_PORT ((ushort)8010)
      15             : 
      16             : /* Message types */
      17          24 : #define FD_FAILOVER_MSG_HELLO            (0U)
      18         162 : #define FD_FAILOVER_MSG_HANDOFF_REQUEST  (1U)
      19         114 : #define FD_FAILOVER_MSG_DEMOTED          (2U)
      20          48 : #define FD_FAILOVER_MSG_PROMOTE_ACK      (3U)
      21          27 : #define FD_FAILOVER_MSG_PROMOTE_REJECTED (4U)
      22         102 : #define FD_FAILOVER_MSG_HANDOFF_RESULT   (5U)
      23           9 : #define FD_FAILOVER_MSG_KEEPALIVE        (6U)
      24             : #define FD_FAILOVER_MSG_CNT              (7U)
      25             : 
      26             : /* Sentinel for a slot field with no value */
      27        1863 : #define FD_FAILOVER_SLOT_NULL (ULONG_MAX)
      28             : 
      29             : /* Consensus payload formats */
      30         240 : #define FD_FAILOVER_MODE_ALPENGLOW (1U)
      31             : 
      32             : /* Session states for authenticated TCP sessions. */
      33         444 : #define FD_FAILOVER_SESSION_LISTENING (0UL) /* Accept candidates until one authenticates. */
      34           3 : #define FD_FAILOVER_SESSION_DIALING   (1UL) /* Wait for outbound TCP to connect. */
      35          33 : #define FD_FAILOVER_SESSION_HELLO     (2UL) /* Complete TLS and exchange HELLO. */
      36         708 : #define FD_FAILOVER_SESSION_PAIRED    (3UL) /* Exchange messages with the authenticated peer. */
      37          24 : #define FD_FAILOVER_SESSION_BACKOFF   (4UL) /* Wait before the next dial attempt. */
      38             : #define FD_FAILOVER_SESSION_CNT       (5UL)
      39             : 
      40             : /* HELLO pairing outcomes */
      41          27 : #define FD_FAILOVER_HELLO_OK             (0)
      42           0 : #define FD_FAILOVER_HELLO_ERR_VERSION    (1)
      43          12 : #define FD_FAILOVER_HELLO_ERR_STAKED     (2)
      44           3 : #define FD_FAILOVER_HELLO_ERR_SELF       (3)
      45           3 : #define FD_FAILOVER_HELLO_ERR_BOTH_HOLD  (4)
      46           0 : #define FD_FAILOVER_HELLO_ERR_HOLDS      (5)
      47           0 : #define FD_FAILOVER_HELLO_ERR_BOOT_ID    (6)
      48          18 : #define FD_FAILOVER_HELLO_ERR_MODE       (7)
      49           0 : #define FD_FAILOVER_HELLO_ERR_PROOF      (8)
      50             : 
      51             : /* Upper bound on the vote history payload in alpenglow mode,
      52             :    FD_VOTOR_HIST_SER_MAX is 5274 bytes. */
      53           0 : #define FD_FAILOVER_ALPENGLOW_STATE_MAX (6144UL)
      54           0 : #define FD_FAILOVER_STATE_MAX           (FD_FAILOVER_ALPENGLOW_STATE_MAX)
      55             : 
      56             : /* Wire protocol message bodies. Little endian, packed, fixed layout. */
      57             : struct __attribute__((packed)) fd_failover_hello {
      58             :   ushort version;             /* FD_FAILOVER_VERSION */
      59             :   uchar  staked_pubkey[ 32 ]; /* the identity this pair hands off */
      60             :   uchar  holds;               /* 1 when this host runs staked_pubkey at pairing, else 0 */
      61             :   uchar  mode;                /* FD_FAILOVER_MODE_* consensus */
      62             :   ulong  boot_id;             /* random nonzero value per boot to distinguish restarts */
      63             :   uchar  commit[ 20 ];        /* FD commit hash */
      64             : };
      65             : typedef struct fd_failover_hello fd_failover_hello_t;
      66             : FD_STATIC_ASSERT( sizeof(fd_failover_hello_t)==64UL, wire_layout );
      67             : 
      68             : /* Pre-TLS admission */
      69          24 : #define FD_FAILOVER_ADMISSION_MAGIC  (0x314d44414c494146UL)
      70           6 : #define FD_FAILOVER_ADMISSION_MAX    (2048UL)
      71             : #define FD_FAILOVER_CLIENT_HELLO_MAX (1024UL)
      72             : 
      73             : struct __attribute__((packed)) fd_failover_admission_start {
      74             :   ulong               magic;
      75             :   fd_failover_hello_t hello;
      76             :   uchar               nonce[ 32 ];
      77             :   ushort              client_hello_sz;
      78             : };
      79             : typedef struct fd_failover_admission_start fd_failover_admission_start_t;
      80             : FD_STATIC_ASSERT( sizeof(fd_failover_admission_start_t)==106UL, admission_start_layout );
      81             : 
      82             : struct __attribute__((packed)) fd_failover_admission_challenge {
      83             :   ulong               magic;
      84             :   fd_failover_hello_t hello;
      85             :   uchar               nonce[ 32 ];
      86             : };
      87             : typedef struct fd_failover_admission_challenge fd_failover_admission_challenge_t;
      88             : FD_STATIC_ASSERT( sizeof(fd_failover_admission_challenge_t)==104UL, admission_challenge_layout );
      89             : 
      90             : struct __attribute__((packed)) fd_failover_admission_response {
      91             :   ushort server_flight_sz;
      92             :   uchar  proof[ 64 ];
      93             : };
      94             : typedef struct fd_failover_admission_response fd_failover_admission_response_t;
      95             : FD_STATIC_ASSERT( sizeof(fd_failover_admission_response_t)==66UL, admission_response_layout );
      96             : 
      97           6 : #define FD_FAILOVER_SERVER_FLIGHT_MAX (FD_FAILOVER_ADMISSION_MAX-sizeof(fd_failover_admission_response_t))
      98             : 
      99             : struct __attribute__((packed)) fd_failover_demoted {
     100             :   ulong  handoff_id;     /* the handoff id from the HANDOFF_REQUEST */
     101             :   ulong  target_boot_id; /* peer boot_id the handoff is for */
     102             :   ulong  last_vote_slot; /* tip of the final history */
     103             :   uchar  mode;           /* FD_FAILOVER_MODE_* encoding */
     104             :   ushort state_len;      /* size of the final history that follows this struct */
     105             : };
     106             : typedef struct fd_failover_demoted fd_failover_demoted_t;
     107             : FD_STATIC_ASSERT( sizeof(fd_failover_demoted_t)==27UL, wire_layout );
     108             : 
     109             : #define FD_FAILOVER_DEMOTED_PAYLOAD_MAX (sizeof(fd_failover_demoted_t)+FD_FAILOVER_STATE_MAX)
     110             : 
     111             : struct __attribute__((packed)) fd_failover_promote_ack {
     112             :   ulong handoff_id;
     113             : };
     114             : typedef struct fd_failover_promote_ack fd_failover_promote_ack_t;
     115             : FD_STATIC_ASSERT( sizeof(fd_failover_promote_ack_t)==8UL, wire_layout );
     116             : 
     117             : struct __attribute__((packed)) fd_failover_promote_rejected {
     118             :   ulong handoff_id;
     119             :   uchar reason; /* FD_FAILOVER_REJECT_* */
     120             : };
     121             : typedef struct fd_failover_promote_rejected fd_failover_promote_rejected_t;
     122             : FD_STATIC_ASSERT( sizeof(fd_failover_promote_rejected_t)==9UL, wire_layout );
     123             : 
     124             : struct __attribute__((packed)) fd_failover_handoff_request {
     125             :   ulong handoff_id;
     126             :   ulong target_boot_id;
     127             :   ulong replay_slot; /* replay slot of the machine asking for the identity, FD_FAILOVER_SLOT_NULL before replay starts */
     128             : };
     129             : typedef struct fd_failover_handoff_request fd_failover_handoff_request_t;
     130             : FD_STATIC_ASSERT( sizeof(fd_failover_handoff_request_t)==24UL, wire_layout );
     131             : 
     132             : /* Ends the exchange, result is an admin control result. */
     133             : struct __attribute__((packed)) fd_failover_handoff_result {
     134             :   ulong handoff_id;
     135             :   ulong result;
     136             : };
     137             : typedef struct fd_failover_handoff_result fd_failover_handoff_result_t;
     138             : FD_STATIC_ASSERT( sizeof(fd_failover_handoff_result_t)==16UL, wire_layout );
     139             : 
     140             : /* PROMOTE_REJECTED reasons */
     141          15 : #define FD_FAILOVER_REJECT_NONE              (0U)
     142           0 : #define FD_FAILOVER_REJECT_BUSY              (1U)
     143           0 : #define FD_FAILOVER_REJECT_HOLDS_IDENTITY    (2U)
     144          12 : #define FD_FAILOVER_REJECT_REPLAY_BEHIND     (3U)
     145           0 : #define FD_FAILOVER_REJECT_ADOPTION_MISMATCH (4U)
     146           6 : #define FD_FAILOVER_REJECT_ADOPTION_FAILED   (5U)
     147           0 : #define FD_FAILOVER_REJECT_SWITCH_FAILED     (6U)
     148          12 : #define FD_FAILOVER_REJECT_CNT               (7U)
     149             : 
     150             : FD_PROTOTYPES_BEGIN
     151             : 
     152             : /* Checks a peer's HELLO against ours and returns FD_FAILOVER_HELLO_OK or
     153             :    the first fatal error.  The checks are symmetric on both nodes. */
     154             : int
     155             : fd_failover_hello_check( fd_failover_hello_t const * self,
     156             :                          fd_failover_hello_t const * peer );
     157             : 
     158             : /* Admission hash covers exact packed wire bytes and the prepared TLS
     159             :    record.  response_hash binds the listener proof to the client proof
     160             :    and the server's prepared TLS flight, including its ephemeral key. */
     161             : void
     162             : fd_failover_admission_hash( fd_failover_admission_start_t const *     start,
     163             :                             uchar const *                             client_hello,
     164             :                             fd_failover_admission_challenge_t const * challenge,
     165             :                             uchar                                     out[ 32 ] );
     166             : 
     167             : void
     168             : fd_failover_response_hash( uchar const   transcript[ 32 ],
     169             :                            uchar const   client_proof[ 64 ],
     170             :                            uchar const * server_flight,
     171             :                            ushort        server_flight_sz,
     172             :                            uchar         out[ 32 ] );
     173             : 
     174             : void
     175             : fd_failover_proof_msg( uchar       out[ FD_KEYGUARD_FAILOVER_PROOF_SZ ],
     176             :                        int         server,
     177             :                        uchar const transcript[ 32 ] );
     178             : 
     179             : /* Validate a handoff request or response. */
     180             : int
     181             : fd_failover_handoff_request_decode( fd_failover_handoff_request_t * out,
     182             :                                     uchar const *                   payload,
     183             :                                     ulong                           payload_sz );
     184             : 
     185             : int
     186             : fd_failover_handoff_result_decode( fd_failover_handoff_result_t * out,
     187             :                                    uchar const *                  payload,
     188             :                                    ulong                          payload_sz );
     189             : 
     190             : /* Writes a DEMOTED payload. */
     191             : ulong
     192             : fd_failover_demoted_encode( uchar *       out,
     193             :                             ulong         handoff_id,
     194             :                             ulong         target_boot_id,
     195             :                             ulong         last_vote_slot,
     196             :                             uchar const * state,
     197             :                             ulong         state_sz );
     198             : 
     199             : /* Validates a DEMOTED header. */
     200             : int
     201             : fd_failover_demoted_decode( fd_failover_demoted_t * out,
     202             :                             uchar const *           payload,
     203             :                             ulong                   payload_sz );
     204             : 
     205             : /* Write a PROMOTE_ACK or PROMOTE_REJECTED payload. */
     206             : ulong
     207             : fd_failover_promote_ack_encode( uchar * out,
     208             :                                 ulong   handoff_id );
     209             : 
     210             : ulong
     211             : fd_failover_promote_rejected_encode( uchar * out,
     212             :                                      ulong   handoff_id,
     213             :                                      uchar   reason );
     214             : 
     215             : /* Validate a PROMOTE_ACK or PROMOTE_REJECTED payload. */
     216             : int
     217             : fd_failover_promote_ack_decode( fd_failover_promote_ack_t * out,
     218             :                                 uchar const *               payload,
     219             :                                 ulong                       payload_sz );
     220             : 
     221             : int
     222             : fd_failover_promote_rejected_decode( fd_failover_promote_rejected_t * out,
     223             :                                      uchar const *                    payload,
     224             :                                      ulong                            payload_sz );
     225             : 
     226             : FD_PROTOTYPES_END
     227             : 
     228             : #endif /* HEADER_fd_src_discof_failover_fd_failover_proto_h */

Generated by: LCOV version 1.14