Line data Source code
1 : #include "fd_bundle_crank.h"
2 : #include "../../flamenco/runtime/fd_pubkey_utils.h"
3 :
4 : #if FD_HAS_AVX
5 : #include "../../util/simd/fd_avx.h"
6 : #endif
7 :
8 : FD_STATIC_ASSERT( sizeof(fd_bundle_crank_tip_payment_config_t)==89UL, config_struct );
9 :
10 : #define MEMO_PROGRAM_ID 0x05U,0x4aU,0x53U,0x5aU,0x99U,0x29U,0x21U,0x06U,0x4dU,0x24U,0xe8U,0x71U,0x60U,0xdaU,0x38U,0x7cU, \
11 : 0x7cU,0x35U,0xb5U,0xddU,0xbcU,0x92U,0xbbU,0x81U,0xe4U,0x1fU,0xa8U,0x40U,0x41U,0x05U,0x44U,0x8dU
12 :
13 : static const fd_bundle_crank_3_t fd_bundle_crank_3_base[1] = {{
14 :
15 : .sig_cnt = 1,
16 : ._sig_cnt = 1,
17 : .ro_signed_cnt = 0,
18 : .ro_unsigned_cnt = 5,
19 : .acct_addr_cnt = 21,
20 :
21 : .system_program = { SYS_PROG_ID },
22 : .compute_budget_program = { COMPUTE_BUDGET_PROG_ID },
23 : .memo_program = { MEMO_PROGRAM_ID },
24 :
25 : .instr_cnt = 5,
26 : .compute_budget_instruction = {
27 : .prog_id = 16,
28 : .acct_cnt = 0,
29 : .data_sz = 5,
30 : .set_cu_limit = 2,
31 : .cus = 130000U
32 : },
33 :
34 : .init_tip_distribution_acct = {
35 : .prog_id = 20,
36 : .acct_cnt = 5,
37 : .acct_idx = { 9, 13, 15, 0, 19 },
38 : .data_sz = 43,
39 : .ix_discriminator = { FD_BUNDLE_CRANK_DISC_INIT_TIP_DISTR },
40 : },
41 :
42 : .change_tip_receiver = {
43 : .prog_id = 17,
44 : .acct_cnt = 13,
45 : .acct_idx = { 10, 11, 13, 12, 1, 2, 3, 4, 5, 6, 7, 8, 0 },
46 : .data_sz = 8,
47 : .ix_discriminator = { FD_BUNDLE_CRANK_DISC_CHANGE_TIP_RCV }
48 : },
49 :
50 : .change_block_builder = {
51 : .prog_id = 17,
52 : .acct_cnt = 13,
53 : .acct_idx = { 10, 13, 12, 14, 1, 2, 3, 4, 5, 6, 7, 8, 0},
54 : .data_sz = 16,
55 : .ix_discriminator = { FD_BUNDLE_CRANK_DISC_CHANGE_BLK_BLD },
56 : },
57 :
58 : .memo = {
59 : .prog_id = 18,
60 : .acct_cnt = 0,
61 : .data_sz = 3
62 : },
63 :
64 : /* Account addresses that depend on the network: */
65 : .tip_payment_accounts = {{ 0 }},
66 : .tip_distribution_program_config = { 0 },
67 : .tip_payment_program_config = { 0 },
68 : .tip_distribution_program = { 0 },
69 : .tip_payment_program = { 0 },
70 :
71 : /* Fields that depend on the validator configuration: */
72 : .authorized_voter = { 0 },
73 : .validator_vote_account = { 0 },
74 : .memo.memo = { 0 },
75 : .init_tip_distribution_acct.merkle_root_upload_authority = { 0 },
76 : .init_tip_distribution_acct.commission_bps = 0,
77 : .init_tip_distribution_acct.bump = 0,
78 :
79 : /* Fields that vary each time: */
80 : .old_tip_receiver = { 0 },
81 : .old_block_builder = { 0 },
82 : .new_tip_receiver = { 0 },
83 : .new_block_builder = { 0 },
84 : .change_block_builder.block_builder_commission_pct = 0UL
85 : }};
86 :
87 : static const fd_bundle_crank_2_t fd_bundle_crank_2_base[1] = {{
88 :
89 : .sig_cnt = 1,
90 : ._sig_cnt = 1,
91 : .ro_signed_cnt = 0,
92 : .ro_unsigned_cnt = 3,
93 : .acct_addr_cnt = 19,
94 :
95 : .compute_budget_program = { COMPUTE_BUDGET_PROG_ID },
96 : .memo_program = { MEMO_PROGRAM_ID },
97 :
98 : .instr_cnt = 4,
99 : .compute_budget_instruction = {
100 : .prog_id = 16,
101 : .acct_cnt = 0,
102 : .data_sz = 5,
103 : .set_cu_limit = 2,
104 : .cus = 83000U
105 : },
106 :
107 : .change_tip_receiver = {
108 : .prog_id = 17,
109 : .acct_cnt = 13,
110 : .acct_idx = { 10, 11, 13, 12, 1, 2, 3, 4, 5, 6, 7, 8, 0 },
111 : .data_sz = 8,
112 : .ix_discriminator = { FD_BUNDLE_CRANK_DISC_CHANGE_TIP_RCV }
113 : },
114 :
115 : .change_block_builder = {
116 : .prog_id = 17,
117 : .acct_cnt = 13,
118 : .acct_idx = { 10, 13, 12, 14, 1, 2, 3, 4, 5, 6, 7, 8, 0},
119 : .data_sz = 16,
120 : .ix_discriminator = { FD_BUNDLE_CRANK_DISC_CHANGE_BLK_BLD },
121 : },
122 :
123 : .memo = {
124 : .prog_id = 18,
125 : .acct_cnt = 0,
126 : .data_sz = 3
127 : },
128 :
129 : /* Account addresses that depend on the network: */
130 : .tip_payment_accounts = {{ 0 }},
131 : .tip_distribution_program_config = { 0 },
132 : .tip_payment_program_config = { 0 },
133 : .tip_payment_program = { 0 },
134 :
135 : /* Fields that depend on the validator configuration: */
136 : .authorized_voter = { 0 },
137 : .memo.memo = { 0 },
138 : .validator_vote_account = { 0 },
139 :
140 : /* Fields that vary each time: */
141 : .old_tip_receiver = { 0 },
142 : .old_block_builder = { 0 },
143 : .new_tip_receiver = { 0 },
144 : .new_block_builder = { 0 },
145 : .change_block_builder.block_builder_commission_pct = 0UL
146 : }};
147 :
148 : static const fd_acct_addr_t null_addr = { 0 };
149 :
150 : #define MAP_NAME pidx_map
151 369 : #define MAP_T fd_bundle_crank_gen_pidx_t
152 1509 : #define MAP_KEY_T fd_acct_addr_t
153 : #define MAP_MEMOIZE 0
154 : #define MAP_QUERY_OPT 2 /* low hit rate */
155 1857 : #define MAP_LG_SLOT_CNT 5 /* 18 entries, space for 32 */
156 435 : #define MAP_KEY_NULL null_addr
157 : #if FD_HAS_AVX
158 1608 : # define MAP_KEY_INVAL(k) _mm256_testz_si256( wb_ldu( (k).b ), wb_ldu( (k).b ) )
159 : #else
160 : # define MAP_KEY_INVAL(k) MAP_KEY_EQUAL(k, null_addr)
161 : #endif
162 999 : #define MAP_KEY_EQUAL(k0,k1) (!memcmp((k0).b,(k1).b, FD_TXN_ACCT_ADDR_SZ))
163 : #define MAP_KEY_EQUAL_IS_SLOW 1
164 411 : #define MAP_KEY_HASH(key) ((uint)fd_ulong_hash( fd_ulong_load_8( (key).b ) ))
165 :
166 : #include "../../util/tmpl/fd_map.c"
167 :
168 :
169 540 : #define EXPAND_ARR8(arr, i) arr[(i)], arr[(i)+1], arr[(i)+2], arr[(i)+3], arr[(i)+4], arr[(i)+5], arr[(i)+6], arr[(i)+7],
170 135 : #define EXPAND_ARR32(arr, i) EXPAND_ARR8(arr, (i)) EXPAND_ARR8(arr, (i)+8) EXPAND_ARR8(arr, (i)+16) EXPAND_ARR8(arr, (i)+24)
171 :
172 :
173 :
174 : fd_bundle_crank_gen_t *
175 : fd_bundle_crank_gen_init( void * mem,
176 : fd_acct_addr_t const * tip_distribution_program_addr,
177 : fd_acct_addr_t const * tip_payment_program_addr,
178 : fd_acct_addr_t const * validator_vote_acct_addr,
179 : fd_acct_addr_t const * merkle_root_authority_addr,
180 : char const * scheduler_mode,
181 9 : ulong commission_bps ) {
182 9 : fd_bundle_crank_gen_t * g = (fd_bundle_crank_gen_t *)mem;
183 9 : memcpy( g->crank3, fd_bundle_crank_3_base, sizeof(fd_bundle_crank_3_base) );
184 9 : memcpy( g->crank2, fd_bundle_crank_2_base, sizeof(fd_bundle_crank_2_base) );
185 :
186 9 : g->crank3->init_tip_distribution_acct.commission_bps = (ushort)commission_bps;
187 9 : memcpy( g->crank3->tip_distribution_program, tip_distribution_program_addr, 32UL );
188 9 : memcpy( g->crank3->tip_payment_program, tip_payment_program_addr, 32UL );
189 9 : memcpy( g->crank3->validator_vote_account, validator_vote_acct_addr, 32UL );
190 9 : memcpy( g->crank3->init_tip_distribution_acct.merkle_root_upload_authority, merkle_root_authority_addr, 32UL );
191 :
192 : /* What we want here is just an strncpy, but the compiler makes it
193 : really hard to use strncpy to make a deliberately potentially
194 : unterminated string. Rather than fight the compiler, we basically
195 : hand-do it. */
196 9 : int is_nul;
197 9 : is_nul = 0 || (!scheduler_mode[0]); g->crank3->memo.memo[0] = is_nul ? '\0' : scheduler_mode[0];
198 9 : is_nul = is_nul || (!scheduler_mode[1]); g->crank3->memo.memo[1] = is_nul ? '\0' : scheduler_mode[1];
199 9 : is_nul = is_nul || (!scheduler_mode[2]); g->crank3->memo.memo[2] = is_nul ? '\0' : scheduler_mode[2];
200 :
201 9 : uint cerr[1];
202 9 : do {
203 9 : char seed[13];
204 9 : fd_memcpy( seed, "TIP_ACCOUNT_0", 13 ); /* Not NUL terminated */
205 9 : uchar const * seed_ptr[1] = { (uchar const *)seed };
206 9 : ulong seed_len = 13;
207 81 : for( ulong i=0UL; i<8UL; i++ ) {
208 72 : seed[12] = (char)((ulong)'0' + i);
209 72 : uchar out_bump[1];
210 72 : FD_TEST( FD_PUBKEY_SUCCESS==fd_pubkey_find_program_address( (fd_pubkey_t const *)tip_payment_program_addr,
211 72 : 1UL, seed_ptr, &seed_len,
212 72 : (fd_pubkey_t *)g->crank3->tip_payment_accounts[i], out_bump, cerr ) );
213 72 : }
214 9 : } while( 0 );
215 :
216 9 : do {
217 9 : char seed[14];
218 9 : fd_memcpy( seed, "CONFIG_ACCOUNT", 14 ); /* Not NUL terminated */
219 9 : ulong seed_len = 14;
220 9 : uchar out_bump[1];
221 9 : uchar const * seed_ptr[1] = { (uchar const *)seed };
222 9 : FD_TEST( FD_PUBKEY_SUCCESS==fd_pubkey_find_program_address( (fd_pubkey_t const *)tip_payment_program_addr,
223 9 : 1UL, seed_ptr, &seed_len,
224 9 : (fd_pubkey_t *)g->crank3->tip_payment_program_config, out_bump, cerr ) );
225 : /* Same seed used for tip distribution config account too */
226 9 : FD_TEST( FD_PUBKEY_SUCCESS==fd_pubkey_find_program_address( (fd_pubkey_t const *)tip_distribution_program_addr,
227 9 : 1UL, seed_ptr, &seed_len,
228 9 : (fd_pubkey_t *)g->crank3->tip_distribution_program_config, out_bump, cerr ) );
229 9 : } while( 0 );
230 :
231 : /* Populate crank2 from crank3 */
232 9 : memcpy( g->crank2->tip_payment_accounts, g->crank3->tip_payment_accounts, 8UL*32UL );
233 9 : memcpy( g->crank2->tip_distribution_program_config, g->crank3->tip_distribution_program_config, 32UL );
234 9 : memcpy( g->crank2->tip_payment_program_config, g->crank3->tip_payment_program_config, 32UL );
235 9 : memcpy( g->crank2->tip_payment_program, g->crank3->tip_payment_program, 32UL );
236 9 : memcpy( g->crank2->validator_vote_account, g->crank3->validator_vote_account, 32UL );
237 9 : memcpy( g->crank2->memo.memo, g->crank3->memo.memo, 3UL );
238 :
239 9 : FD_TEST( sizeof(g->txn3)==fd_txn_parse( (uchar const *)g->crank3, sizeof(g->crank3), g->txn3, NULL ) );
240 9 : FD_TEST( sizeof(g->txn2)==fd_txn_parse( (uchar const *)g->crank2, sizeof(g->crank2), g->txn2, NULL ) );
241 :
242 9 : pidx_map_new( g->map );
243 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[0], 0 ) }} )->idx= 1UL;
244 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[1], 0 ) }} )->idx= 2UL;
245 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[2], 0 ) }} )->idx= 3UL;
246 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[3], 0 ) }} )->idx= 4UL;
247 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[4], 0 ) }} )->idx= 5UL;
248 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[5], 0 ) }} )->idx= 6UL;
249 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[6], 0 ) }} )->idx= 7UL;
250 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_accounts[7], 0 ) }} )->idx= 8UL;
251 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_distribution_program_config, 0 ) }} )->idx= 9UL;
252 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_program_config, 0 ) }} )->idx=10UL;
253 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->validator_vote_account, 0 ) }} )->idx=15UL;
254 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->compute_budget_program, 0 ) }} )->idx=16UL;
255 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_payment_program, 0 ) }} )->idx=17UL;
256 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->memo_program, 0 ) }} )->idx=18UL;
257 9 : pidx_map_insert( g->map, (fd_acct_addr_t){{ EXPAND_ARR32( g->crank3->tip_distribution_program, 0 ) }} )->idx=20UL;
258 :
259 9 : g->configured_epoch = ULONG_MAX;
260 9 : return g;
261 9 : }
262 :
263 :
264 : static inline void
265 : fd_bundle_crank_update_epoch( fd_bundle_crank_gen_t * g,
266 9 : ulong epoch ) {
267 9 : uchar const * const seeds[3] = {
268 9 : (uchar const *)"TIP_DISTRIBUTION_ACCOUNT",
269 9 : (uchar const *)g->crank3->validator_vote_account,
270 9 : (uchar const *)&epoch,
271 9 : };
272 9 : ulong seed_szs[3] = { 24, 32, 8 };
273 9 : uint custom_err[1];
274 9 : FD_TEST( FD_PUBKEY_SUCCESS==fd_pubkey_find_program_address( (fd_pubkey_t const *)g->crank3->tip_distribution_program,
275 9 : 3UL, seeds, seed_szs,
276 9 : (fd_pubkey_t *)g->crank3->new_tip_receiver,
277 9 : &(g->crank3->init_tip_distribution_acct.bump), custom_err ) );
278 9 : memcpy( g->crank2->new_tip_receiver, g->crank3->new_tip_receiver, 32UL );
279 9 : g->configured_epoch = epoch;
280 9 : }
281 :
282 : void
283 : fd_bundle_crank_get_addresses( fd_bundle_crank_gen_t * gen,
284 : ulong epoch,
285 : fd_acct_addr_t * out_tip_payment_config,
286 3 : fd_acct_addr_t * out_tip_receiver ) {
287 3 : if( FD_UNLIKELY( epoch!=gen->configured_epoch ) ) fd_bundle_crank_update_epoch( gen, epoch );
288 3 : memcpy( out_tip_payment_config, gen->crank3->tip_payment_program_config, 32UL );
289 3 : memcpy( out_tip_receiver, gen->crank3->new_tip_receiver, 32UL );
290 3 : }
291 :
292 : ulong
293 : fd_bundle_crank_generate( fd_bundle_crank_gen_t * gen,
294 : fd_bundle_crank_tip_payment_config_t const * old_tip_payment_config,
295 : fd_acct_addr_t const * new_block_builder,
296 : fd_acct_addr_t const * identity,
297 : fd_acct_addr_t const * tip_receiver_owner,
298 : ulong epoch,
299 : ulong block_builder_commission,
300 : uchar * out_payload,
301 51 : fd_txn_t * out_txn ) {
302 :
303 51 : if( FD_UNLIKELY( epoch!=gen->configured_epoch ) ) fd_bundle_crank_update_epoch( gen, epoch );
304 :
305 51 : if( FD_UNLIKELY( old_tip_payment_config->discriminator != 0x82ccfa1ee0aa0c9bUL ) ) {
306 0 : FD_LOG_WARNING(( "Found unexpected tip payment config account discriminator %lx. Refusing to crank bundles.",
307 0 : old_tip_payment_config->discriminator ));
308 0 : return ULONG_MAX;
309 0 : }
310 :
311 51 : if( FD_UNLIKELY( pidx_map_key_inval( *old_tip_payment_config->tip_receiver ) ||
312 51 : pidx_map_key_inval( *old_tip_payment_config->block_builder ) ) ) {
313 6 : FD_LOG_WARNING(( "Found null pubkey in tip payment config account. Refusing to crank bundles." ));
314 6 : return ULONG_MAX;
315 6 : }
316 :
317 45 : int swap3 = !fd_memeq( tip_receiver_owner, gen->crank3->tip_distribution_program, sizeof(fd_acct_addr_t) );
318 :
319 45 : if( FD_LIKELY( fd_memeq( old_tip_payment_config->tip_receiver, gen->crank3->new_tip_receiver, 32UL ) &&
320 45 : fd_memeq( old_tip_payment_config->block_builder, new_block_builder, 32UL ) &&
321 45 : !swap3 &&
322 45 : old_tip_payment_config->commission_pct==block_builder_commission ) ) {
323 : /* Everything configured properly! */
324 6 : return 0UL;
325 6 : }
326 :
327 :
328 39 : if( FD_UNLIKELY( swap3 ) ) {
329 3 : memcpy( gen->crank3->authorized_voter, identity, 32UL );
330 3 : memcpy( gen->crank3->new_block_builder, new_block_builder, 32UL );
331 3 : memcpy( gen->crank3->old_tip_receiver, old_tip_payment_config->tip_receiver, 32UL );
332 3 : memcpy( gen->crank3->old_block_builder, old_tip_payment_config->block_builder, 32UL );
333 3 : gen->crank3->change_block_builder.block_builder_commission_pct = block_builder_commission;
334 36 : } else {
335 36 : memcpy( gen->crank2->authorized_voter, identity, 32UL );
336 36 : memcpy( gen->crank2->new_block_builder, new_block_builder, 32UL );
337 36 : memcpy( gen->crank2->old_tip_receiver, old_tip_payment_config->tip_receiver, 32UL );
338 36 : memcpy( gen->crank2->old_block_builder, old_tip_payment_config->block_builder, 32UL );
339 36 : gen->crank2->change_block_builder.block_builder_commission_pct = block_builder_commission;
340 36 : }
341 :
342 : /* If it weren't for the fact that the old tip payment config is
343 : essentially attacker-controlled, we'd be basically done now.
344 : However, someone trying to grief us can e.g. set the old block
345 : builder to the tip payment program, and if we're not careful, we'll
346 : create a transaction with a duplicate account. We trust identity,
347 : new tip_receiver, and new_block_builder well enough though. Note
348 : that it's not possible for either attacker-controlled address to be
349 : the system program, because the account must be writable, and write
350 : locks to the system program get demoted.
351 :
352 : Technically, the validator vote account could be a read only
353 : account, but if an attacker set the old block builder or tip
354 : receiver to that address, we'd need to promote it to a writable
355 : account which is a bit difficult with this way of doing it.
356 : There's not much harm in passing it as writable, and that makes
357 : things much easier. */
358 39 : fd_bundle_crank_gen_pidx_t * identity_pidx = pidx_map_insert( gen->map, *(fd_acct_addr_t *)identity );
359 39 : if( FD_UNLIKELY( !identity_pidx ) ) {
360 0 : FD_LOG_WARNING(( "Identity was already in map. Refusing to crank bundles." ));
361 0 : return ULONG_MAX;
362 0 : }
363 39 : identity_pidx->idx = 0UL;
364 :
365 39 : fd_bundle_crank_gen_pidx_t * new_tr_pidx = pidx_map_insert( gen->map, *(fd_acct_addr_t *)gen->crank3->new_tip_receiver );
366 39 : if( FD_UNLIKELY( !new_tr_pidx ) ) {
367 0 : pidx_map_remove( gen->map, identity_pidx );
368 0 : FD_LOG_WARNING(( "New tip receiver was already in map. Refusing to crank bundles." ));
369 0 : return ULONG_MAX;
370 0 : }
371 39 : new_tr_pidx->idx = 13UL;
372 :
373 39 : fd_bundle_crank_gen_pidx_t * new_bb_pidx = pidx_map_insert( gen->map, *(fd_acct_addr_t *)new_block_builder );
374 39 : if( FD_UNLIKELY( !new_bb_pidx ) ) {
375 0 : pidx_map_remove( gen->map, new_tr_pidx );
376 0 : pidx_map_remove( gen->map, identity_pidx );
377 0 : FD_LOG_WARNING(( "New block builder was already in map. Refusing to crank bundles." ));
378 0 : return ULONG_MAX;
379 0 : }
380 39 : new_bb_pidx->idx = 14UL;
381 :
382 39 : int inserted1 = 0;
383 39 : int inserted2 = 0;
384 39 : fd_bundle_crank_gen_pidx_t dummy1[1] = {{ .idx = 11UL }};
385 39 : fd_bundle_crank_gen_pidx_t dummy2[1] = {{ .idx = 12UL }};
386 39 : ulong swap2_unused_idx = ULONG_MAX;
387 :
388 39 : fd_bundle_crank_gen_pidx_t * old_tr_pidx = pidx_map_query( gen->map, *old_tip_payment_config->tip_receiver, NULL );
389 39 : if( FD_LIKELY( NULL==old_tr_pidx ) ) {
390 21 : old_tr_pidx = pidx_map_insert( gen->map, *old_tip_payment_config->tip_receiver );
391 21 : old_tr_pidx->idx = 11UL;
392 21 : inserted1 = 1;
393 21 : } else if( FD_UNLIKELY( !swap3 && old_tr_pidx->idx>18UL ) ) {
394 : /* Not an account we use in swap2, so it's okay to use index 11 for
395 : the old tip receiver. */
396 0 : swap2_unused_idx = old_tr_pidx->idx;
397 0 : old_tr_pidx = dummy1;
398 18 : } else {
399 : /* perturb the account at index 11, where the old tip receiver
400 : pubkey normally goes, so that it's not a duplicate, then use the
401 : other index. None of the non-attacker controlled keys look
402 : anything like 0xEE, 0xEE, ..., 0xEE, so we just need to make sure
403 : it doesn't match the old block builder (which will end up with a
404 : first byte of either 0xFE or the current value of
405 : old_block_builder[0]). */
406 18 : memset( gen->crank3->old_tip_receiver, (char)0xEE, 32UL );
407 18 : memset( gen->crank2->old_tip_receiver, (char)0xEE, 32UL );
408 18 : gen->crank3->old_tip_receiver[0] = gen->crank3->old_block_builder[0]+1;
409 18 : gen->crank2->old_tip_receiver[0] = gen->crank2->old_block_builder[0]+1;
410 18 : }
411 :
412 39 : fd_bundle_crank_gen_pidx_t * old_bb_pidx = pidx_map_query( gen->map, *old_tip_payment_config->block_builder, NULL );
413 39 : if( FD_UNLIKELY( NULL==old_bb_pidx ) ) {
414 9 : old_bb_pidx = pidx_map_insert( gen->map, *old_tip_payment_config->block_builder );
415 9 : old_bb_pidx->idx = 12UL;
416 9 : inserted2 = 1;
417 30 : } else if( FD_UNLIKELY( !swap3 && old_bb_pidx->idx>18UL && old_bb_pidx->idx!=swap2_unused_idx ) ) {
418 : /* If it happens to be the same account that we don't use in swap2,
419 : then we need to handle it differently. */
420 0 : old_bb_pidx = dummy2;
421 30 : } else {
422 30 : memset( gen->crank3->old_block_builder, (char)0xFE, 32UL );
423 30 : memset( gen->crank2->old_block_builder, (char)0xFE, 32UL );
424 30 : gen->crank3->old_block_builder[2] = gen->crank3->old_tip_receiver[2]+1;
425 30 : gen->crank2->old_block_builder[2] = gen->crank2->old_tip_receiver[2]+1;
426 30 : if( FD_UNLIKELY( old_bb_pidx->idx==swap2_unused_idx ) ) old_bb_pidx = dummy1;
427 30 : }
428 :
429 39 : gen->crank3->change_tip_receiver.acct_idx [1] = (uchar)(old_tr_pidx->idx);
430 39 : gen->crank2->change_tip_receiver.acct_idx [1] = (uchar)(old_tr_pidx->idx);
431 39 : gen->crank3->change_tip_receiver.acct_idx [3] = (uchar)(old_bb_pidx->idx);
432 39 : gen->crank3->change_block_builder.acct_idx[2] = (uchar)(old_bb_pidx->idx);
433 39 : gen->crank2->change_tip_receiver.acct_idx [3] = (uchar)(old_bb_pidx->idx);
434 39 : gen->crank2->change_block_builder.acct_idx[2] = (uchar)(old_bb_pidx->idx);
435 :
436 39 : if( FD_UNLIKELY( inserted2 ) ) pidx_map_remove( gen->map, old_bb_pidx );
437 39 : if( FD_LIKELY ( inserted1 ) ) pidx_map_remove( gen->map, old_tr_pidx );
438 39 : pidx_map_remove( gen->map, new_bb_pidx );
439 39 : pidx_map_remove( gen->map, new_tr_pidx );
440 39 : pidx_map_remove( gen->map, identity_pidx );
441 :
442 39 : if( FD_UNLIKELY( swap3 ) ) {
443 3 : fd_memcpy( out_payload, gen->crank3, sizeof(gen->crank3) );
444 3 : fd_memcpy( out_txn, gen->txn3, sizeof(gen->txn3) );
445 3 : return sizeof(gen->crank3);
446 36 : } else {
447 36 : fd_memcpy( out_payload, gen->crank2, sizeof(gen->crank2) );
448 36 : fd_memcpy( out_txn, gen->txn2, sizeof(gen->txn2) );
449 36 : return sizeof(gen->crank2);
450 36 : }
451 39 : }
452 :
453 : void
454 : fd_bundle_crank_apply( fd_bundle_crank_gen_t * gen,
455 : fd_bundle_crank_tip_payment_config_t * tip_payment_config,
456 : fd_acct_addr_t const * new_block_builder,
457 : fd_acct_addr_t * tip_receiver_owner,
458 : ulong epoch,
459 0 : ulong block_builder_commission ) {
460 :
461 0 : if( FD_UNLIKELY( epoch!=gen->configured_epoch ) ) fd_bundle_crank_update_epoch( gen, epoch );
462 :
463 0 : memcpy( tip_receiver_owner, gen->crank3->tip_distribution_program, sizeof(fd_acct_addr_t) );
464 0 : memcpy( tip_payment_config->tip_receiver, gen->crank3->new_tip_receiver, sizeof(fd_acct_addr_t) );
465 0 : memcpy( tip_payment_config->block_builder, new_block_builder, sizeof(fd_acct_addr_t) );
466 :
467 0 : tip_payment_config->commission_pct = block_builder_commission;
468 0 : }
|