Line data Source code
1 : #ifndef HEADER_fd_src_disco_keyguard_fd_keyswitch_h 2 : #define HEADER_fd_src_disco_keyguard_fd_keyswitch_h 3 : 4 : #include "../fd_disco_base.h" 5 : 6 : /* A fd_keyswitch_public_t provides APIs for out-of-band switching of 7 : the key of a validator. */ 8 : 9 9 : #define FD_KEYSWITCH_ALIGN (128UL) 10 6 : #define FD_KEYSWITCH_FOOTPRINT (128UL) 11 : 12 3 : #define FD_KEYSWITCH_MAGIC (0xf17eda2c37830000UL) /* firedancer ks ver 0 */ 13 : 14 3 : #define FD_KEYSWITCH_STATE_UNLOCKED (0UL) 15 : #define FD_KEYSWITCH_STATE_LOCKED (1UL) 16 3 : #define FD_KEYSWITCH_STATE_SWITCH_PENDING (2UL) 17 3 : #define FD_KEYSWITCH_STATE_UNHALT_PENDING (3UL) 18 0 : #define FD_KEYSWITCH_STATE_FAILED (4UL) 19 6 : #define FD_KEYSWITCH_STATE_COMPLETED (5UL) 20 : 21 : /* Application-specific param values should be defined below. */ 22 : 23 0 : #define FD_KEYSWITCH_PARAM_AV_ADD (0UL) 24 0 : #define FD_KEYSWITCH_PARAM_AV_CLEAR (1UL) 25 : 26 : struct __attribute__((aligned(FD_KEYSWITCH_ALIGN))) fd_keyswitch_private { 27 : ulong magic; /* ==FD_KEYSWITCH_MAGIC */ 28 : ulong state; 29 : ulong result; 30 : ulong param; 31 : uchar bytes[ 64UL ]; 32 : /* Padding to FD_KEYSWITCH_ALIGN here */ 33 : }; 34 : 35 : typedef struct fd_keyswitch_private fd_keyswitch_t; 36 : 37 : FD_PROTOTYPES_BEGIN 38 : 39 : /* fd_keyswitch_{align,footprint} return the required alignment and 40 : footprint of a memory region suitable for use as a keyswitch. 41 : fd_keyswitch_align returns FD_KEYSWITCH_ALIGN. */ 42 : 43 : FD_FN_CONST ulong 44 : fd_keyswitch_align( void ); 45 : 46 : FD_FN_CONST ulong 47 : fd_keyswitch_footprint( void ); 48 : 49 : /* fd_keyswitch_new formats an unused memory region for use as a 50 : keyswitch. Assumes shmem is a non-NULL pointer to this region in the 51 : local address space with the required footprint and alignment. The 52 : keyswitch will be initialized to have the given state (should be in 53 : [0,UINT_MAX]). Returns shmem (and the memory region it points to 54 : will be formatted as a keyswitch, caller is not joined) and NULL on 55 : failure (logs details). Reasons for failure include an obviously bad 56 : shmem region. */ 57 : 58 : void * 59 : fd_keyswitch_new( void * shmem, 60 : ulong state ); 61 : 62 : /* fd_keyswitch_join joins the caller to the keyswitch. shks points to 63 : the first byte of the memory region backing the keyswitch in the 64 : caller's address space. Returns a pointer in the local address space 65 : to the keyswitch on success (this should not be assumed to be just a 66 : cast of shkc) or NULL on failure (logs details). Reasons for failure 67 : include the shkc is obviously not a local pointer to a memory region 68 : holding a keyswitch. Every successful join should have a matching 69 : leave. The lifetime of the join is until the matching leave or 70 : caller's thread group is terminated. */ 71 : 72 : fd_keyswitch_t * 73 : fd_keyswitch_join( void * shks ); 74 : 75 : /* fd_keyswitch_leave leaves a current local join. Returns a pointer to 76 : the underlying shared memory region on success (this should not be 77 : assumed to be just a cast of ks) and NULL on failure (logs details). 78 : Reasons for failure include ks is NULL. */ 79 : 80 : void * 81 : fd_keyswitch_leave( fd_keyswitch_t const * ks ); 82 : 83 : /* fd_keyswitch_delete unformats a memory region used as a keyswitch. 84 : Assumes nobody is joined to the region. Returns a pointer to the 85 : underlying shared memory region or NULL if used obviously in error 86 : (e.g. shks obviously does not point to a keyswitch ... logs details). 87 : The ownership of the memory region is transferred to the caller on 88 : success. */ 89 : 90 : void * 91 : fd_keyswitch_delete( void * shkc ); 92 : 93 : /* fd_keyswitch_state_query observes the current signal posted to the 94 : keyswitch. Assumes ks is a current local join. This is a compiler 95 : fence. Returns the current state on the ks at some point in time 96 : between when this was called and this returned. */ 97 : 98 : static inline ulong 99 24 : fd_keyswitch_state_query( fd_keyswitch_t const * ks ) { 100 24 : FD_COMPILER_MFENCE(); 101 24 : ulong s = FD_VOLATILE_CONST( ks->state ); 102 24 : FD_COMPILER_MFENCE(); 103 24 : return s; 104 24 : } 105 : 106 : /* fd_keyswitch_state_query observes the current param posted to the 107 : keyswitch. Assumes ks is a current local join. This is a compiler 108 : fence. Returns the current param on the ks at some point in time 109 : between when this was called and this returned. */ 110 : 111 : static inline ulong 112 0 : fd_keyswitch_param_query( fd_keyswitch_t const * ks ) { 113 0 : FD_COMPILER_MFENCE(); 114 0 : ulong s = FD_VOLATILE_CONST( ks->param ); 115 0 : FD_COMPILER_MFENCE(); 116 0 : return s; 117 0 : } 118 : 119 : /* fd_keyswitch_state atomically attempts to transition the ks from 120 : state before to state after. Assumes ks is a current local join and 121 : the caller is currently allowed to do a transition from before to 122 : after. Returns 0 if the transition succeeded, or 1 if it failed*/ 123 : 124 : static inline void 125 : fd_keyswitch_state( fd_keyswitch_t * ks, 126 12 : ulong s ) { 127 12 : FD_COMPILER_MFENCE(); 128 12 : FD_VOLATILE( ks->state ) = s; 129 12 : FD_COMPILER_MFENCE(); 130 12 : } 131 : 132 : FD_PROTOTYPES_END 133 : 134 : #endif /* HEADER_fd_src_disco_keyguard_fd_keyswitch_h */