Line data Source code
1 : #define _GNU_SOURCE
2 :
3 : #include "../../disco/topo/fd_topo.h"
4 : #include "generated/fd_eqvoc_tile_seccomp.h"
5 :
6 : #include "../../choreo/fd_choreo.h"
7 :
8 : #include "../../disco/fd_disco.h"
9 : #include "../../disco/keyguard/fd_keyload.h"
10 : #include "../../disco/shred/fd_stake_ci.h"
11 :
12 : #define SCRATCH_MAX ( 4UL /*KiB*/ << 10 )
13 : #define SCRATCH_DEPTH ( 4UL ) /* 4 scratch frames */
14 :
15 :
16 : struct fd_eqvoc_tile_ctx {
17 : fd_pubkey_t identity_key[1];
18 :
19 : fd_stake_ci_t * stake_ci;
20 : fd_shred_dest_weighted_t * new_dest_ptr;
21 : ulong new_dest_cnt;
22 :
23 : ulong contact_in_idx;
24 : fd_wksp_t * contact_in_mem;
25 : ulong contact_in_chunk0;
26 : ulong contact_in_wmark;
27 :
28 : fd_gossip_duplicate_shred_t duplicate_shred;
29 : uchar duplicate_shred_chunk[FD_EQVOC_PROOF_CHUNK_MAX];
30 :
31 : ulong gossip_in_idx;
32 : fd_wksp_t * gossip_in_mem;
33 : ulong gossip_in_chunk0;
34 : ulong gossip_in_wmark;
35 :
36 : fd_shred_t shred;
37 :
38 : ulong shred_net_in_idx;
39 : fd_wksp_t * shred_net_in_mem;
40 : ulong shred_net_in_chunk0;
41 : ulong shred_net_in_wmark;
42 :
43 : ulong seed;
44 : fd_eqvoc_t * eqvoc;
45 : };
46 : typedef struct fd_eqvoc_tile_ctx fd_eqvoc_tile_ctx_t;
47 :
48 : FD_FN_CONST static inline ulong
49 0 : scratch_align( void ) {
50 0 : return 128UL;
51 0 : }
52 :
53 : FD_FN_PURE static inline ulong
54 0 : loose_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
55 0 : return 0UL;
56 0 : }
57 :
58 : FD_FN_PURE static inline ulong
59 0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
60 : /* clang-format off */
61 0 : ulong l = FD_LAYOUT_INIT;
62 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_eqvoc_tile_ctx_t), sizeof(fd_eqvoc_tile_ctx_t) );
63 0 : l = FD_LAYOUT_APPEND( l, fd_stake_ci_align(), fd_stake_ci_footprint() );
64 0 : l = FD_LAYOUT_APPEND( l, fd_eqvoc_align(), fd_eqvoc_footprint( 1 << 10, 1 << 10 ) );
65 0 : return FD_LAYOUT_FINI( l, scratch_align() );
66 : /* clang-format on */
67 0 : }
68 :
69 : static inline void
70 : handle_new_cluster_contact_info( fd_eqvoc_tile_ctx_t * ctx,
71 : uchar const * buf,
72 0 : ulong buf_sz ) {
73 0 : ulong const * header = (ulong const *)fd_type_pun_const( buf );
74 :
75 0 : ulong dest_cnt = buf_sz / sizeof(fd_shred_dest_wire_t);
76 :
77 0 : fd_shred_dest_wire_t const * in_dests = fd_type_pun_const( header );
78 0 : fd_shred_dest_weighted_t * dests = fd_stake_ci_dest_add_init( ctx->stake_ci );
79 :
80 0 : ctx->new_dest_ptr = dests;
81 0 : ctx->new_dest_cnt = dest_cnt;
82 :
83 0 : for( ulong i=0UL; i<dest_cnt; i++ ) {
84 0 : memcpy( dests[i].pubkey.uc, in_dests[i].pubkey, 32UL );
85 0 : dests[i].ip4 = in_dests[i].ip4_addr;
86 0 : dests[i].port = in_dests[i].udp_port;
87 0 : }
88 0 : }
89 :
90 : static inline void
91 0 : finalize_new_cluster_contact_info( fd_eqvoc_tile_ctx_t * ctx ) {
92 0 : fd_stake_ci_dest_add_fini( ctx->stake_ci, ctx->new_dest_cnt );
93 0 : }
94 :
95 : static void
96 : during_frag( fd_eqvoc_tile_ctx_t * ctx,
97 : ulong in_idx,
98 : ulong seq FD_PARAM_UNUSED,
99 : ulong sig,
100 : ulong chunk,
101 : ulong sz,
102 0 : ulong ctl FD_PARAM_UNUSED ) {
103 :
104 0 : if( FD_UNLIKELY( in_idx == ctx->contact_in_idx ) ) {
105 0 : if( FD_UNLIKELY( chunk < ctx->contact_in_chunk0 || chunk > ctx->contact_in_wmark ) ) {
106 0 : FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]",
107 0 : chunk,
108 0 : sz,
109 0 : ctx->contact_in_chunk0,
110 0 : ctx->contact_in_wmark ));
111 0 : }
112 :
113 0 : uchar const * dcache_entry = fd_chunk_to_laddr_const( ctx->contact_in_mem, chunk );
114 0 : handle_new_cluster_contact_info( ctx, dcache_entry, sz );
115 0 : } else if( FD_UNLIKELY( in_idx == ctx->gossip_in_idx ) ) {
116 0 : uchar * packet = fd_chunk_to_laddr( ctx->gossip_in_mem, chunk );
117 0 : memcpy( &ctx->duplicate_shred, packet, sizeof(fd_gossip_duplicate_shred_t) );
118 0 : FD_TEST( ctx->duplicate_shred.chunk_len <= sizeof(ctx->duplicate_shred_chunk) );
119 0 : memcpy( ctx->duplicate_shred_chunk, packet + sizeof(fd_gossip_duplicate_shred_t), ctx->duplicate_shred.chunk_len );
120 0 : ctx->duplicate_shred.chunk = ctx->duplicate_shred_chunk;
121 0 : } else if ( FD_UNLIKELY( in_idx == ctx->shred_net_in_idx ) ) {
122 0 : if( FD_UNLIKELY( chunk < ctx->shred_net_in_chunk0 || chunk > ctx->shred_net_in_wmark ) ) {
123 0 : FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]",
124 0 : chunk,
125 0 : sz,
126 0 : ctx->shred_net_in_chunk0,
127 0 : ctx->shred_net_in_wmark ));
128 0 : }
129 :
130 0 : uchar const * packet = fd_chunk_to_laddr_const( ctx->shred_net_in_mem, chunk );
131 0 : memcpy( &ctx->shred, packet + fd_disco_netmux_sig_hdr_sz( sig ), sizeof(fd_shred_t) );
132 0 : }
133 0 : }
134 :
135 : static void
136 : after_frag( fd_eqvoc_tile_ctx_t * ctx,
137 : ulong in_idx,
138 : ulong seq,
139 : ulong sig,
140 : ulong sz,
141 : ulong tsorig,
142 : ulong tspub,
143 0 : fd_stem_context_t * stem ) {
144 0 : (void)seq;
145 0 : (void)sig;
146 0 : (void)sz;
147 0 : (void)tsorig;
148 0 : (void)tspub;
149 0 : (void)stem;
150 :
151 0 : if( FD_UNLIKELY( in_idx == ctx->contact_in_idx ) ) {
152 0 : finalize_new_cluster_contact_info( ctx );
153 0 : return;
154 0 : } else if ( FD_UNLIKELY( in_idx == ctx->gossip_in_idx ) ) {
155 : // fd_gossip_duplicate_shred_t * chunk = &ctx->duplicate_shred;
156 : // ulong slot = ctx->duplicate_shred.slot;
157 : // fd_pubkey_t const * from = &chunk->from;
158 :
159 : // fd_eqvoc_proof_t * proof = fd_eqvoc_proof_query( ctx->eqvoc, slot, from );
160 : // if( FD_UNLIKELY( !proof ) ) {
161 :
162 : // if( FD_UNLIKELY( chunk->chunk_index == chunk->num_chunks - 1 ) ) {
163 : // FD_LOG_WARNING(( "received last proof chunk first. unable to determine chunk len. ignoring." ));
164 : // return;
165 : // }
166 :
167 : // proof = fd_eqvoc_proof_insert( ctx->eqvoc, slot, from );
168 : // fd_pubkey_t const * leader = fd_epoch_leaders_get( ctx->eqvoc->leaders, slot );
169 : // fd_eqvoc_proof_init( proof, leader, chunk->wallclock, chunk->num_chunks, chunk->chunk_len, ctx->eqvoc->bmtree_mem );
170 : // }
171 : // fd_eqvoc_proof_chunk_insert( proof, chunk );
172 : // if( FD_UNLIKELY( fd_eqvoc_proof_complete( proof ) ) ) {
173 : // int rc = fd_eqvoc_proof_verify( proof );
174 : // FD_LOG_NOTICE(( "proof verify %d", rc ));
175 : // fd_eqvoc_proof_remove( ctx->eqvoc, &proof->key );
176 : // }
177 :
178 0 : return;
179 0 : }
180 : // } else if ( FD_UNLIKELY( in_idx == ctx->shred_net_in_idx ) ) {
181 : // FD_LOG_NOTICE(( "got shred %lu %u", ctx->shred.slot, ctx->shred.idx ));
182 : // } else {
183 : // FD_LOG_WARNING(( "unexpected in_idx %lu", in_idx ));
184 : // }
185 :
186 0 : }
187 :
188 : static void
189 : privileged_init( fd_topo_t * topo,
190 0 : fd_topo_tile_t * tile ) {
191 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
192 :
193 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
194 0 : fd_eqvoc_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l,
195 0 : alignof( fd_eqvoc_tile_ctx_t ),
196 0 : sizeof( fd_eqvoc_tile_ctx_t ) );
197 :
198 0 : if( FD_UNLIKELY( !strcmp( tile->eqvoc.identity_key_path, "" ) ) )
199 0 : FD_LOG_ERR(( "identity_key_path not set" ));
200 :
201 0 : ctx->identity_key[0] = *(fd_pubkey_t const *)
202 0 : fd_type_pun_const( fd_keyload_load( tile->eqvoc.identity_key_path,
203 0 : /* pubkey only: */ 1 ) );
204 :
205 0 : FD_TEST( fd_rng_secure( &ctx->seed, sizeof(ulong) ) );
206 0 : }
207 :
208 : static void
209 : unprivileged_init( fd_topo_t * topo,
210 0 : fd_topo_tile_t * tile ) {
211 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
212 :
213 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
214 0 : fd_eqvoc_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_eqvoc_tile_ctx_t ), sizeof( fd_eqvoc_tile_ctx_t ) );
215 0 : void * stake_ci_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_ci_align(), fd_stake_ci_footprint() );
216 0 : void * eqvoc_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_eqvoc_align(), fd_eqvoc_footprint( 1 << 10, 1 << 10 ) );
217 0 : ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
218 0 : if( FD_UNLIKELY( scratch_top != (ulong)scratch + scratch_footprint( tile ) ) ) {
219 0 : FD_LOG_ERR(( "scratch overflow %lu %lu %lu",
220 0 : scratch_top - (ulong)scratch - scratch_footprint( tile ),
221 0 : scratch_top,
222 0 : (ulong)scratch + scratch_footprint( tile )) );
223 0 : }
224 :
225 0 : ctx->stake_ci = fd_stake_ci_join( fd_stake_ci_new( stake_ci_mem, ctx->identity_key ) );
226 0 : ctx->eqvoc = fd_eqvoc_join( fd_eqvoc_new( eqvoc_mem, 1 << 10, 1 << 10, 0 ) );
227 :
228 0 : ctx->contact_in_idx = fd_topo_find_tile_in_link( topo, tile, "gossip_send", 0 );
229 0 : FD_TEST( ctx->contact_in_idx != ULONG_MAX );
230 0 : fd_topo_link_t * contact_in_link = &topo->links[tile->in_link_id[ctx->contact_in_idx]];
231 0 : ctx->contact_in_mem = topo->workspaces[topo->objs[contact_in_link->dcache_obj_id].wksp_id].wksp;
232 0 : ctx->contact_in_chunk0 = fd_dcache_compact_chunk0( ctx->contact_in_mem, contact_in_link->dcache );
233 0 : ctx->contact_in_wmark = fd_dcache_compact_wmark( ctx->contact_in_mem, contact_in_link->dcache, contact_in_link->mtu );
234 :
235 0 : ctx->gossip_in_idx = fd_topo_find_tile_in_link( topo, tile, "gossip_eqvoc", 0 );
236 0 : FD_TEST( ctx->gossip_in_idx != ULONG_MAX );
237 0 : fd_topo_link_t * gossip_in_link = &topo->links[tile->in_link_id[ctx->gossip_in_idx]];
238 0 : ctx->gossip_in_mem = topo->workspaces[topo->objs[gossip_in_link->dcache_obj_id].wksp_id].wksp;
239 0 : ctx->gossip_in_chunk0 = fd_dcache_compact_chunk0( ctx->gossip_in_mem, gossip_in_link->dcache );
240 0 : ctx->gossip_in_wmark = fd_dcache_compact_wmark( ctx->gossip_in_mem, gossip_in_link->dcache, gossip_in_link->mtu );
241 :
242 0 : ctx->shred_net_in_idx = fd_topo_find_tile_in_link( topo, tile, "shred_net", 0 );
243 0 : FD_TEST( ctx->shred_net_in_idx != ULONG_MAX );
244 0 : fd_topo_link_t * shred_net_in_link = &topo->links[tile->in_link_id[ctx->shred_net_in_idx]];
245 0 : ctx->shred_net_in_mem = topo->workspaces[topo->objs[shred_net_in_link->dcache_obj_id].wksp_id].wksp;
246 0 : ctx->shred_net_in_chunk0 = fd_dcache_compact_chunk0( ctx->shred_net_in_mem, shred_net_in_link->dcache );
247 0 : ctx->shred_net_in_wmark = fd_dcache_compact_wmark( ctx->shred_net_in_mem, shred_net_in_link->dcache, shred_net_in_link->mtu );
248 0 : }
249 :
250 : static ulong
251 : populate_allowed_seccomp( fd_topo_t const * topo,
252 : fd_topo_tile_t const * tile,
253 : ulong out_cnt,
254 0 : struct sock_filter * out ) {
255 0 : (void)topo;
256 0 : (void)tile;
257 :
258 0 : populate_sock_filter_policy_fd_eqvoc_tile( out_cnt, out, (uint)fd_log_private_logfile_fd() );
259 0 : return sock_filter_policy_fd_eqvoc_tile_instr_cnt;
260 0 : }
261 :
262 : static ulong
263 : populate_allowed_fds( fd_topo_t const * topo,
264 : fd_topo_tile_t const * tile,
265 : ulong out_fds_cnt,
266 0 : int * out_fds ) {
267 0 : (void)topo;
268 0 : (void)tile;
269 :
270 0 : if( FD_UNLIKELY( out_fds_cnt<2UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
271 :
272 0 : ulong out_cnt = 0UL;
273 0 : out_fds[ out_cnt++ ] = 2; /* stderr */
274 0 : if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
275 0 : out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
276 0 : return out_cnt;
277 0 : }
278 :
279 0 : #define STEM_BURST (1UL)
280 :
281 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_eqvoc_tile_ctx_t
282 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_eqvoc_tile_ctx_t)
283 :
284 0 : #define STEM_CALLBACK_DURING_FRAG during_frag
285 0 : #define STEM_CALLBACK_AFTER_FRAG after_frag
286 :
287 : #include "../../disco/stem/fd_stem.c"
288 :
289 : fd_topo_run_tile_t fd_tile_eqvoc = {
290 : .name = "eqvoc",
291 : .loose_footprint = loose_footprint,
292 : .populate_allowed_seccomp = populate_allowed_seccomp,
293 : .populate_allowed_fds = populate_allowed_fds,
294 : .scratch_align = scratch_align,
295 : .scratch_footprint = scratch_footprint,
296 : .privileged_init = privileged_init,
297 : .unprivileged_init = unprivileged_init,
298 : .run = stem_run,
299 : };
|