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