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