LCOV - code coverage report
Current view: top level - disco/bundle - fd_bundle_crank.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 179 205 87.3 %
Date: 2026-06-29 05:51:35 Functions: 4 5 80.0 %

          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        1509 : # 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          45 :                           fd_txn_t                                    * out_txn ) {
     302             : 
     303          45 :   if( FD_UNLIKELY( epoch!=gen->configured_epoch ) ) fd_bundle_crank_update_epoch( gen, epoch );
     304             : 
     305          45 :   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          45 :   int swap3 = !fd_memeq( tip_receiver_owner, gen->crank3->tip_distribution_program, sizeof(fd_acct_addr_t) );
     312             : 
     313          45 :   if( FD_LIKELY( fd_memeq( old_tip_payment_config->tip_receiver,  gen->crank3->new_tip_receiver, 32UL ) &&
     314          45 :                  fd_memeq( old_tip_payment_config->block_builder, new_block_builder,             32UL ) &&
     315          45 :                  !swap3                                                                                 &&
     316          45 :                  old_tip_payment_config->commission_pct==block_builder_commission ) ) {
     317             :     /* Everything configured properly! */
     318           6 :     return 0UL;
     319           6 :   }
     320             : 
     321             : 
     322          39 :   if( FD_UNLIKELY( swap3 ) ) {
     323           3 :     memcpy( gen->crank3->authorized_voter,  identity,                              32UL );
     324           3 :     memcpy( gen->crank3->new_block_builder, new_block_builder,                     32UL );
     325           3 :     memcpy( gen->crank3->old_tip_receiver,  old_tip_payment_config->tip_receiver,  32UL );
     326           3 :     memcpy( gen->crank3->old_block_builder, old_tip_payment_config->block_builder, 32UL );
     327           3 :     gen->crank3->change_block_builder.block_builder_commission_pct = block_builder_commission;
     328          36 :   } else {
     329          36 :     memcpy( gen->crank2->authorized_voter,  identity,                              32UL );
     330          36 :     memcpy( gen->crank2->new_block_builder, new_block_builder,                     32UL );
     331          36 :     memcpy( gen->crank2->old_tip_receiver,  old_tip_payment_config->tip_receiver,  32UL );
     332          36 :     memcpy( gen->crank2->old_block_builder, old_tip_payment_config->block_builder, 32UL );
     333          36 :     gen->crank2->change_block_builder.block_builder_commission_pct = block_builder_commission;
     334          36 :   }
     335             : 
     336             :   /* If it weren't for the fact that the old tip payment config is
     337             :      essentially attacker-controlled, we'd be basically done now.
     338             :      However, someone trying to grief us can e.g. set the old block
     339             :      builder to the tip payment program, and if we're not careful, we'll
     340             :      create a transaction with a duplicate account.  We trust identity,
     341             :      new tip_receiver, and new_block_builder well enough though.  Note
     342             :      that it's not possible for either attacker-controlled address to be
     343             :      the system program, because the account must be writable, and write
     344             :      locks to the system program get demoted.
     345             : 
     346             :      Technically, the validator vote account could be a read only
     347             :      account, but if an attacker set the old block builder or tip
     348             :      receiver to that address, we'd need to promote it to a writable
     349             :      account which is a bit difficult with this way of doing it.
     350             :      There's not much harm in passing it as writable, and that makes
     351             :      things much easier. */
     352          39 :   fd_bundle_crank_gen_pidx_t * identity_pidx = pidx_map_insert( gen->map, *(fd_acct_addr_t *)identity );
     353          39 :   if( FD_UNLIKELY( !identity_pidx ) ) {
     354           0 :     FD_LOG_WARNING(( "Identity was already in map.  Refusing to crank bundles." ));
     355           0 :     return ULONG_MAX;
     356           0 :   }
     357          39 :   identity_pidx->idx = 0UL;
     358             : 
     359          39 :   fd_bundle_crank_gen_pidx_t * new_tr_pidx = pidx_map_insert( gen->map, *(fd_acct_addr_t *)gen->crank3->new_tip_receiver );
     360          39 :   if( FD_UNLIKELY( !new_tr_pidx ) ) {
     361           0 :     pidx_map_remove( gen->map, identity_pidx );
     362           0 :     FD_LOG_WARNING(( "New tip receiver was already in map.  Refusing to crank bundles." ));
     363           0 :     return ULONG_MAX;
     364           0 :   }
     365          39 :   new_tr_pidx->idx = 13UL;
     366             : 
     367          39 :   fd_bundle_crank_gen_pidx_t * new_bb_pidx = pidx_map_insert( gen->map, *(fd_acct_addr_t *)new_block_builder );
     368          39 :   if( FD_UNLIKELY( !new_bb_pidx ) ) {
     369           0 :     pidx_map_remove( gen->map, new_tr_pidx   );
     370           0 :     pidx_map_remove( gen->map, identity_pidx );
     371           0 :     FD_LOG_WARNING(( "New block builder was already in map.  Refusing to crank bundles." ));
     372           0 :     return ULONG_MAX;
     373           0 :   }
     374          39 :   new_bb_pidx->idx = 14UL;
     375             : 
     376          39 :   int inserted1 = 0;
     377          39 :   int inserted2 = 0;
     378          39 :   fd_bundle_crank_gen_pidx_t dummy1[1] = {{ .idx = 11UL }};
     379          39 :   fd_bundle_crank_gen_pidx_t dummy2[1] = {{ .idx = 12UL }};
     380          39 :   ulong swap2_unused_idx = ULONG_MAX;
     381             : 
     382          39 :   fd_bundle_crank_gen_pidx_t * old_tr_pidx = pidx_map_query( gen->map, *old_tip_payment_config->tip_receiver, NULL );
     383          39 :   if( FD_LIKELY( NULL==old_tr_pidx ) ) {
     384          21 :     old_tr_pidx = pidx_map_insert( gen->map, *old_tip_payment_config->tip_receiver );
     385          21 :     old_tr_pidx->idx = 11UL;
     386          21 :     inserted1 = 1;
     387          21 :   } else if( FD_UNLIKELY( !swap3 && old_tr_pidx->idx>18UL ) ) {
     388             :     /* Not an account we use in swap2, so it's okay to use index 11 for
     389             :        the old tip receiver. */
     390           0 :     swap2_unused_idx = old_tr_pidx->idx;
     391           0 :     old_tr_pidx      = dummy1;
     392          18 :   } else {
     393             :     /* perturb the account at index 11, where the old tip receiver
     394             :        pubkey normally goes, so that it's not a duplicate, then use the
     395             :        other index.  None of the non-attacker controlled keys look
     396             :        anything like 0xEE, 0xEE, ..., 0xEE, so we just need to make sure
     397             :        it doesn't match the old block builder (which will end up with a
     398             :        first byte of either 0xFE or the current value of
     399             :        old_block_builder[0]). */
     400          18 :     memset( gen->crank3->old_tip_receiver, (char)0xEE, 32UL );
     401          18 :     memset( gen->crank2->old_tip_receiver, (char)0xEE, 32UL );
     402          18 :     gen->crank3->old_tip_receiver[0] = gen->crank3->old_block_builder[0]+1;
     403          18 :     gen->crank2->old_tip_receiver[0] = gen->crank2->old_block_builder[0]+1;
     404          18 :   }
     405             : 
     406          39 :   fd_bundle_crank_gen_pidx_t * old_bb_pidx = pidx_map_query( gen->map, *old_tip_payment_config->block_builder, NULL );
     407          39 :   if( FD_UNLIKELY( NULL==old_bb_pidx ) ) {
     408           9 :     old_bb_pidx = pidx_map_insert( gen->map, *old_tip_payment_config->block_builder );
     409           9 :     old_bb_pidx->idx = 12UL;
     410           9 :     inserted2 = 1;
     411          30 :   } else if( FD_UNLIKELY( !swap3 && old_bb_pidx->idx>18UL && old_bb_pidx->idx!=swap2_unused_idx ) ) {
     412             :     /* If it happens to be the same account that we don't use in swap2,
     413             :        then we need to handle it differently. */
     414           0 :     old_bb_pidx = dummy2;
     415          30 :   } else {
     416          30 :     memset( gen->crank3->old_block_builder, (char)0xFE, 32UL );
     417          30 :     memset( gen->crank2->old_block_builder, (char)0xFE, 32UL );
     418          30 :     gen->crank3->old_block_builder[2] = gen->crank3->old_tip_receiver[2]+1;
     419          30 :     gen->crank2->old_block_builder[2] = gen->crank2->old_tip_receiver[2]+1;
     420          30 :     if( FD_UNLIKELY( old_bb_pidx->idx==swap2_unused_idx ) ) old_bb_pidx = dummy1;
     421          30 :   }
     422             : 
     423          39 :   gen->crank3->change_tip_receiver.acct_idx [1] = (uchar)(old_tr_pidx->idx);
     424          39 :   gen->crank2->change_tip_receiver.acct_idx [1] = (uchar)(old_tr_pidx->idx);
     425          39 :   gen->crank3->change_tip_receiver.acct_idx [3] = (uchar)(old_bb_pidx->idx);
     426          39 :   gen->crank3->change_block_builder.acct_idx[2] = (uchar)(old_bb_pidx->idx);
     427          39 :   gen->crank2->change_tip_receiver.acct_idx [3] = (uchar)(old_bb_pidx->idx);
     428          39 :   gen->crank2->change_block_builder.acct_idx[2] = (uchar)(old_bb_pidx->idx);
     429             : 
     430          39 :   if( FD_UNLIKELY( inserted2 ) ) pidx_map_remove( gen->map, old_bb_pidx );
     431          39 :   if( FD_LIKELY  ( inserted1 ) ) pidx_map_remove( gen->map, old_tr_pidx );
     432          39 :   pidx_map_remove( gen->map, new_bb_pidx   );
     433          39 :   pidx_map_remove( gen->map, new_tr_pidx   );
     434          39 :   pidx_map_remove( gen->map, identity_pidx );
     435             : 
     436          39 :   if( FD_UNLIKELY( swap3 ) ) {
     437           3 :     fd_memcpy( out_payload, gen->crank3, sizeof(gen->crank3) );
     438           3 :     fd_memcpy( out_txn,     gen->txn3,   sizeof(gen->txn3)   );
     439           3 :     return sizeof(gen->crank3);
     440          36 :   } else {
     441          36 :     fd_memcpy( out_payload, gen->crank2, sizeof(gen->crank2) );
     442          36 :     fd_memcpy( out_txn,     gen->txn2,   sizeof(gen->txn2)   );
     443          36 :     return sizeof(gen->crank2);
     444          36 :   }
     445          39 : }
     446             : 
     447             : void
     448             : fd_bundle_crank_apply( fd_bundle_crank_gen_t                       * gen,
     449             :                        fd_bundle_crank_tip_payment_config_t        * tip_payment_config,
     450             :                        fd_acct_addr_t                       const  * new_block_builder,
     451             :                        fd_acct_addr_t                              * tip_receiver_owner,
     452             :                        ulong                                         epoch,
     453           0 :                        ulong                                         block_builder_commission ) {
     454             : 
     455           0 :   if( FD_UNLIKELY( epoch!=gen->configured_epoch ) ) fd_bundle_crank_update_epoch( gen, epoch );
     456             : 
     457           0 :   memcpy( tip_receiver_owner,                gen->crank3->tip_distribution_program, sizeof(fd_acct_addr_t) );
     458           0 :   memcpy( tip_payment_config->tip_receiver,  gen->crank3->new_tip_receiver,         sizeof(fd_acct_addr_t) );
     459           0 :   memcpy( tip_payment_config->block_builder, new_block_builder,                     sizeof(fd_acct_addr_t) );
     460             : 
     461           0 :   tip_payment_config->commission_pct = block_builder_commission;
     462           0 : }

Generated by: LCOV version 1.14