Line data Source code
1 : #include "../../../../disco/topo/fd_topo.h"
2 : #include "../../../../flamenco/types/fd_types_custom.h"
3 : #include "../../../../flamenco/runtime/fd_system_ids_pp.h"
4 :
5 0 : #define BENCHG_TRANSACTION_MODE_SMALL 0
6 0 : #define BENCHG_TRANSACTION_MODE_LARGE 1
7 0 : #define BENCHG_TRANSACTION_MODE_TRANSFER 2
8 :
9 : typedef struct {
10 : fd_rng_t rng[ 1 ];
11 : fd_sha512_t sha[ 1 ];
12 :
13 : ulong sender_idx;
14 : ulong lamport_idx;
15 : int changed_blockhash;
16 :
17 : int has_recent_blockhash;
18 : uchar recent_blockhash[ 32 ];
19 : uchar staged_blockhash[ 32 ];
20 :
21 : int transaction_mode;
22 : float contending_fraction;
23 : float cu_price_spread;
24 :
25 : ulong acct_cnt;
26 : fd_pubkey_t * acct_public_keys;
27 : fd_pubkey_t * acct_private_keys;
28 :
29 : ulong benchg_cnt;
30 : ulong benchg_idx;
31 :
32 : fd_wksp_t * mem;
33 : ulong out_chunk0;
34 : ulong out_wmark;
35 : ulong out_chunk;
36 : } fd_benchg_ctx_t;
37 :
38 : FD_FN_CONST static inline ulong
39 0 : scratch_align( void ) {
40 0 : return alignof( fd_benchg_ctx_t );
41 0 : }
42 :
43 : FD_FN_PURE static inline ulong
44 0 : scratch_footprint( fd_topo_tile_t const * tile ) {
45 0 : (void)tile;
46 0 : ulong l = FD_LAYOUT_INIT;
47 0 : l = FD_LAYOUT_APPEND( l, alignof( fd_benchg_ctx_t ), sizeof( fd_benchg_ctx_t ) );
48 0 : l = FD_LAYOUT_APPEND( l, alignof( fd_pubkey_t ), sizeof( fd_pubkey_t ) * tile->benchg.accounts_cnt );
49 0 : l = FD_LAYOUT_APPEND( l, alignof( fd_pubkey_t ), sizeof( fd_pubkey_t ) * tile->benchg.accounts_cnt );
50 0 : return FD_LAYOUT_FINI( l, scratch_align() );
51 0 : }
52 :
53 : static const uchar HARDCODED_PUBKEY[32] = { 0x0e,0xd2,0x90,0x05,0x83,0xd1,0x7c,0xc4,0x22,0x8c,0x10,0x75,0x84,0x18,0x71,0xa1, \
54 : 0x96,0xbe,0x46,0xc4,0xce,0xcd,0x5d,0xc0,0xae,0x7e,0xa9,0x61,0x4b,0x8a,0xdf,0x41 };
55 :
56 : static const uchar HARDCODED_SIG[64] = { 0xdb,0x89,0x2c,0xaa,0x90,0x1f,0x80,0xcf,0xde,0x32,0x09,0xbf,0xce,0x58,0xda,0x9e, \
57 : 0xd6,0xa1,0x8c,0x0f,0x74,0xfa,0x31,0x09,0x07,0x33,0xab,0x46,0xf9,0xde,0x60,0x3c, \
58 : 0x22,0x20,0xc6,0x7e,0xeb,0x9b,0xce,0x12,0x3a,0xd5,0x34,0xb8,0x1c,0x80,0x49,0x8a, \
59 : 0xb1,0x1e,0xbb,0xed,0xb2,0x24,0xf0,0x19,0x4b,0x85,0x3b,0x55,0x4b,0x41,0xbe,0x0a };
60 :
61 : typedef struct __attribute__((packed)) {
62 : uchar sig_cnt; /* = 1 */
63 : uchar signature[64];
64 : uchar _sig_cnt; /* also 1 */
65 : uchar ro_signed_cnt; /* ??? */
66 : uchar ro_unsigned_cnt; /* ??? */
67 : uchar acct_addr_cnt; /* = ??? */
68 : uchar fee_payer[32];
69 : } single_signer_hdr_t;
70 :
71 : typedef struct __attribute__((packed)) {
72 : uchar sig_cnt; /* = 1 */
73 : uchar signature[64];
74 : uchar _sig_cnt; /* also 1 */
75 : uchar ro_signed_cnt; /* = 0 */
76 : uchar ro_unsigned_cnt; /* = 1 . Compute Budget Program */
77 : uchar acct_addr_cnt; /* = 2 */
78 : uchar fee_payer[32];
79 : uchar compute_budget_program[32]; /* = {COMPUTE_BUDGET_PROG_ID} */
80 : uchar recent_blockhash[32];
81 : uchar instr_cnt; /* = 2 */
82 : /* Start of instruction */
83 : struct __attribute__((packed)) {
84 : uchar prog_id; /* = 1 */
85 : uchar acct_cnt; /* = 0 */
86 : uchar data_sz; /* = 9 */
87 : uchar set_cu_price; /* = 3 */
88 : ulong micro_lamports_per_cu; /* Prefereably less than 10k or so */
89 : } _1;
90 : /* Start of second instruction */
91 : struct __attribute__((packed)) {
92 : uchar prog_id; /* = 1 */
93 : uchar acct_cnt; /* = 0 */
94 : uchar data_sz; /* = 5 */
95 : uchar set_cu_limit; /* = 2 */
96 : uint cus; /* = 300 */
97 : } _2;
98 : } small_noop_t;
99 :
100 : typedef struct __attribute__((packed)) {
101 : uchar sig_cnt; /* = 1 */
102 : uchar signature[64];
103 : uchar _sig_cnt; /* also 1 */
104 : uchar ro_signed_cnt; /* = 0 */
105 : uchar ro_unsigned_cnt; /* = 2 . Compute Budget Program, Ed25519SV */
106 : uchar acct_addr_cnt; /* = 3 */
107 : uchar fee_payer[32];
108 : uchar compute_budget_program[32]; /* = {COMPUTE_BUDGET_PROG_ID} */
109 : uchar ed25519_sv_program[32]; /* = { ED25519_SV } */
110 : uchar recent_blockhash[32];
111 : uchar instr_cnt; /* = 2 */
112 : /* Start of instruction */
113 : struct __attribute__((packed)) {
114 : uchar prog_id; /* = 1 */
115 : uchar acct_cnt; /* = 0 */
116 : uchar data_sz; /* = 9 */
117 : uchar set_cu_price; /* = 3 */
118 : ulong micro_lamports_per_cu; /* Prefereably less than 10k or so */
119 : } _1;
120 : /* Start of second instruction */
121 : struct __attribute__((packed)) {
122 : uchar prog_id; /* = 2 */
123 : uchar acct_cnt; /* = 0 */
124 : uchar data_sz_0; /* = 0xFA */
125 : uchar data_sz_1; /* = 0x07 */
126 : /* Offsets the follow count from here */
127 : uchar signature_cnt; /* = 1 */
128 : uchar _padding; /* ignored, set to 0 */
129 : ushort signature_off; /* = 56 */
130 : ushort signature_ix_idx; /* = 0 */
131 : ushort pubkey_off; /* = 24 */
132 : ushort pubkey_ix_idx; /* = 0 */
133 : ushort data_off; /* = 120 */
134 : ushort data_sz; /* = 1 */
135 : ushort data_ix_idx; /* = 0 */
136 : ulong _padding2; /* Set to anything */
137 : uchar hardcoded_pubkey[32];
138 : uchar hardcoded_sig[64];
139 : uchar message; /* = 0 */
140 : uchar _padding3[897]; /* Set to anything */
141 : } _2;
142 : } large_noop_t;
143 :
144 : typedef struct __attribute__((packed)) {
145 : uchar sig_cnt; /* = 1 */
146 : uchar signature[64];
147 : uchar _sig_cnt; /* also 1 */
148 : uchar ro_signed_cnt; /* = 0 */
149 : uchar ro_unsigned_cnt; /* = 1 . System program */
150 : uchar acct_addr_cnt; /* = 3 */
151 : uchar fee_payer[32];
152 : uchar transfer_dest[32];
153 : uchar system_program[32]; /* = { 0 0 ...} */
154 : uchar recent_blockhash[32];
155 : uchar instr_cnt; /* = 1 */
156 : /* Start of instruction */
157 : struct __attribute__((packed)) {
158 : uchar prog_id; /* = 2 */
159 : uchar acct_cnt; /* = 2 */
160 : uchar from_acct; /* = 0 */
161 : uchar to_acct; /* = 1 */
162 : uchar data_sz; /* = 9 */
163 : uchar transfer; /* = 2 */
164 : ulong lamports; /* variable */
165 : } _1;
166 : } transfer_t;
167 :
168 :
169 : FD_STATIC_ASSERT( sizeof(large_noop_t)==1232UL, txn );
170 :
171 : static inline void
172 : after_credit( fd_benchg_ctx_t * ctx,
173 : fd_stem_context_t * stem,
174 : int * opt_poll_in,
175 0 : int * charge_busy ) {
176 0 : (void)opt_poll_in;
177 :
178 0 : if( FD_UNLIKELY( !ctx->has_recent_blockhash ) ) return;
179 :
180 0 : *charge_busy = 1;
181 :
182 0 : int is_contending = fd_rng_float_c( ctx->rng ) < ctx->contending_fraction;
183 0 : ulong sender_idx = fd_ulong_if( is_contending, 0UL, ctx->sender_idx );
184 :
185 0 : float norm = 4.0f + fd_rng_float_norm( ctx->rng );
186 0 : if( FD_UNLIKELY( norm<0.0f ) ) norm = 0.0f;
187 0 : ulong cu_price_spread = (ulong)(ctx->cu_price_spread * norm);
188 :
189 0 : void * _txn = fd_chunk_to_laddr( ctx->mem, ctx->out_chunk );
190 :
191 0 : ulong transaction_size = 0UL;
192 0 : uchar * recent_blockhash = NULL;
193 :
194 0 : switch( ctx->transaction_mode ) {
195 0 : case BENCHG_TRANSACTION_MODE_SMALL:
196 0 : {
197 0 : small_noop_t * txn = (small_noop_t *)_txn;
198 :
199 0 : txn->sig_cnt = 1;
200 0 : txn->_sig_cnt = 1;
201 0 : txn->ro_signed_cnt = 0;
202 0 : txn->ro_unsigned_cnt = 1;
203 0 : txn->acct_addr_cnt = 2;
204 0 : memcpy( txn->compute_budget_program, (uchar const[32]) { COMPUTE_BUDGET_PROG_ID }, 32UL );
205 0 : txn->instr_cnt = 2;
206 0 : txn->_1.prog_id = 1;
207 0 : txn->_1.acct_cnt = 0;
208 0 : txn->_1.data_sz = 9;
209 0 : txn->_1.set_cu_price = 3;
210 0 : txn->_2.prog_id = 1;
211 0 : txn->_2.acct_cnt = 0;
212 0 : txn->_2.data_sz = 5;
213 0 : txn->_2.set_cu_limit = 2;
214 0 : txn->_2.cus = 300;
215 :
216 : /* Variable */
217 0 : txn->_1.micro_lamports_per_cu = ctx->lamport_idx; /* Unique per transaction so they aren't duplicates */
218 0 : txn->_1.micro_lamports_per_cu += fd_ulong_if( is_contending, 1000000UL, 0UL ); /* +300 lamports */
219 0 : txn->_1.micro_lamports_per_cu += cu_price_spread;
220 :
221 0 : transaction_size = sizeof(small_noop_t);
222 0 : recent_blockhash = txn->recent_blockhash;
223 0 : }
224 0 : break;
225 :
226 0 : case BENCHG_TRANSACTION_MODE_LARGE:
227 0 : {
228 0 : large_noop_t * txn = (large_noop_t *)_txn;
229 :
230 0 : txn->sig_cnt = 1;
231 0 : txn->_sig_cnt = 1;
232 0 : txn->ro_signed_cnt = 0;
233 0 : txn->ro_unsigned_cnt = 2;
234 0 : txn->acct_addr_cnt = 3;
235 0 : memcpy( txn->compute_budget_program, (uchar const[32]) { COMPUTE_BUDGET_PROG_ID }, 32UL );
236 0 : memcpy( txn->ed25519_sv_program, (uchar const[32]) { ED25519_SV_PROG_ID }, 32UL );
237 0 : txn->instr_cnt = 2;
238 :
239 0 : txn->_1.prog_id = 1;
240 0 : txn->_1.acct_cnt = 0;
241 0 : txn->_1.data_sz = 9;
242 0 : txn->_1.set_cu_price = 3;
243 0 : txn->_1.micro_lamports_per_cu = 0UL;
244 0 : txn->_1.micro_lamports_per_cu += cu_price_spread;
245 0 : txn->_1.micro_lamports_per_cu += fd_ulong_if( is_contending, 43000UL, 0UL ); /* +4 lamports/csu */
246 :
247 :
248 0 : txn->_2.prog_id = 2;
249 0 : txn->_2.acct_cnt = 0;
250 0 : txn->_2.data_sz_0 = 0xFA;
251 0 : txn->_2.data_sz_1 = 0x07;
252 :
253 0 : txn->_2.signature_cnt = 1;
254 0 : txn->_2._padding = 0;
255 0 : txn->_2.signature_off = 56;
256 0 : txn->_2.signature_ix_idx= 0;
257 0 : txn->_2.pubkey_off = 24;
258 0 : txn->_2.pubkey_ix_idx = 0;
259 0 : memcpy( txn->_2.hardcoded_pubkey, HARDCODED_PUBKEY, 32UL );
260 0 : memcpy( txn->_2.hardcoded_sig, HARDCODED_SIG, 64UL );
261 0 : txn->_2.message = 0;
262 :
263 0 : txn->_2._padding2 = ctx->lamport_idx * ctx->acct_cnt + ctx->sender_idx; /* Unique per transaction so they aren't duplicates */
264 :
265 0 : transaction_size = sizeof(large_noop_t);
266 0 : recent_blockhash = txn->recent_blockhash;
267 0 : }
268 0 : break;
269 :
270 0 : case BENCHG_TRANSACTION_MODE_TRANSFER:
271 0 : {
272 0 : transfer_t * txn = (transfer_t *)_txn;
273 :
274 0 : txn->sig_cnt = 1;
275 0 : txn->_sig_cnt = 1;
276 0 : txn->ro_signed_cnt = 0;
277 0 : txn->ro_unsigned_cnt = 1;
278 0 : txn->acct_addr_cnt = 3;
279 0 : memcpy( txn->transfer_dest, ctx->acct_public_keys[ sender_idx ].uc, 32UL );
280 0 : for( ulong j=0UL; j<32UL; j++ ) txn->transfer_dest[ j ] ^= 0xFF;
281 0 : memcpy( txn->system_program, (uchar const[32]) { SYS_PROG_ID }, 32UL );
282 0 : txn->instr_cnt = 1;
283 :
284 0 : txn->_1.prog_id = 2;
285 0 : txn->_1.acct_cnt = 2;
286 0 : txn->_1.from_acct = 0;
287 0 : txn->_1.to_acct = 1;
288 0 : txn->_1.data_sz = 9;
289 0 : txn->_1.transfer = 2;
290 :
291 0 : txn->_1.lamports = ctx->lamport_idx;
292 :
293 0 : transaction_size = sizeof(transfer_t);
294 0 : recent_blockhash = txn->recent_blockhash;
295 0 : }
296 0 : break;
297 :
298 0 : default:
299 0 : FD_LOG_ERR(( "Unkown transaction mode %i", ctx->transaction_mode ));
300 0 : break;
301 0 : }
302 :
303 0 : single_signer_hdr_t * txnh = (single_signer_hdr_t *)_txn;
304 0 : fd_memcpy( txnh->fee_payer, ctx->acct_public_keys[ sender_idx ].uc, 32UL );
305 0 : fd_memcpy( recent_blockhash, ctx->recent_blockhash, 32UL );
306 :
307 0 : fd_ed25519_sign( txnh->signature,
308 0 : &(txnh->_sig_cnt),
309 0 : transaction_size-65UL,
310 0 : ctx->acct_public_keys[ sender_idx ].uc,
311 0 : ctx->acct_private_keys[ sender_idx ].uc,
312 0 : ctx->sha );
313 :
314 0 : fd_stem_publish( stem, 0UL, 0UL, ctx->out_chunk, transaction_size, 0UL, 0UL, 0UL );
315 0 : ctx->out_chunk = fd_dcache_compact_next( ctx->out_chunk, transaction_size, ctx->out_chunk0, ctx->out_wmark );
316 :
317 0 : ctx->sender_idx = (ctx->sender_idx + 1UL) % ctx->acct_cnt;
318 0 : if( FD_UNLIKELY( !ctx->sender_idx ) ) {
319 0 : if( FD_UNLIKELY( ctx->changed_blockhash ) ) {
320 0 : ctx->lamport_idx = 1UL+ctx->benchg_idx;
321 0 : ctx->changed_blockhash = 0;
322 0 : fd_memcpy( ctx->recent_blockhash, ctx->staged_blockhash, 32UL );
323 0 : } else {
324 : /* Increments of the number of generators so there are never
325 : duplicate transactions generated. */
326 0 : ctx->lamport_idx += ctx->benchg_cnt;
327 0 : }
328 0 : }
329 0 : }
330 :
331 : static inline void
332 : during_frag( fd_benchg_ctx_t * ctx,
333 : ulong in_idx FD_PARAM_UNUSED,
334 : ulong seq FD_PARAM_UNUSED,
335 : ulong sig FD_PARAM_UNUSED,
336 : ulong chunk,
337 : ulong sz FD_PARAM_UNUSED,
338 0 : ulong ctl FD_PARAM_UNUSED ) {
339 0 : if( FD_UNLIKELY( !ctx->has_recent_blockhash ) ) {
340 0 : fd_memcpy( ctx->recent_blockhash, fd_chunk_to_laddr( ctx->mem, chunk ), 32UL );
341 0 : ctx->has_recent_blockhash = 1;
342 0 : ctx->changed_blockhash = 0;
343 0 : } else {
344 0 : if( FD_UNLIKELY( !memcmp( ctx->recent_blockhash, fd_chunk_to_laddr( ctx->mem, chunk ), 32UL ) ) ) return;
345 :
346 0 : fd_memcpy( ctx->staged_blockhash, fd_chunk_to_laddr( ctx->mem, chunk ), 32UL );
347 0 : ctx->changed_blockhash = 1;
348 0 : }
349 0 : }
350 :
351 : static void
352 : unprivileged_init( fd_topo_t * topo,
353 0 : fd_topo_tile_t * tile ) {
354 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
355 :
356 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
357 0 : fd_benchg_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_benchg_ctx_t ), sizeof( fd_benchg_ctx_t ) );
358 0 : ctx->acct_public_keys = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_pubkey_t ), sizeof( fd_pubkey_t ) * tile->benchg.accounts_cnt );
359 0 : ctx->acct_private_keys = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_pubkey_t ), sizeof( fd_pubkey_t ) * tile->benchg.accounts_cnt );
360 :
361 0 : FD_TEST( fd_rng_join( fd_rng_new( ctx->rng, (uint)tile->kind_id, 0UL ) ) );
362 0 : FD_TEST( fd_sha512_join( fd_sha512_new( ctx->sha ) ) );
363 :
364 0 : ctx->acct_cnt = tile->benchg.accounts_cnt;
365 0 : ctx->transaction_mode = tile->benchg.mode;
366 0 : ctx->contending_fraction = tile->benchg.contending_fraction;
367 0 : ctx->cu_price_spread = tile->benchg.cu_price_spread;
368 :
369 0 : for( ulong i=0UL; i<ctx->acct_cnt; i++ ) {
370 0 : fd_memset( ctx->acct_private_keys[ i ].uc, 0, 32UL );
371 0 : FD_STORE( ulong, ctx->acct_private_keys[ i ].uc, i );
372 0 : fd_ed25519_public_from_private( ctx->acct_public_keys[ i ].uc, ctx->acct_private_keys[ i ].uc , ctx->sha );
373 0 : }
374 :
375 0 : ctx->has_recent_blockhash = 0;
376 :
377 0 : ctx->sender_idx = 0UL;
378 0 : ctx->lamport_idx = 1UL+tile->kind_id;
379 0 : ctx->changed_blockhash = 0;
380 :
381 0 : ctx->benchg_cnt = fd_topo_tile_name_cnt( topo, "benchg" );
382 0 : ctx->benchg_idx = tile->kind_id;
383 :
384 0 : ctx->mem = topo->workspaces[ topo->objs[ topo->links[ tile->out_link_id[ 0 ] ].dcache_obj_id ].wksp_id ].wksp;
385 0 : ctx->out_chunk0 = fd_dcache_compact_chunk0( ctx->mem, topo->links[ tile->out_link_id[ 0 ] ].dcache );
386 0 : ctx->out_wmark = fd_dcache_compact_wmark ( ctx->mem, topo->links[ tile->out_link_id[ 0 ] ].dcache, topo->links[ tile->out_link_id[ 0 ] ].mtu );
387 0 : ctx->out_chunk = ctx->out_chunk0;
388 :
389 0 : ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, 1UL );
390 0 : if( FD_UNLIKELY( scratch_top > (ulong)scratch + scratch_footprint( tile ) ) )
391 0 : FD_LOG_ERR(( "scratch overflow %lu %lu %lu", scratch_top - (ulong)scratch - scratch_footprint( tile ), scratch_top, (ulong)scratch + scratch_footprint( tile ) ));
392 0 : }
393 :
394 0 : #define STEM_BURST (1UL)
395 :
396 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_benchg_ctx_t
397 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_benchg_ctx_t)
398 :
399 0 : #define STEM_CALLBACK_AFTER_CREDIT after_credit
400 0 : #define STEM_CALLBACK_DURING_FRAG during_frag
401 :
402 : #include "../../../../disco/stem/fd_stem.c"
403 :
404 : fd_topo_run_tile_t fd_tile_benchg = {
405 : .name = "benchg",
406 : .scratch_align = scratch_align,
407 : .scratch_footprint = scratch_footprint,
408 : .unprivileged_init = unprivileged_init,
409 : .run = stem_run,
410 : };
|