Line data Source code
1 : #ifndef HEADER_fd_src_disco_bundle_fd_bundle_tile_private_h 2 : #define HEADER_fd_src_disco_bundle_fd_bundle_tile_private_h 3 : 4 : #include "fd_bundle_auth.h" 5 : #include "fd_keepalive.h" 6 : #include "../stem/fd_stem.h" 7 : #include "../keyguard/fd_keyswitch.h" 8 : #include "../keyguard/fd_keyguard_client.h" 9 : #include "../../waltz/grpc/fd_grpc_client.h" 10 : #include "../../waltz/resolv/fd_netdb.h" 11 : #include "../../waltz/fd_rtt_est.h" 12 : #include "../../util/alloc/fd_alloc.h" 13 : #include "../../util/hist/fd_histf.h" 14 : 15 : #if FD_HAS_OPENSSL 16 : #include <openssl/ssl.h> /* SSL_CTX */ 17 : #endif 18 : 19 : struct fd_bundle_out_ctx { 20 : ulong idx; 21 : fd_wksp_t * mem; 22 : ulong chunk0; 23 : ulong wmark; 24 : ulong chunk; 25 : }; 26 : 27 : typedef struct fd_bundle_out_ctx fd_bundle_out_ctx_t; 28 : 29 : /* fd_bundle_metrics_t contains private metric counters. These get 30 : published to fd_metrics periodically. */ 31 : 32 : struct fd_bundle_metrics { 33 : ulong txn_received_cnt; 34 : ulong bundle_received_cnt; 35 : ulong packet_received_cnt; 36 : ulong proto_received_bytes; 37 : ulong shredstream_heartbeat_cnt; 38 : ulong ping_ack_cnt; 39 : 40 : ulong decode_fail_cnt; 41 : ulong transport_fail_cnt; 42 : ulong missing_builder_info_fail_cnt; 43 : 44 : fd_histf_t msg_rx_delay[1]; 45 : }; 46 : 47 : typedef struct fd_bundle_metrics fd_bundle_metrics_t; 48 : 49 : /* fd_bundle_tile_t is the context object provided to callbacks from 50 : stem, and contains all state needed to progress the tile. */ 51 : 52 : struct fd_bundle_tile { 53 : /* Key switch */ 54 : fd_keyswitch_t * keyswitch; 55 : 56 : /* Key guard */ 57 : fd_keyguard_client_t keyguard_client[1]; 58 : 59 : uint is_ssl : 1; 60 : int keylog_fd; 61 : # if FD_HAS_OPENSSL 62 : /* OpenSSL */ 63 : SSL_CTX * ssl_ctx; 64 : SSL * ssl; 65 : fd_alloc_t * ssl_alloc; 66 : # endif /* FD_HAS_OPENSSL */ 67 : 68 : /* Config */ 69 : char server_fqdn[ 256 ]; /* cstr */ 70 : ulong server_fqdn_len; 71 : char server_sni[ 256 ]; /* cstr */ 72 : ulong server_sni_len; 73 : ushort server_tcp_port; 74 : 75 : /* Resolver */ 76 : fd_netdb_fds_t netdb_fds[1]; 77 : uint server_ip4_addr; /* last DNS lookup result */ 78 : 79 : /* TCP socket */ 80 : int tcp_sock; 81 : int so_rcvbuf; 82 : uint tcp_sock_connected : 1; 83 : uint defer_reset : 1; 84 : long cached_ts; 85 : 86 : /* Keepalive via HTTP/2 PINGs (randomized) */ 87 : long keepalive_interval; 88 : fd_keepalive_t keepalive[1]; 89 : fd_rtt_estimate_t rtt[1]; 90 : 91 : /* gRPC client */ 92 : void * grpc_client_mem; 93 : ulong grpc_buf_max; 94 : fd_grpc_client_t * grpc_client; 95 : fd_grpc_client_metrics_t grpc_metrics[1]; 96 : ulong map_seed; 97 : 98 : /* Bundle authenticator */ 99 : fd_bundle_auther_t auther; 100 : 101 : /* Bundle block builder info */ 102 : uchar builder_pubkey[ 32 ]; 103 : uchar builder_commission; /* in [0,100] (percent) */ 104 : uchar builder_info_avail : 1; /* Block builder info available? (potentially stale) */ 105 : uchar builder_info_wait : 1; /* Request already in-flight? */ 106 : long builder_info_valid_until; 107 : 108 : /* Bundle subscriptions */ 109 : uchar packet_subscription_live : 1; /* Want to subscribe to a stream? */ 110 : uchar packet_subscription_wait : 1; /* Request already in-flight? */ 111 : uchar bundle_subscription_live : 1; 112 : uchar bundle_subscription_wait : 1; 113 : 114 : /* Bundle state */ 115 : ulong bundle_seq; 116 : ulong bundle_txn_cnt; 117 : 118 : /* Error backoff */ 119 : fd_rng_t rng[1]; 120 : uint backoff_iter; 121 : long backoff_until; 122 : long backoff_reset; 123 : 124 : /* Stem publish */ 125 : fd_stem_context_t * stem; 126 : fd_bundle_out_ctx_t verify_out; 127 : fd_bundle_out_ctx_t plugin_out; 128 : 129 : /* App metrics */ 130 : fd_bundle_metrics_t metrics; 131 : 132 : /* Check engine light */ 133 : uchar bundle_status_recent; /* most recently observed 'check engine light' */ 134 : uchar bundle_status_plugin; /* last 'plugin' update written */ 135 : uchar bundle_status_logged; 136 : long last_bundle_status_log_nanos; 137 : }; 138 : 139 : typedef struct fd_bundle_tile fd_bundle_tile_t; 140 : 141 : /* Define 'request_ctx' IDs to identify different types of gRPC calls */ 142 : 143 57 : #define FD_BUNDLE_CLIENT_REQ_Bundle_SubscribePackets 4 144 99 : #define FD_BUNDLE_CLIENT_REQ_Bundle_SubscribeBundles 5 145 30 : #define FD_BUNDLE_CLIENT_REQ_Bundle_GetBlockBuilderFeeInfo 6 146 : 147 : FD_PROTOTYPES_BEGIN 148 : 149 : /* fd_bundle_now is an externally linked function wrapping 150 : fd_log_wallclock. This is backed by a weak symbol, allowing tests to 151 : override the clock source. */ 152 : 153 : long 154 : fd_bundle_now( void ); 155 : 156 : /* fd_bundle_client_grpc_callbacks provides callbacks for grpc_client. */ 157 : 158 : extern fd_grpc_client_callbacks_t fd_bundle_client_grpc_callbacks; 159 : 160 : /* fd_bundle_client_step is an all-in-one routine to drive client logic. 161 : As long as the tile calls this periodically, the client will 162 : reconnect to the bundle server, authenticate, and subscribe to 163 : packets and bundles. */ 164 : 165 : void 166 : fd_bundle_client_step( fd_bundle_tile_t * bundle, 167 : int * charge_busy ); 168 : 169 : /* fd_bundle_client_step_reconnect drives the 'reconnect' state machine. 170 : Once the HTTP/2 conn is established (SETTINGS exchanged), this 171 : function drives the auth logic, requests block builder info, sets up 172 : packet and bundle subscriptions, and PINGs. */ 173 : 174 : int 175 : fd_bundle_client_step_reconnect( fd_bundle_tile_t * ctx, 176 : long now ); 177 : 178 : /* fd_bundle_tile_backoff is called whenever an error occurs. Stalls 179 : forward progress for a randomized amount of time to prevent error 180 : floods. */ 181 : 182 : void 183 : fd_bundle_tile_backoff( fd_bundle_tile_t * ctx, 184 : long now ); 185 : 186 : /* fd_bundle_tile_should_stall returns 1 if forward progress should be 187 : temporarily prevented due to an error. */ 188 : 189 : FD_FN_PURE static inline int 190 : fd_bundle_tile_should_stall( fd_bundle_tile_t const * ctx, 191 54 : long now ) { 192 54 : return now < ctx->backoff_until; 193 54 : } 194 : 195 : /* fd_bundle_tile_housekeeping runs periodically at a low frequency. */ 196 : 197 : void 198 : fd_bundle_tile_housekeeping( fd_bundle_tile_t * ctx ); 199 : 200 : /* fd_bundle_client_grpc_rx_start is the first RX callback of a stream. */ 201 : 202 : void 203 : fd_bundle_client_grpc_rx_start( 204 : void * app_ctx, 205 : ulong request_ctx 206 : ) ; 207 : 208 : /* fd_bundle_client_grpc_rx_msg is called by grpc_client when a gRPC 209 : message arrives (unary or server-streaming response). */ 210 : 211 : void 212 : fd_bundle_client_grpc_rx_msg( 213 : void * app_ctx, /* (fd_bundle_tile_t *) */ 214 : void const * protobuf, 215 : ulong protobuf_sz, 216 : ulong request_ctx /* FD_BUNDLE_CLIENT_REQ_{...} */ 217 : ); 218 : 219 : /* fd_bundle_client_grpc_rx_end is called by grpc_client when a gRPC 220 : server-streaming response finishes. */ 221 : 222 : void 223 : fd_bundle_client_grpc_rx_end( 224 : void * app_ctx, 225 : ulong request_ctx, 226 : fd_grpc_resp_hdrs_t * resp 227 : ); 228 : 229 : /* fd_bundle_client_grpc_rx_timeout is called by grpc_client when a 230 : gRPC request deadline gets exceeded. */ 231 : 232 : void 233 : fd_bundle_client_grpc_rx_timeout( 234 : void * app_ctx, 235 : ulong request_ctx, /* FD_BUNDLE_CLIENT_REQ_{...} */ 236 : int deadline_kind /* FD_GRPC_DEADLINE_{HEADER|RX_END} */ 237 : ); 238 : 239 : /* fd_bundle_client_status provides a "check engine light". 240 : 241 : Returns 0 if the client has recently failed and is currently backing 242 : off from a reconnect attempt. 243 : 244 : Returns 1 if the client is currently reconnecting. 245 : 246 : Returns 2 if all of the following conditions are met: 247 : - TCP socket is alive 248 : - SSL session is not in an error state 249 : - HTTP/2 connection is established (SETTINGS exchange done) 250 : - gRPC bundle and packet subscriptions are live 251 : - HTTP/2 PING exchange was done recently 252 : 253 : Return codes are compatible with FD_PLUGIN_MSG_BLOCK_ENGINE_UPDATE_STATUS_{...}. */ 254 : 255 : int 256 : fd_bundle_client_status( fd_bundle_tile_t const * ctx ); 257 : 258 : /* fd_bundle_request_ctx_cstr returns the gRPC method name for a 259 : FD_BUNDLE_CLIENT_REQ_* ID. Returns "unknown" the ID is not 260 : recognized. */ 261 : 262 : FD_FN_CONST char const * 263 : fd_bundle_request_ctx_cstr( ulong request_ctx ); 264 : 265 : /* fd_bundle_client_reset frees all connection-related resources. */ 266 : 267 : void 268 : fd_bundle_client_reset( fd_bundle_tile_t * ctx ); 269 : 270 : /* fd_bundle_client_ping_tx enqueues a PING frame for sending. Returns 271 : 1 on success and 0 on failure (occurs when frame_tx buf is full). */ 272 : 273 : void 274 : fd_bundle_client_send_ping( fd_bundle_tile_t * ctx ); 275 : 276 : FD_PROTOTYPES_END 277 : 278 : #endif /* HEADER_fd_src_disco_bundle_fd_bundle_tile_private_h */