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