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 0 : #define FD_KEYSWITCH_ALIGN (128UL) 10 0 : #define FD_KEYSWITCH_FOOTPRINT (32896UL) 11 : 12 0 : #define FD_KEYSWITCH_MAGIC (0xf17eda2c37830000UL) /* firedancer ks ver 0 */ 13 : 14 0 : #define FD_KEYSWITCH_STATE_UNLOCKED (0UL) 15 0 : #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 : /* Application-specific param values should be defined below. */ 22 : 23 : /* Sign tile identity switches. KEYPAIR passes a new keypair in 24 : bytes[0..64), PUBKEY passes a public key in bytes[0..32) and selects 25 : the junk key or the failover identity the sign tile already holds. 26 : CHECK passes a public key in bytes[0..32) and checks whether it can 27 : become the failover identity without changing any keys. */ 28 0 : #define FD_KEYSWITCH_PARAM_IDENTITY_KEYPAIR (0UL) 29 0 : #define FD_KEYSWITCH_PARAM_IDENTITY_PUBKEY (1UL) 30 0 : #define FD_KEYSWITCH_PARAM_IDENTITY_CHECK (2UL) 31 0 : #define FD_KEYSWITCH_PARAM_IDENTITY_PREPARE (3UL) /* preload a failover key without installing it */ 32 : 33 0 : #define FD_KEYSWITCH_PARAM_AV_ADD (0UL) 34 0 : #define FD_KEYSWITCH_PARAM_AV_CLEAR (1UL) 35 : 36 : struct __attribute__((aligned(FD_KEYSWITCH_ALIGN))) fd_keyswitch_private { 37 : ulong magic; /* ==FD_KEYSWITCH_MAGIC */ 38 : ulong state; 39 : ulong result; 40 : ulong param; 41 : uchar bytes[ 32768UL ]; 42 : ulong failover; /* 1 when the failover tile made this switch, 0 for set-identity */ 43 : /* Padding to FD_KEYSWITCH_ALIGN here */ 44 : }; 45 : 46 : typedef struct fd_keyswitch_private fd_keyswitch_t; 47 : 48 : FD_PROTOTYPES_BEGIN 49 : 50 : /* fd_keyswitch_{align,footprint} return the required alignment and 51 : footprint of a memory region suitable for use as a keyswitch. 52 : fd_keyswitch_align returns FD_KEYSWITCH_ALIGN. */ 53 : 54 : FD_FN_CONST ulong 55 : fd_keyswitch_align( void ); 56 : 57 : FD_FN_CONST ulong 58 : fd_keyswitch_footprint( void ); 59 : 60 : /* fd_keyswitch_new formats an unused memory region for use as a 61 : keyswitch. Assumes shmem is a non-NULL pointer to this region in the 62 : local address space with the required footprint and alignment. The 63 : keyswitch will be initialized to have the given state (should be in 64 : [0,UINT_MAX]). Returns shmem (and the memory region it points to 65 : will be formatted as a keyswitch, caller is not joined) and NULL on 66 : failure (logs details). Reasons for failure include an obviously bad 67 : shmem region. */ 68 : 69 : void * 70 : fd_keyswitch_new( void * shmem, 71 : ulong state ); 72 : 73 : /* fd_keyswitch_join joins the caller to the keyswitch. shks points to 74 : the first byte of the memory region backing the keyswitch in the 75 : caller's address space. Returns a pointer in the local address space 76 : to the keyswitch on success (this should not be assumed to be just a 77 : cast of shkc) or NULL on failure (logs details). Reasons for failure 78 : include the shkc is obviously not a local pointer to a memory region 79 : holding a keyswitch. Every successful join should have a matching 80 : leave. The lifetime of the join is until the matching leave or 81 : caller's thread group is terminated. */ 82 : 83 : fd_keyswitch_t * 84 : fd_keyswitch_join( void * shks ); 85 : 86 : /* fd_keyswitch_leave leaves a current local join. Returns a pointer to 87 : the underlying shared memory region on success (this should not be 88 : assumed to be just a cast of ks) and NULL on failure (logs details). 89 : Reasons for failure include ks is NULL. */ 90 : 91 : void * 92 : fd_keyswitch_leave( fd_keyswitch_t const * ks ); 93 : 94 : /* fd_keyswitch_delete unformats a memory region used as a keyswitch. 95 : Assumes nobody is joined to the region. Returns a pointer to the 96 : underlying shared memory region or NULL if used obviously in error 97 : (e.g. shks obviously does not point to a keyswitch ... logs details). 98 : The ownership of the memory region is transferred to the caller on 99 : success. */ 100 : 101 : void * 102 : fd_keyswitch_delete( void * shkc ); 103 : 104 : /* fd_keyswitch_state_query observes the current signal posted to the 105 : keyswitch. Assumes ks is a current local join. This is a compiler 106 : fence. Returns the current state on the ks at some point in time 107 : between when this was called and this returned. */ 108 : 109 : static inline ulong 110 0 : fd_keyswitch_state_query( fd_keyswitch_t const * ks ) { 111 0 : return __atomic_load_n( &ks->state, __ATOMIC_ACQUIRE ); 112 0 : } 113 : 114 : /* fd_keyswitch_state_query observes the current param posted to the 115 : keyswitch. Assumes ks is a current local join. This is a compiler 116 : fence. Returns the current param on the ks at some point in time 117 : between when this was called and this returned. */ 118 : 119 : static inline ulong 120 0 : fd_keyswitch_param_query( fd_keyswitch_t const * ks ) { 121 0 : return __atomic_load_n( &ks->param, __ATOMIC_ACQUIRE ); 122 0 : } 123 : 124 : /* fd_keyswitch_state atomically attempts to transition the ks from 125 : state before to state after. Assumes ks is a current local join and 126 : the caller is currently allowed to do a transition from before to 127 : after. Returns 0 if the transition succeeded, or 1 if it failed*/ 128 : 129 : static inline void 130 : fd_keyswitch_state( fd_keyswitch_t * ks, 131 0 : ulong s ) { 132 0 : __atomic_store_n( &ks->state, s, __ATOMIC_RELEASE ); 133 0 : } 134 : 135 : FD_PROTOTYPES_END 136 : 137 : #endif /* HEADER_fd_src_disco_keyguard_fd_keyswitch_h */