LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_stake_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1738 1900 91.5 %
Date: 2024-11-13 11:58:15 Functions: 46 54 85.2 %

          Line data    Source code
       1             : #define FD_SCRATCH_USE_HANDHOLDING 1
       2             : #include <limits.h>
       3             : 
       4             : #include "../../../util/bits/fd_sat.h"
       5             : #include "../../../util/bits/fd_uwide.h"
       6             : #include "../fd_account.h"
       7             : #include "../fd_executor.h"
       8             : #include "../fd_pubkey_utils.h"
       9             : #include "../fd_system_ids.h"
      10             : 
      11             : #include "fd_stake_program.h"
      12             : #include "fd_vote_program.h"
      13             : #include "../sysvar/fd_sysvar_epoch_schedule.h"
      14             : #include "../sysvar/fd_sysvar_rent.h"
      15             : 
      16             : /* A note on fd_borrowed_account_acquire_write:
      17             : 
      18             :    The stake program uses this function to prevent aliasing of accounts.
      19             :    (When the same account is passed via multiple instruction account
      20             :    indexes.)  Internally, it acquires a transaction-wide mutex on the
      21             :    account.  If called twice on the same account while the mutex is
      22             :    still locked, it returns an "AccountBorrowFailed" error.
      23             : 
      24             :    There is no exact equivalent to this in Agave/Rust.
      25             : 
      26             :      let handle = instruction_context.try_borrow_instruction_account(...)
      27             : 
      28             :    The above creates the lock on the account.  However, that lock is
      29             :    **implicitly** released when 'handle' goes out of scope.  Firedancer
      30             :    releases the handle **explicitly**. */
      31             : 
      32             : /**********************************************************************/
      33             : /* Errors                                                             */
      34             : /**********************************************************************/
      35             : 
      36             : // DO NOT REORDER: https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md#enums
      37             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L28
      38             : #define FD_STAKE_ERR_NO_CREDITS_TO_REDEEM                                                   ( 0 )
      39          81 : #define FD_STAKE_ERR_LOCKUP_IN_FORCE                                                        ( 1 )
      40         219 : #define FD_STAKE_ERR_ALREADY_DEACTIVATED                                                    ( 2 )
      41          66 : #define FD_STAKE_ERR_TOO_SOON_TO_REDELEGATE                                                 ( 3 )
      42           0 : #define FD_STAKE_ERR_INSUFFICIENT_STAKE                                                     ( 4 )
      43         561 : #define FD_STAKE_ERR_MERGE_TRANSIENT_STAKE                                                  ( 5 )
      44         303 : #define FD_STAKE_ERR_MERGE_MISMATCH                                                         ( 6 )
      45          39 : #define FD_STAKE_ERR_CUSTODIAN_MISSING                                                      ( 7 )
      46          36 : #define FD_STAKE_ERR_CUSTODIAN_SIGNATURE_MISSING                                            ( 8 )
      47         189 : #define FD_STAKE_ERR_INSUFFICIENT_REFERENCE_VOTES                                           ( 9 )
      48          27 : #define FD_STAKE_ERR_VOTE_ADDRESS_MISMATCH                                                  ( 10 )
      49         204 : #define FD_STAKE_ERR_MINIMUM_DELIQUENT_EPOCHS_FOR_DEACTIVATION_NOT_MET                      ( 11 )
      50         213 : #define FD_STAKE_ERR_INSUFFICIENT_DELEGATION                                                ( 12 )
      51             : #define FD_STAKE_ERR_REDELEGATE_TRANSIENT_OR_INACTIVE_STAKE                                 ( 13 )
      52             : #define FD_STAKE_ERR_REDELEGATE_TO_SAME_VOTE_ACCOUNT                                        ( 14 )
      53             : #define FD_STAKE_ERR_REDELEGATED_STAKE_MUST_FULLY_ACTIVATE_BEFORE_DEACTIVATION_IS_PERMITTED ( 15 )
      54         234 : #define FD_STAKE_ERR_EPOCH_REWARDS_ACTIVE                                                   ( 16 )
      55             : 
      56             : /**********************************************************************/
      57             : /* Constants                                                          */
      58             : /**********************************************************************/
      59             : 
      60             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/lib.rs#L31
      61        3984 : #define MINIMUM_DELEGATION_SOL                     ( 1 )
      62             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/native_token.rs#L6
      63        3984 : #define LAMPORTS_PER_SOL                           ( 1000000000 )
      64             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/mod.rs#L18
      65        1119 : #define MINIMUM_DELINQUENT_EPOCHS_FOR_DEACTIVATION ( 5 )
      66             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L26-L28
      67        5379 : #define DEFAULT_WARMUP_COOLDOWN_RATE               ( 0.25 )
      68        5169 : #define NEW_WARMUP_COOLDOWN_RATE                   ( 0.09 )
      69           0 : #define DEFAULT_SLASH_PENALTY                      ( 12 )
      70             : 
      71             : #define STAKE_AUTHORIZE_STAKER                                                                     \
      72        4104 :   ( ( fd_stake_authorize_t ){ .discriminant = fd_stake_authorize_enum_staker, .inner = {0} } )
      73             : #define STAKE_AUTHORIZE_WITHDRAWER                                                                 \
      74         477 :   ( ( fd_stake_authorize_t ){ .discriminant = fd_stake_authorize_enum_withdrawer, .inner = {0} } )
      75             : 
      76             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L51
      77             : #define DEFAULT_COMPUTE_UNITS 750UL
      78             : 
      79             : /**********************************************************************/
      80             : /* MergeKind                                                          */
      81             : /**********************************************************************/
      82             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1074-L1079
      83             : struct merge_kind_inactive {
      84             :   fd_stake_meta_t  meta;
      85             :   ulong            active_stake;
      86             :   fd_stake_flags_t stake_flags;
      87             : };
      88             : typedef struct merge_kind_inactive merge_kind_inactive_t;
      89             : 
      90             : struct merge_kind_activation_epoch {
      91             :   fd_stake_meta_t  meta;
      92             :   fd_stake_t       stake;
      93             :   fd_stake_flags_t stake_flags;
      94             : };
      95             : typedef struct merge_kind_activation_epoch merge_kind_activation_epoch_t;
      96             : 
      97             : struct merge_kind_fully_active {
      98             :   fd_stake_meta_t meta;
      99             :   fd_stake_t      stake;
     100             : };
     101             : typedef struct merge_kind_fully_active merge_kind_fully_active_t;
     102             : 
     103             : union merge_kind_inner {
     104             :   merge_kind_inactive_t         inactive;
     105             :   merge_kind_activation_epoch_t activation_epoch;
     106             :   merge_kind_fully_active_t     fully_active;
     107             : };
     108             : typedef union merge_kind_inner merge_kind_inner_t;
     109             : 
     110             : struct merge_kind {
     111             :   uint               discriminant;
     112             :   merge_kind_inner_t inner;
     113             : };
     114             : typedef struct merge_kind merge_kind_t;
     115             : 
     116             : enum { merge_kind_inactive = 0, merge_kind_activation_epoch = 1, merge_kind_fully_active = 2 };
     117             : 
     118             : typedef fd_stake_history_entry_t stake_activation_status_t;
     119             : 
     120             : struct effective_activating {
     121             :   ulong effective;
     122             :   ulong activating;
     123             : };
     124             : typedef struct effective_activating effective_activating_t;
     125             : 
     126             : /**********************************************************************/
     127             : /* Bincode                                                            */
     128             : /**********************************************************************/
     129             : 
     130             : static int
     131             : get_state( fd_borrowed_account_t const * self,
     132             :            fd_valloc_t                   valloc,
     133       11625 :            fd_stake_state_v2_t *         out ) {
     134       11625 :   int rc;
     135             : 
     136       11625 :   fd_bincode_decode_ctx_t bincode_ctx;
     137       11625 :   bincode_ctx.data    = self->const_data;
     138       11625 :   bincode_ctx.dataend = self->const_data + self->const_meta->dlen;
     139       11625 :   bincode_ctx.valloc  = valloc;
     140             : 
     141       11625 :   rc = fd_stake_state_v2_decode( out, &bincode_ctx );
     142       11625 :   if( FD_UNLIKELY( rc!=FD_BINCODE_SUCCESS ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     143             : 
     144       10857 :   return 0;
     145       11625 : }
     146             : 
     147             : static int
     148             : set_state( fd_exec_instr_ctx_t const * ctx,
     149             :            ulong                       acct_idx,
     150        3555 :            fd_stake_state_v2_t const * state ) {
     151             : 
     152        3555 :   uchar * data = NULL;
     153        3555 :   ulong   dlen = 0UL;
     154             :   
     155        3555 :   int err = fd_account_get_data_mut( ctx, acct_idx, &data, &dlen );
     156        3555 :   if( FD_UNLIKELY( err ) ) return err;
     157             : 
     158        3285 :   ulong serialized_size = fd_stake_state_v2_size( state );
     159        3285 :   if( FD_UNLIKELY( serialized_size>dlen ) )
     160           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     161             : 
     162        3285 :   fd_borrowed_account_t * account = NULL;
     163        3285 :   do {
     164        3285 :     int err = fd_instr_borrowed_account_modify_idx( ctx, acct_idx, serialized_size, &account );
     165        3285 :     if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
     166        3285 :   } while(0);
     167             : 
     168        3285 :   fd_bincode_encode_ctx_t encode = {
     169        3285 :     .data    = account->data,
     170        3285 :     .dataend = account->data + serialized_size,
     171        3285 :   };
     172        3285 :   do {
     173        3285 :     int err = fd_stake_state_v2_encode( state, &encode );
     174        3285 :     if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_stake_state_v2_encode failed" ));
     175        3285 :   } while(0);
     176             : 
     177        3285 :   return 0;
     178        3285 : }
     179             : 
     180             : /**********************************************************************/
     181             : /* mod stake                                                          */
     182             : /**********************************************************************/
     183             : 
     184             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/lib.rs#L29
     185             : static inline ulong
     186        3984 : get_minimum_delegation( fd_exec_slot_ctx_t const * slot_ctx /* feature set */ ) {
     187        3984 :   return fd_ulong_if( FD_FEATURE_ACTIVE( slot_ctx, stake_raise_minimum_delegation_to_1_sol ),
     188        3984 :                       MINIMUM_DELEGATION_SOL * LAMPORTS_PER_SOL,
     189        3984 :                       1 );
     190        3984 : }
     191             : 
     192             : /**********************************************************************/
     193             : /* mod stake/state                                                    */
     194             : /**********************************************************************/
     195             : 
     196             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L30
     197             : static inline double
     198        5169 : warmup_cooldown_rate( ulong current_epoch, ulong * new_rate_activation_epoch ) {
     199        5169 :   return fd_double_if( current_epoch <
     200        5169 :                            ( new_rate_activation_epoch ? *new_rate_activation_epoch : ULONG_MAX ),
     201        5169 :                        DEFAULT_WARMUP_COOLDOWN_RATE,
     202        5169 :                        NEW_WARMUP_COOLDOWN_RATE );
     203        5169 : }
     204             : 
     205             : /**********************************************************************/
     206             : /* validated                                                          */
     207             : /**********************************************************************/
     208             : 
     209             : struct validated_delegated_info {
     210             :   ulong stake_amount;
     211             : };
     212             : typedef struct validated_delegated_info validated_delegated_info_t;
     213             : 
     214             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L963
     215             : static int
     216             : validate_delegated_amount( fd_borrowed_account_t *      account,
     217             :                            fd_stake_meta_t const *      meta,
     218             :                            fd_exec_slot_ctx_t const *   slot_ctx,
     219             :                            validated_delegated_info_t * out,
     220         630 :                            uint *                       custom_err ) {
     221         630 :   ulong stake_amount = fd_ulong_sat_sub( account->const_meta->info.lamports, meta->rent_exempt_reserve );
     222             : 
     223         630 :   if( FD_UNLIKELY( stake_amount<get_minimum_delegation( slot_ctx ) ) ) {
     224         150 :     *custom_err = FD_STAKE_ERR_INSUFFICIENT_DELEGATION;
     225         150 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     226         150 :   }
     227         480 :   out->stake_amount = stake_amount;
     228         480 :   return 0;
     229         630 : }
     230             : 
     231             : struct validated_split_info {
     232             :   ulong source_remaining_balance;
     233             :   ulong destination_rent_exempt_reserve;
     234             : };
     235             : typedef struct validated_split_info validated_split_info_t;
     236             : 
     237             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L992
     238             : static int
     239             : validate_split_amount( fd_exec_instr_ctx_t const * invoke_context,
     240             :                        uchar                       source_account_index,
     241             :                        uchar                       destination_account_index,
     242             :                        ulong                       lamports,
     243             :                        fd_stake_meta_t const *     source_meta,
     244             :                        ulong                       additional_required_lamports,
     245             :                        int                         source_is_active,
     246        1530 :                        validated_split_info_t *    out ) {
     247             : 
     248        1530 :   ulong source_lamports = 0;
     249             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1003-L1004
     250        6120 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( invoke_context, source_account_index, source_account ) {
     251             : 
     252             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1005
     253        1530 :   source_lamports = source_account->const_meta->info.lamports;
     254             : 
     255        1530 :   } FD_BORROWED_ACCOUNT_DROP( source_account );
     256             : 
     257        1530 :   ulong destination_lamports = 0;
     258        1530 :   ulong destination_data_len = 0;
     259             : 
     260             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1007-L1008
     261        6120 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( invoke_context, destination_account_index, destination_account ) {
     262             : 
     263             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1009-1010
     264        1530 :   destination_lamports = destination_account->const_meta->info.lamports;
     265        1530 :   destination_data_len = destination_account->const_meta->dlen;
     266             : 
     267        1530 :   } FD_BORROWED_ACCOUNT_DROP( destination_account );
     268             : 
     269             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1013-L1021
     270        1530 :   if( FD_UNLIKELY( lamports==0 ) ) return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
     271        1467 :   if( FD_UNLIKELY( lamports>source_lamports ) ) return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
     272             : 
     273             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1027-L1040
     274        1467 :   ulong source_minimum_balance =
     275        1467 :       fd_ulong_sat_add( source_meta->rent_exempt_reserve, additional_required_lamports );
     276        1467 :   ulong source_remaining_balance = fd_ulong_sat_sub( source_lamports, lamports );
     277             : 
     278        1467 :   if( FD_LIKELY( source_remaining_balance==0 ) ) {
     279        1038 :   } else if( source_remaining_balance<source_minimum_balance ) {
     280         117 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
     281         921 :   } else {
     282        1350 :   };
     283             : 
     284             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1042
     285        1350 :   fd_rent_t const * rent = fd_sysvar_cache_rent( invoke_context->slot_ctx->sysvar_cache );
     286        1350 :   if( FD_UNLIKELY( !rent ) )
     287           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     288             : 
     289             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1043
     290        1350 :   ulong destination_rent_exempt_reserve =
     291        1350 :       fd_rent_exempt_minimum_balance( rent, destination_data_len );
     292             : 
     293             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1048
     294        1350 :   if( FD_UNLIKELY(
     295        1350 :            FD_FEATURE_ACTIVE( invoke_context->slot_ctx, require_rent_exempt_split_destination ) &&
     296        1350 :            source_is_active && source_remaining_balance!=0 &&
     297        1350 :            destination_lamports<destination_rent_exempt_reserve ) ) {
     298         258 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
     299         258 :   }
     300             : 
     301             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1059-L1066
     302        1092 :   ulong destination_minimum_balance =
     303        1092 :       fd_ulong_sat_add( destination_rent_exempt_reserve, additional_required_lamports );
     304        1092 :   ulong destination_balance_deficit =
     305        1092 :       fd_ulong_sat_sub( destination_minimum_balance, destination_lamports );
     306        1092 :   if( FD_UNLIKELY( lamports<destination_balance_deficit ) ) {
     307         168 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
     308         168 :   }
     309             : 
     310             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1067-L1071
     311         924 :   out->source_remaining_balance        = source_remaining_balance;
     312         924 :   out->destination_rent_exempt_reserve = destination_rent_exempt_reserve;
     313         924 :   return 0;
     314        1092 : }
     315             : 
     316             : /**********************************************************************/
     317             : /* impl Lockup                                                        */
     318             : /**********************************************************************/
     319             : 
     320             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L270
     321             : static inline int
     322             : lockup_is_in_force( fd_stake_lockup_t const *     self,
     323             :                     fd_sol_sysvar_clock_t const * clock,
     324        1875 :                     fd_pubkey_t const *           custodian ) {
     325             :   // FIXME FD_LIKELY
     326        1875 :   if( custodian && !memcmp( custodian, &self->custodian, sizeof( fd_pubkey_t ) ) ) {
     327          45 :     return 0;
     328          45 :   }
     329        1830 :   return self->unix_timestamp>clock->unix_timestamp || self->epoch>clock->epoch;
     330        1875 : }
     331             : 
     332             : /**********************************************************************/
     333             : /* impl Authorized                                                    */
     334             : /**********************************************************************/
     335             : 
     336             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L359
     337             : static inline int
     338             : authorized_check( fd_stake_authorized_t const * self,
     339             :                   fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
     340        4809 :                   fd_stake_authorize_t          stake_authorize ) {
     341             :   /* clang-format off */
     342        4809 :   switch( stake_authorize.discriminant ) {
     343             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L365
     344        4104 :   case fd_stake_authorize_enum_staker:
     345        4104 :     if( FD_LIKELY( fd_instr_signers_contains( signers, &self->staker ) ) ) {
     346        3168 :       return 0;
     347        3168 :     }
     348         936 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     349             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L366
     350         705 :   case fd_stake_authorize_enum_withdrawer:
     351         705 :     if( FD_LIKELY( fd_instr_signers_contains( signers, &self->withdrawer ) ) ) {
     352         555 :       return 0;
     353         555 :     }
     354         150 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     355           0 :   default:
     356           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     357        4809 :   }
     358             :   /* clang-format on */
     359        4809 : }
     360             : 
     361             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L371
     362             : static int
     363             : authorized_authorize( fd_stake_authorized_t *                  self,
     364             :                       fd_pubkey_t const *                      signers[static FD_TXN_SIG_MAX],
     365             :                       fd_pubkey_t const *                      new_authorized,
     366             :                       fd_stake_authorize_t const *             stake_authorize,
     367             :                       fd_stake_lockup_custodian_args_t const * lockup_custodian_args,
     368         747 :                       /* out */ uint *                         custom_err ) {
     369         747 :   int rc;
     370         747 :   switch( stake_authorize->discriminant ) {
     371             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L379
     372         396 :   case fd_stake_authorize_enum_staker:
     373         396 :     if( FD_UNLIKELY( !fd_instr_signers_contains( signers, &self->staker ) &&
     374         396 :                       !fd_instr_signers_contains( signers, &self->withdrawer ) ) ) {
     375         216 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     376         216 :     }
     377         180 :     self->staker = *new_authorized;
     378         180 :     break;
     379             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L386
     380         351 :   case fd_stake_authorize_enum_withdrawer:
     381         351 :     if( FD_LIKELY( lockup_custodian_args ) ) {
     382         351 :       fd_stake_lockup_t const *     lockup    = &lockup_custodian_args->lockup;
     383         351 :       fd_sol_sysvar_clock_t const * clock     = &lockup_custodian_args->clock;
     384         351 :       fd_pubkey_t const *           custodian = lockup_custodian_args->custodian;
     385             : 
     386             :       // FIXME FD_LIKELY
     387         351 :       if( lockup_is_in_force( lockup, clock, NULL ) ) {
     388             :         // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L389-L402
     389         129 :         if( !custodian ) { // FIXME FD_LIKELY
     390          39 :           *custom_err = FD_STAKE_ERR_CUSTODIAN_MISSING;
     391          39 :           return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     392          90 :         } else {
     393          90 :           if( FD_UNLIKELY( !fd_instr_signers_contains( signers, custodian ) ) ) {
     394          36 :             *custom_err = FD_STAKE_ERR_CUSTODIAN_SIGNATURE_MISSING;
     395          36 :             return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     396          36 :           }
     397             : 
     398          54 :           if( FD_UNLIKELY( lockup_is_in_force( lockup, clock, custodian ) ) ) {
     399          48 :             *custom_err = FD_STAKE_ERR_LOCKUP_IN_FORCE;
     400          48 :             return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     401          48 :           }
     402          54 :         }
     403         129 :       }
     404             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L405
     405         228 :       rc = authorized_check( self, signers, *stake_authorize );
     406         228 :       if( FD_UNLIKELY( rc ) ) return rc;
     407         144 :       self->withdrawer = *new_authorized;
     408         144 :     }
     409         747 :   }
     410         324 :   return 0;
     411         747 : }
     412             : 
     413             : /**********************************************************************/
     414             : /* impl Meta                                                          */
     415             : /**********************************************************************/
     416             : 
     417             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L482
     418             : static inline int
     419             : set_lockup_meta( fd_stake_meta_t *             self,
     420             :                  fd_lockup_args_t const *      lockup,
     421             :                  fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
     422         525 :                  fd_sol_sysvar_clock_t const * clock ) {
     423             :   // FIXME FD_LIKELY
     424         525 :   if( lockup_is_in_force( &self->lockup, clock, NULL ) ) {
     425         333 :     if( !fd_instr_signers_contains( signers, &self->lockup.custodian ) ) {
     426         270 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     427         270 :     }
     428         333 :   } else if( !fd_instr_signers_contains( signers, &self->authorized.withdrawer ) ) {
     429         138 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     430         138 :   }
     431             : 
     432             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L498-L506
     433         117 :   if( lockup->unix_timestamp ) self->lockup.unix_timestamp = *lockup->unix_timestamp;
     434         117 :   if( lockup->epoch ) self->lockup.epoch = *lockup->epoch;
     435         117 :   if( lockup->custodian ) self->lockup.custodian = *lockup->custodian;
     436         117 :   return 0;
     437         525 : }
     438             : 
     439             : /**********************************************************************/
     440             : /* impl Delegation                                                    */
     441             : /**********************************************************************/
     442             : 
     443             : typedef fd_stake_history_entry_t fd_stake_activation_status_t;
     444             : 
     445             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L728
     446             : static effective_activating_t
     447             : stake_and_activating( fd_delegation_t const *    self,
     448             :                       ulong                      target_epoch,
     449             :                       fd_stake_history_t const * history,
     450        3342 :                       ulong *                    new_rate_activation_epoch ) {
     451        3342 :   ulong delegated_stake = self->stake;
     452             : 
     453        3342 :   fd_stake_history_entry_t const * cluster_stake_at_activation_epoch;
     454             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L736
     455        3342 :   if( self->activation_epoch==ULONG_MAX ) {
     456         312 :     return ( effective_activating_t ){ .effective = delegated_stake, .activating = 0 };
     457        3030 :   } else if( self->activation_epoch==self->deactivation_epoch ) {
     458         270 :     return ( effective_activating_t ){ .effective = 0, .activating = 0 };
     459        2760 :   } else if( target_epoch==self->activation_epoch ) {
     460         453 :     return ( effective_activating_t ){ .effective = 0, .activating = delegated_stake };
     461        2307 :   } else if( target_epoch<self->activation_epoch ) {
     462         252 :     return ( effective_activating_t ){ .effective = 0, .activating = 0 };
     463        2055 :   } else if( history &&
     464        2055 :               ( cluster_stake_at_activation_epoch = fd_stake_history_treap_ele_query_const(
     465        2055 :                     history->treap, self->activation_epoch, history->pool ) ) ) {
     466         588 :     ulong                            prev_epoch         = self->activation_epoch;
     467         588 :     fd_stake_history_entry_t const * prev_cluster_stake = cluster_stake_at_activation_epoch;
     468             : 
     469             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L763
     470         588 :     ulong current_epoch;
     471         588 :     ulong current_effective_stake = 0;
     472        4083 :     for( ;; ) {
     473        4083 :       current_epoch = prev_epoch + 1;
     474        4083 :       if( FD_LIKELY( prev_cluster_stake->activating==0 ) ) { // FIXME always optimize loop break?
     475         120 :         break;
     476         120 :       }
     477             : 
     478             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L775-L780
     479        3963 :       ulong  remaining_activating_stake = delegated_stake - current_effective_stake;
     480        3963 :       double weight = (double)remaining_activating_stake / (double)prev_cluster_stake->activating;
     481        3963 :       double warmup_cooldown_rate_ =
     482        3963 :           warmup_cooldown_rate( current_epoch, new_rate_activation_epoch );
     483             : 
     484             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L782-L786
     485        3963 :       double newly_effective_cluster_stake =
     486        3963 :           (double)prev_cluster_stake->effective * warmup_cooldown_rate_;
     487        3963 :       ulong newly_effective_stake =
     488        3963 :           fd_ulong_max( fd_rust_cast_double_to_ulong( weight * newly_effective_cluster_stake ), 1 );
     489             : 
     490             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L787-L792
     491        3963 :       current_effective_stake += newly_effective_stake;
     492        3963 :       if( FD_LIKELY( current_effective_stake>=delegated_stake ) ) {
     493         204 :         current_effective_stake = delegated_stake;
     494         204 :         break;
     495         204 :       }
     496             : 
     497             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L793
     498        3759 :       if( FD_LIKELY( current_epoch>=target_epoch ||
     499        3759 :                      current_epoch>=self->deactivation_epoch ) ) { // FIXME always optimize loop break
     500         264 :         break;
     501         264 :       }
     502             : 
     503             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L796-L801
     504        3495 :       fd_stake_history_entry_t const * current_cluster_stake =
     505        3495 :           fd_stake_history_treap_ele_query_const( history->treap, current_epoch, history->pool );
     506        3495 :       if( FD_UNLIKELY( current_cluster_stake = fd_stake_history_treap_ele_query_const(
     507        3495 :                             history->treap, current_epoch, history->pool ) ) ) {
     508        3495 :         prev_epoch         = current_epoch;
     509        3495 :         prev_cluster_stake = current_cluster_stake;
     510        3495 :       } else {
     511             :         // FIXME always optimize loop break
     512           0 :         break;
     513           0 :       }
     514        3495 :     }
     515             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L804-L807
     516         588 :     return ( effective_activating_t ){ .effective  = current_effective_stake,
     517         588 :                                        .activating = delegated_stake - current_effective_stake };
     518        1467 :   } else {
     519             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L810
     520        1467 :     return ( effective_activating_t ){ .effective = delegated_stake, .activating = 0 };
     521        1467 :   }
     522        3342 : }
     523             : 
     524             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L641
     525             : static fd_stake_activation_status_t
     526             : stake_activating_and_deactivating( fd_delegation_t const *    self,
     527             :                                    ulong                      target_epoch,
     528             :                                    fd_stake_history_t const * stake_history,
     529        3342 :                                    ulong *                    new_rate_activation_epoch ) {
     530             : 
     531             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L648
     532        3342 :   effective_activating_t effective_activating =
     533        3342 :       stake_and_activating( self, target_epoch, stake_history, new_rate_activation_epoch );
     534             : 
     535        3342 :   ulong effective_stake  = effective_activating.effective;
     536        3342 :   ulong activating_stake = effective_activating.activating;
     537             : 
     538        3342 :   fd_stake_history_entry_t * cluster_stake_at_activation_epoch = NULL;
     539             : 
     540        3342 :   fd_stake_history_entry_t k;
     541        3342 :   k.epoch = self->deactivation_epoch;
     542             : 
     543             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/stake/state.rs#L652
     544        3342 :   if( target_epoch<self->deactivation_epoch ) {
     545             :     // if is bootstrap
     546        2292 :     if( activating_stake==0 ) {
     547        1566 :       return ( fd_stake_history_entry_t ){
     548        1566 :           .effective = effective_stake, .deactivating = 0, .activating = 0 };
     549        1566 :     } else {
     550         726 :       return ( fd_stake_history_entry_t ){
     551         726 :           .effective = effective_stake, .deactivating = 0, .activating = activating_stake };
     552         726 :     }
     553        2292 :   } else if( target_epoch==self->deactivation_epoch ) {
     554             :     // https://github.com/anza-xyz/agave/blob/be16321eb0db3e12a57a32f59febbf54b92ebb7c/sdk/program/src/stake/state.rs#L662
     555         318 :     return ( fd_stake_history_entry_t ){
     556         318 :         .effective = effective_stake, .deactivating = effective_stake, .activating = 0 };
     557         732 :   } else if( stake_history!=NULL ) {
     558             :     // https://github.com/anza-xyz/agave/blob/be16321eb0db3e12a57a32f59febbf54b92ebb7c/sdk/program/src/stake/state.rs#L665
     559         732 :     fd_stake_history_entry_t * n =
     560         732 :         fd_stake_history_treap_ele_query( stake_history->treap, k.epoch, stake_history->pool );
     561             : 
     562         732 :     if( NULL!=n ) { cluster_stake_at_activation_epoch = n; }
     563             : 
     564         732 :     if( cluster_stake_at_activation_epoch==NULL ) {
     565         483 :       fd_stake_history_entry_t entry = { .effective = 0, .activating = 0, .deactivating = 0 };
     566             : 
     567         483 :       return entry;
     568         483 :     }
     569         249 :     ulong                      prev_epoch         = self->deactivation_epoch;
     570         249 :     fd_stake_history_entry_t * prev_cluster_stake = cluster_stake_at_activation_epoch;
     571             : 
     572         249 :     ulong current_epoch;
     573         249 :     ulong current_effective_stake = effective_stake;
     574        1212 :     for( ;; ) {
     575        1212 :       current_epoch = prev_epoch + 1;
     576        1212 :       if( prev_cluster_stake->deactivating==0 ) break;
     577             : 
     578        1206 :       double weight = (double)current_effective_stake / (double)prev_cluster_stake->deactivating;
     579        1206 :       double warmup_cooldown_rate_ =
     580        1206 :           warmup_cooldown_rate( current_epoch, new_rate_activation_epoch );
     581             : 
     582             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L697-L700
     583        1206 :       double newly_not_effective_cluster_stake =
     584        1206 :           (double)prev_cluster_stake->effective * warmup_cooldown_rate_;
     585        1206 :       ulong newly_not_effective_stake =
     586        1206 :           fd_ulong_max( fd_rust_cast_double_to_ulong( weight * newly_not_effective_cluster_stake ), 1 );
     587             : 
     588        1206 :       current_effective_stake =
     589        1206 :           fd_ulong_sat_sub( current_effective_stake, newly_not_effective_stake );
     590        1206 :       if( current_effective_stake==0 ) break;
     591             : 
     592        1173 :       if( current_epoch>=target_epoch ) break;
     593             : 
     594             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L711-L713
     595         963 :       fd_stake_history_entry_t * current_cluster_stake = NULL;
     596         963 :       if( ( current_cluster_stake = fd_stake_history_treap_ele_query(
     597         963 :                  stake_history->treap, current_epoch, stake_history->pool ) ) ) {
     598         963 :         prev_epoch         = current_epoch;
     599         963 :         prev_cluster_stake = current_cluster_stake;
     600         963 :       } else {
     601           0 :         break;
     602           0 :       }
     603         963 :     }
     604             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L720
     605         249 :     return ( fd_stake_history_entry_t ){ .effective    = current_effective_stake,
     606         249 :                                          .deactivating = current_effective_stake,
     607         249 :                                          .activating   = 0 };
     608         732 :   } else {
     609             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L723C16-L723C17
     610           0 :     return ( fd_stake_history_entry_t ){ .effective = 0, .activating = 0, .deactivating = 0 };
     611           0 :   }
     612        3342 : }
     613             : 
     614             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L630
     615             : static inline ulong
     616             : delegation_stake( fd_delegation_t const *    self,
     617             :                   ulong                      epoch,
     618             :                   fd_stake_history_t const * history,
     619         444 :                   ulong *                    new_rate_activation_epoch ) {
     620         444 :   return stake_activating_and_deactivating( self, epoch, history, new_rate_activation_epoch )
     621         444 :       .effective;
     622         444 : }
     623             : 
     624             : /**********************************************************************/
     625             : /* mod tools                                                          */
     626             : /**********************************************************************/
     627             : 
     628             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/tools.rs#L44
     629             : static inline int
     630             : acceptable_reference_epoch_credits( fd_vote_epoch_credits_t * epoch_credits,
     631         681 :                                     ulong                     current_epoch ) {
     632         681 :   ulong len            = deq_fd_vote_epoch_credits_t_cnt( epoch_credits );
     633         681 :   ulong epoch_index[1] = { ULONG_MAX };
     634             :   // FIXME FD_LIKELY
     635         681 :   if( !__builtin_usubl_overflow( len, MINIMUM_DELINQUENT_EPOCHS_FOR_DEACTIVATION, epoch_index ) ) {
     636         558 :     ulong epoch = current_epoch;
     637        3057 :     for( ulong i = len - 1; i>=*epoch_index; i-- ) {
     638        2574 :       ulong vote_epoch = deq_fd_vote_epoch_credits_t_peek_index( epoch_credits, i )->epoch;
     639        2574 :       if( vote_epoch!=epoch ) { return 0; }
     640        2508 :       epoch = fd_ulong_sat_sub( epoch, 1 );
     641        2508 :       if( i==0 ) break;
     642        2508 :     }
     643         492 :     return 1;
     644         558 :   } else {
     645         123 :     return 0;
     646         123 :   };
     647           0 : }
     648             : 
     649             : /* https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/tools.rs#L67-L83 */
     650             : static inline int
     651         468 : eligible_for_deactivate_delinquent( fd_vote_epoch_credits_t * epoch_credits, ulong current_epoch ) {
     652         468 :   if( FD_LIKELY( deq_fd_vote_epoch_credits_t_empty( epoch_credits ) ) ) {
     653          30 :     return 1;
     654          30 :   }
     655             : 
     656         438 :   fd_vote_epoch_credits_t * last = deq_fd_vote_epoch_credits_t_peek_tail( epoch_credits );
     657         438 :   if( FD_LIKELY( !last ) ) {
     658           0 :     return 1;
     659         438 :   } else {
     660         438 :     ulong epoch         = last->epoch;
     661         438 :     ulong minimum_epoch = ULONG_MAX;
     662         438 :     int res = fd_ulong_checked_sub( current_epoch, MINIMUM_DELINQUENT_EPOCHS_FOR_DEACTIVATION, &minimum_epoch );
     663         438 :     if( FD_LIKELY( res==0 ) ) {
     664         438 :       return epoch<=minimum_epoch;
     665         438 :     } else {
     666           0 :       return 0;
     667           0 :     }
     668         438 :   }
     669         438 : }
     670             : 
     671             : /**********************************************************************/
     672             : /* impl StakeFlags                                                    */
     673             : /**********************************************************************/
     674             : 
     675             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/stake_flags.rs#L72
     676             : #define STAKE_FLAGS_MUST_FULLY_ACTIVATE_BEFORE_DEACTIVATION_IS_PERMITTED                           \
     677             :   ( ( fd_stake_flags_t ){ .bits = 1 } )
     678             : 
     679             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/stake_flags.rs#L75
     680         837 : #define STAKE_FLAGS_EMPTY ( ( fd_stake_flags_t ){ .bits = 0 } )
     681             : 
     682             : /**********************************************************************/
     683             : /* impl Stake                                                         */
     684             : /**********************************************************************/
     685             : 
     686             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L915
     687             : static int
     688             : stake_split( fd_stake_t * self,
     689             :              ulong        remaining_stake_delta,
     690             :              ulong        split_stake_amount,
     691             :              uint *       custom_err,
     692         543 :              fd_stake_t * out ) {
     693         543 :   if( FD_UNLIKELY( remaining_stake_delta>self->delegation.stake ) ) {
     694           0 :     *custom_err = FD_STAKE_ERR_INSUFFICIENT_STAKE;
     695           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     696           0 :   }
     697         543 :   self->delegation.stake -= remaining_stake_delta;
     698         543 :   fd_stake_t new;
     699         543 :   new                  = *self;
     700         543 :   new.delegation.stake = split_stake_amount;
     701         543 :   *out                 = new;
     702         543 :   return 0;
     703         543 : }
     704             : 
     705             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L934
     706             : static int
     707         432 : stake_deactivate( fd_stake_t * stake, ulong epoch, uint * custom_err ) {
     708         432 :   if( FD_UNLIKELY( stake->delegation.deactivation_epoch!=ULONG_MAX ) ) {
     709         219 :     *custom_err = FD_STAKE_ERR_ALREADY_DEACTIVATED;
     710         219 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     711         219 :   } else {
     712         213 :     stake->delegation.deactivation_epoch = epoch;
     713         213 :     return 0;
     714         213 :   }
     715         432 : }
     716             : 
     717             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L62
     718             : static inline int
     719             : new_warmup_cooldown_rate_epoch( fd_exec_instr_ctx_t const * invoke_context,
     720             :                                 /* out */ ulong *           epoch,
     721        3810 :                                 int *                       err ) {
     722        3810 :   *err = 0;
     723        3810 :   fd_epoch_schedule_t const * epoch_schedule = fd_sysvar_cache_epoch_schedule( invoke_context->slot_ctx->sysvar_cache );
     724        3810 :   if( FD_UNLIKELY( !epoch_schedule ) ) {
     725           0 :     *epoch = ULONG_MAX;
     726           0 :     *err   = FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     727           0 :     return 1;
     728           0 :   }
     729        3810 :   ulong slot = invoke_context->epoch_ctx->features.reduce_stake_warmup_cooldown;
     730        3810 :   *epoch     = fd_slot_to_epoch( epoch_schedule, slot, NULL );
     731        3810 :   return 1;
     732        3810 : }
     733             : 
     734             : /**********************************************************************/
     735             : /* util                                                               */
     736             : /**********************************************************************/
     737             : 
     738             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/state.rs#L205
     739             : FD_FN_CONST static inline ulong
     740           0 : stake_state_v2_size_of( void ) {
     741           0 :   return 200;
     742           0 : }
     743             : 
     744             : /**********************************************************************/
     745             : /* impl MergeKind                                                     */
     746             : /**********************************************************************/
     747             : 
     748             : static fd_stake_meta_t const *
     749        2484 : meta( merge_kind_t const * self ) {
     750        2484 :   switch( self->discriminant ) {
     751        1542 :   case merge_kind_inactive:
     752        1542 :     return &self->inner.inactive.meta;
     753         453 :   case merge_kind_activation_epoch:
     754         453 :     return &self->inner.activation_epoch.meta;
     755         489 :   case merge_kind_fully_active:
     756         489 :     return &self->inner.fully_active.meta;
     757           0 :   default:
     758           0 :     FD_LOG_ERR( ( "invalid merge_kind_t discriminant" ) );
     759        2484 :   }
     760        2484 : }
     761             : 
     762             : static fd_stake_t const *
     763         414 : active_stake( merge_kind_t const * self ) {
     764         414 :   switch( self->discriminant ) {
     765         222 :   case merge_kind_inactive:
     766         222 :     return NULL;
     767         117 :   case merge_kind_activation_epoch:
     768         117 :     return &self->inner.activation_epoch.stake;
     769          75 :   case merge_kind_fully_active:
     770          75 :     return &self->inner.fully_active.stake;
     771           0 :   default:
     772           0 :     FD_LOG_ERR( ( "invalid merge_kind_t discriminant" ) );
     773         414 :   }
     774         414 : }
     775             : 
     776             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1097
     777             : static int
     778             : get_if_mergeable( fd_exec_instr_ctx_t *         invoke_context, // not const to log
     779             :                   fd_stake_state_v2_t const *   stake_state,
     780             :                   ulong                         stake_lamports,
     781             :                   fd_sol_sysvar_clock_t const * clock,
     782             :                   fd_stake_history_t const *    stake_history,
     783             :                   merge_kind_t *                out,
     784        2535 :                   uint *                        custom_err ) {
     785             :   // stake_history must be non-NULL
     786             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1104
     787        2535 :   switch( stake_state->discriminant ) {
     788        1833 :   case fd_stake_state_v2_enum_stake: {
     789        1833 :     fd_stake_meta_t const *  meta        = &stake_state->inner.stake.meta;
     790        1833 :     fd_stake_t const *       stake       = &stake_state->inner.stake.stake;
     791        1833 :     fd_stake_flags_t const * stake_flags = &stake_state->inner.stake.stake_flags;
     792             : 
     793        1833 :     ulong new_rate_activation_epoch = ULONG_MAX;
     794        1833 :     int   err;
     795             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1111
     796        1833 :     int   is_some = new_warmup_cooldown_rate_epoch( invoke_context, &new_rate_activation_epoch, &err );
     797        1833 :     if( FD_UNLIKELY( err ) ) return err;
     798             : 
     799             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1108
     800        1833 :     fd_stake_history_entry_t status =
     801        1833 :         stake_activating_and_deactivating( &stake->delegation,
     802        1833 :                                            clock->epoch,
     803        1833 :                                            stake_history,
     804        1833 :                                            fd_ptr_if( is_some, &new_rate_activation_epoch, NULL ) );
     805             : 
     806             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1115
     807        1833 :     if( status.effective==0 && status.activating==0 && status.deactivating==0 ) {
     808             : 
     809         594 :       *out = ( merge_kind_t ){ .discriminant = merge_kind_inactive,
     810         594 :                                .inner        = { .inactive = { .meta         = *meta,
     811         594 :                                                                .active_stake = stake_lamports,
     812         594 :                                                                .stake_flags  = *stake_flags } } };
     813         594 :       return 0;
     814             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1116
     815        1239 :     } else if( status.effective==0 ) {
     816         342 :       *out = ( merge_kind_t ){ .discriminant = merge_kind_activation_epoch,
     817         342 :                                .inner        = { .activation_epoch = { .meta        = *meta,
     818         342 :                                                                        .stake       = *stake,
     819         342 :                                                                        .stake_flags = *stake_flags } } };
     820         342 :       return 0;
     821             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1117
     822         897 :     } else if( status.activating==0 && status.deactivating==0 ) {
     823         336 :       *out = ( merge_kind_t ){ .discriminant = merge_kind_fully_active,
     824         336 :                                .inner = { .fully_active = { .meta  = *meta, 
     825         336 :                                                             .stake = *stake } } };
     826         336 :       return 0;
     827         561 :     } else {
     828         561 :       fd_log_collector_msg_literal( invoke_context, "stake account with transient stake cannot be merged" );
     829         561 :       *custom_err = FD_STAKE_ERR_MERGE_TRANSIENT_STAKE;
     830         561 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     831         561 :     }
     832           0 :     break;
     833        1833 :   }
     834         552 :   case fd_stake_state_v2_enum_initialized: {
     835             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1126
     836         552 :     *out = ( merge_kind_t ){ .discriminant = merge_kind_inactive,
     837         552 :                              .inner        = { .inactive = { .meta         = stake_state->inner.initialized.meta,
     838         552 :                                                              .active_stake = stake_lamports,
     839         552 :                                                              .stake_flags  = STAKE_FLAGS_EMPTY} } };
     840         552 :     break;
     841        1833 :   }
     842         150 :   default:
     843             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1128
     844         150 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     845        2535 :   }
     846         552 :   return 0;
     847        2535 : }
     848             : 
     849             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1132
     850             : static int
     851             : metas_can_merge( fd_exec_instr_ctx_t *         invoke_context, // not const to log
     852             :                  fd_stake_meta_t const *       stake,
     853             :                  fd_stake_meta_t const *       source,
     854             :                  fd_sol_sysvar_clock_t const * clock,
     855         660 :                  uint *                        custom_err ) {
     856             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1139
     857         660 :   int  can_merge_lockups =
     858         660 :       ( !memcmp( &stake->lockup, &source->lockup, sizeof( fd_stake_lockup_t ) ) ) ||
     859         660 :       ( !lockup_is_in_force( &stake->lockup, clock, NULL ) &&
     860         327 :         !lockup_is_in_force( &source->lockup, clock, NULL ) );
     861             : 
     862             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1146
     863         660 :   if( FD_LIKELY( !memcmp( &stake->authorized, &source->authorized, sizeof( fd_stake_authorized_t ) ) && can_merge_lockups ) ) {
     864         378 :     return 0;
     865         378 :   } else {
     866         282 :     fd_log_collector_msg_literal( invoke_context, "Unable to merge due to metadata mismatch" );
     867         282 :     *custom_err = FD_STAKE_ERR_MERGE_MISMATCH;
     868         282 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     869         282 :   }
     870         660 : }
     871             : 
     872             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1154
     873             : static int
     874             : active_delegations_can_merge( fd_exec_instr_ctx_t *   invoke_context, // not const to log
     875             :                               fd_delegation_t const * stake,
     876             :                               fd_delegation_t const * source,
     877          51 :                               uint *                  custom_err ) {
     878          51 :   if( memcmp( &stake->voter_pubkey, &source->voter_pubkey, sizeof(fd_pubkey_t) ) ) {
     879           3 :     fd_log_collector_msg_literal( invoke_context, "Unable to merge due to voter mismatch" );
     880           3 :     *custom_err = FD_STAKE_ERR_MERGE_MISMATCH;
     881           3 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     882          48 :   } else if( FD_LIKELY( stake->deactivation_epoch==ULONG_MAX && source->deactivation_epoch==ULONG_MAX ) ) {
     883             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1162
     884          39 :     return 0;
     885          39 :   } else {
     886             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1167
     887           9 :     fd_log_collector_msg_literal( invoke_context, "Unable to merge due to stake deactivation" );
     888           9 :     *custom_err = FD_STAKE_ERR_MERGE_MISMATCH;
     889           9 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     890           9 :   }
     891          51 : }
     892             : 
     893             : static int
     894             : stake_weighted_credits_observed( fd_stake_t const * stake,
     895             :                                  ulong              absorbed_lamports,
     896             :                                  ulong              absorbed_credits_observed,
     897          60 :                                  ulong *            out ) {
     898             :   /* https://github.com/anza-xyz/agave/blob/dc74c22960b4f2adfc672f6dc3bfaa74ec1d5d48/programs/stake/src/stake_state.rs#L1194 */
     899          60 :   if( FD_LIKELY( stake->credits_observed==absorbed_credits_observed ) ) {
     900          39 :     *out = stake->credits_observed;
     901          39 :     return 1;
     902          39 :   } else {
     903             :     /* https://github.com/anza-xyz/agave/blob/dc74c22960b4f2adfc672f6dc3bfaa74ec1d5d48/programs/stake/src/stake_state.rs#L1197 */
     904             :     /* let total_stake = u128::from(stake.delegation.stake.checked_add(absorbed_lamports)?); */
     905          21 :     ulong total_stake;
     906             :     /* If there is an overflow on the ulong addition then exit */
     907          21 :     if( FD_UNLIKELY( fd_ulong_checked_add( stake->delegation.stake, absorbed_lamports, &total_stake ) ) ) {
     908           6 :       return 0;
     909           6 :     }
     910             : 
     911             :     /* https://github.com/anza-xyz/agave/blob/9489096dc5b7f0a61a981f3d0fd393d264896c2a/programs/stake/src/stake_state.rs#L1198 */
     912             :     /* The multiplication of two 64 bit integers will never overflow the 128 bits */
     913          15 :     ulong stake_weighted_credits_h;
     914          15 :     ulong stake_weighted_credits_l;
     915             :     /* let stake_weighted_credits = */
     916             :     /*     u128::from(stake.credits_observed).checked_mul(u128::from(stake.delegation.stake))?; */
     917          15 :     fd_uwide_mul( &stake_weighted_credits_h, &stake_weighted_credits_l,
     918          15 :                   stake->credits_observed, stake->delegation.stake );
     919             : 
     920             :     /* https://github.com/anza-xyz/agave/blob/9489096dc5b7f0a61a981f3d0fd393d264896c2a/programs/stake/src/stake_state.rs#L1200 */
     921             :     /* The multiplication of two 64 bit integers will never overflow the 128 bits */
     922          15 :     ulong absorbed_weighted_credits_h;
     923          15 :     ulong absorbed_weighted_credits_l;
     924             :     /* let absorbed_weighted_credits = */
     925             :     /*     u128::from(absorbed_credits_observed).checked_mul(u128::from(absorbed_lamports))?; */
     926          15 :     fd_uwide_mul( &absorbed_weighted_credits_h, &absorbed_weighted_credits_l,
     927          15 :                   absorbed_credits_observed, absorbed_lamports );
     928             : 
     929             :     /* https://github.com/anza-xyz/agave/blob/9489096dc5b7f0a61a981f3d0fd393d264896c2a/programs/stake/src/stake_state.rs#L1204 */
     930             :     /* let total_weighted_credits = stake_weighted_credits */
     931             :     /*     .checked_add(absorbed_weighted_credits)? */
     932             :     /*     .checked_add(total_stake)? */
     933             :     /*     .checked_sub(1)?; */
     934          15 :     ulong total_weighted_credits_partial_one_h;
     935          15 :     ulong total_weighted_credits_partial_one_l;
     936          15 :     ulong carry_out = fd_uwide_add( &total_weighted_credits_partial_one_h, &total_weighted_credits_partial_one_l,
     937          15 :                                     stake_weighted_credits_h, stake_weighted_credits_l,
     938          15 :                                     absorbed_weighted_credits_h, absorbed_weighted_credits_l, 0UL );
     939             :     /* return on overflow */
     940          15 :     if( FD_UNLIKELY( carry_out ) ) {
     941           0 :       return 0;
     942           0 :     }
     943             : 
     944          15 :     ulong total_weighted_credits_partial_two_h;
     945          15 :     ulong total_weighted_credits_partial_two_l;
     946          15 :     carry_out = fd_uwide_add( &total_weighted_credits_partial_two_h, &total_weighted_credits_partial_two_l,
     947          15 :                               total_weighted_credits_partial_one_h, total_weighted_credits_partial_one_l,
     948          15 :                               0UL, total_stake, 0UL );
     949             :     /* return on overflow */
     950          15 :     if( FD_UNLIKELY( carry_out ) ) {
     951           0 :       return 0;
     952           0 :     }
     953             : 
     954             :     /* The only way we can underflow the subtraction of 1 is if the value of total_weighted_credits_partial_two is zero */
     955          15 :     if( FD_UNLIKELY( total_weighted_credits_partial_two_h==0 && total_weighted_credits_partial_two_l==0 ) ) {
     956           0 :       return 0;
     957           0 :     }
     958          15 :     ulong total_weighted_credits_h;
     959          15 :     ulong total_weighted_credits_l;
     960          15 :     fd_uwide_dec( &total_weighted_credits_h, &total_weighted_credits_l,
     961          15 :                   total_weighted_credits_partial_two_h, total_weighted_credits_partial_two_l, 1UL );
     962             : 
     963             :     /* https://github.com/anza-xyz/agave/blob/8a1b2dc3fa4b85e26fbce0db06a462d4853b0652/programs/stake/src/stake_state.rs#L1208 */
     964             :     /* u64::try_from(total_weighted_credits.checked_div(total_stake)?).ok() */
     965          15 :     ulong res_h;
     966          15 :     ulong res_l;
     967          15 :     if( FD_UNLIKELY( fd_uwide_div( &res_h, &res_l, total_weighted_credits_h, total_weighted_credits_l, total_stake ) ) ) {
     968           0 :       return 0;
     969           0 :     }
     970          15 :     *out = res_l;
     971          15 :     return 1;
     972          15 :   }
     973          60 : }
     974             : 
     975             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1239
     976             : static int
     977             : merge_delegation_stake_and_credits_observed( FD_FN_UNUSED fd_exec_instr_ctx_t const * invoke_context,
     978             :                                              fd_stake_t *                stake,
     979             :                                              ulong                       absorbed_lamports,
     980          60 :                                              ulong absorbed_credits_observed ) {
     981          60 :   int rc;
     982          60 :   int  is_some = stake_weighted_credits_observed(
     983          60 :       stake, absorbed_lamports, absorbed_credits_observed, &stake->credits_observed );
     984          60 :   if( FD_UNLIKELY( !is_some ) ) return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
     985          54 :   rc = fd_ulong_checked_add( stake->delegation.stake, absorbed_lamports, &stake->delegation.stake );
     986          54 :   if( FD_UNLIKELY( rc ) ) return rc;
     987          51 :   return 0;
     988          54 : }
     989             : 
     990             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1171
     991             : static int
     992             : merge_kind_merge( merge_kind_t                  self,
     993             :                   fd_exec_instr_ctx_t *         invoke_context, // not const to log
     994             :                   merge_kind_t                  source,
     995             :                   fd_sol_sysvar_clock_t const * clock,
     996             :                   fd_stake_state_v2_t *         out,
     997             :                   int  *                        is_some,
     998         426 :                   uint *                        custom_err ) {
     999         426 :   int rc;
    1000             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1177
    1001         426 :   rc = metas_can_merge( invoke_context, meta( &self ), meta( &source ), clock, custom_err );
    1002         426 :   if( FD_UNLIKELY( rc ) ) return rc;
    1003             : 
    1004             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1178-L1188
    1005         207 :   fd_stake_t const * stake   = active_stake( &self );
    1006         207 :   fd_stake_t const * source_ = active_stake( &source );
    1007             : 
    1008             :   // FIXME FD_LIKELY
    1009         207 :   if( stake && source_ ) {
    1010          51 :     rc = active_delegations_can_merge(
    1011          51 :         invoke_context, &stake->delegation, &source_->delegation, custom_err );
    1012          51 :     if( FD_UNLIKELY( rc ) ) return rc;
    1013          51 :   }
    1014             : 
    1015             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1188
    1016             :   // FIXME FD_LIKELY
    1017         195 :   fd_stake_state_v2_t   merged_state_ = {0};
    1018         195 :   fd_stake_state_v2_t * merged_state  = &merged_state_;
    1019         195 :   if( self.discriminant==merge_kind_inactive && source.discriminant==merge_kind_inactive ) {
    1020             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1189
    1021          66 :     merged_state = NULL;
    1022         129 :   } else if( self.discriminant==merge_kind_inactive && source.discriminant==merge_kind_activation_epoch ) {
    1023             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1190
    1024          39 :     merged_state = NULL;
    1025          90 :   } else if( self.discriminant==merge_kind_activation_epoch && source.discriminant==merge_kind_inactive ) {
    1026          42 :     fd_stake_meta_t  meta               = self.inner.activation_epoch.meta;
    1027          42 :     fd_stake_t       stake              = self.inner.activation_epoch.stake;
    1028          42 :     fd_stake_flags_t stake_flags        = self.inner.activation_epoch.stake_flags;
    1029          42 :     ulong            source_lamports    = source.inner.inactive.active_stake;
    1030          42 :     fd_stake_flags_t source_stake_flags = source.inner.inactive.stake_flags;
    1031             : 
    1032             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1195
    1033          42 :     rc = fd_ulong_checked_add( stake.delegation.stake, source_lamports, &stake.delegation.stake );
    1034          42 :     if( FD_UNLIKELY( rc ) ) return rc;
    1035             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1196
    1036          39 :     *merged_state = ( fd_stake_state_v2_t ){
    1037          39 :         .discriminant = fd_stake_state_v2_enum_stake,
    1038          39 :         .inner        = { .stake = { .meta        = meta,
    1039          39 :                                      .stake       = stake,
    1040          39 :                                      .stake_flags = { .bits = stake_flags.bits | source_stake_flags.bits } } } };
    1041          48 :   } else if( self.discriminant==merge_kind_activation_epoch && source.discriminant==merge_kind_activation_epoch ) {
    1042             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1203
    1043          18 :     fd_stake_meta_t  meta               = self.inner.activation_epoch.meta;
    1044          18 :     fd_stake_t       stake              = self.inner.activation_epoch.stake;
    1045          18 :     fd_stake_flags_t stake_flags        = self.inner.activation_epoch.stake_flags;
    1046          18 :     fd_stake_meta_t  source_meta        = source.inner.activation_epoch.meta;
    1047          18 :     fd_stake_t       source_stake       = source.inner.activation_epoch.stake;
    1048          18 :     fd_stake_flags_t source_stake_flags = source.inner.activation_epoch.stake_flags;
    1049             : 
    1050             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1206
    1051          18 :     ulong source_lamports = ULONG_MAX;
    1052          18 :     rc = fd_ulong_checked_add( source_meta.rent_exempt_reserve, source_stake.delegation.stake, &source_lamports );
    1053          18 :     if( FD_UNLIKELY( rc ) ) return rc;
    1054             : 
    1055             :     // // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1210
    1056          18 :     rc = merge_delegation_stake_and_credits_observed(invoke_context, &stake, source_lamports, source_stake.credits_observed );
    1057          18 :     if( FD_UNLIKELY( rc ) ) return rc;
    1058             : 
    1059             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1215
    1060          18 :     *merged_state = ( fd_stake_state_v2_t ){
    1061          18 :         .discriminant = fd_stake_state_v2_enum_stake,
    1062          18 :         .inner        = { .stake = { .meta        = meta,
    1063          18 :                                      .stake       = stake,
    1064          18 :                                      .stake_flags = { .bits = stake_flags.bits | source_stake_flags.bits } } } };
    1065          30 :   } else if( self.discriminant==merge_kind_fully_active && source.discriminant==merge_kind_fully_active ) {
    1066             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1221
    1067          21 :     fd_stake_meta_t meta         = self.inner.fully_active.meta;
    1068          21 :     fd_stake_t      stake        = self.inner.fully_active.stake;
    1069          21 :     fd_stake_t      source_stake = source.inner.fully_active.stake;
    1070          21 :     rc                           = merge_delegation_stake_and_credits_observed(
    1071          21 :         invoke_context, &stake, source_stake.delegation.stake, source_stake.credits_observed );
    1072          21 :     if( FD_UNLIKELY( rc ) ) return rc;
    1073             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1231
    1074          12 :     *merged_state = ( fd_stake_state_v2_t ){
    1075          12 :         .discriminant = fd_stake_state_v2_enum_stake,
    1076          12 :         .inner = { .stake = { .meta = meta, .stake = stake, .stake_flags = STAKE_FLAGS_EMPTY } } };
    1077          12 :   } else {
    1078           9 :     *custom_err = FD_STAKE_ERR_MERGE_MISMATCH;
    1079           9 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1080           9 :   }
    1081         174 :   if( !merged_state ) {
    1082         105 :     *is_some = 0;
    1083         105 :     return 0;
    1084         105 :   }
    1085          69 :   *is_some = 1;
    1086          69 :   *out     = *merged_state;
    1087          69 :   return 0;
    1088         174 : }
    1089             : 
    1090             : /**********************************************************************/
    1091             : /* mod stake_state                                                    */
    1092             : /**********************************************************************/
    1093             : 
    1094             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L72
    1095             : static int
    1096             : get_stake_status( fd_exec_instr_ctx_t const *    invoke_context,
    1097             :                   fd_stake_t *                   stake,
    1098             :                   fd_sol_sysvar_clock_t const *  clock,
    1099        1071 :                   fd_stake_activation_status_t * out ) {
    1100        1071 :   fd_stake_history_t const * stake_history = fd_sysvar_cache_stake_history( invoke_context->slot_ctx->sysvar_cache );
    1101        1071 :   if( FD_UNLIKELY( !stake_history ) )
    1102           6 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1103        1065 :   ulong new_rate_activation_epoch = ULONG_MAX;
    1104        1065 :   int   err;
    1105        1065 :   int   is_some = new_warmup_cooldown_rate_epoch( invoke_context, &new_rate_activation_epoch, &err );
    1106        1065 :   if( FD_UNLIKELY( err ) ) return err;
    1107             : 
    1108        1065 :   *out =
    1109        1065 :       stake_activating_and_deactivating( &stake->delegation,
    1110        1065 :                                          clock->epoch,
    1111        1065 :                                          stake_history,
    1112        1065 :                                          fd_ptr_if( is_some, &new_rate_activation_epoch, NULL ) );
    1113        1065 :   return 0;
    1114        1065 : }
    1115             : 
    1116             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/vote/state/mod.rs#L740
    1117             : static ulong
    1118         333 : get_credits( fd_vote_state_t       const * vote_state ) {
    1119             : 
    1120         333 :     return ( deq_fd_vote_epoch_credits_t_empty( vote_state->epoch_credits )
    1121         333 :               ? 0
    1122         333 :               : deq_fd_vote_epoch_credits_t_peek_index(
    1123         102 :                     vote_state->epoch_credits,
    1124         102 :                     deq_fd_vote_epoch_credits_t_cnt( vote_state->epoch_credits ) - 1 )
    1125         102 :                     ->credits );
    1126         333 : }
    1127             : 
    1128             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L85
    1129             : static int
    1130             : redelegate_stake( fd_exec_instr_ctx_t const *   ctx,
    1131             :                   fd_stake_t *                  stake,
    1132             :                   ulong                         stake_lamports,
    1133             :                   fd_pubkey_t const *           voter_pubkey,
    1134             :                   fd_vote_state_t const *       vote_state,
    1135             :                   fd_sol_sysvar_clock_t const * clock,
    1136             :                   fd_stake_history_t const *    stake_history,
    1137         261 :                   uint *                        custom_err ) {
    1138         261 :   ulong new_rate_activation_epoch = ULONG_MAX;
    1139         261 :   int   err;
    1140         261 :   int   is_some = new_warmup_cooldown_rate_epoch( ctx, &new_rate_activation_epoch, &err );
    1141         261 :   if( FD_UNLIKELY( err ) ) return err;
    1142             : 
    1143             :   // FIXME FD_LIKELY
    1144             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L96
    1145         261 :   if( delegation_stake( &stake->delegation, clock->epoch, stake_history, fd_ptr_if( is_some, &new_rate_activation_epoch, NULL ) )!=0 ) {
    1146             : 
    1147         138 :     if( FD_LIKELY( !memcmp( &stake->delegation.voter_pubkey, voter_pubkey, sizeof( fd_pubkey_t ) ) ) &&
    1148         138 :          clock->epoch==stake->delegation.deactivation_epoch ) {
    1149          72 :       stake->delegation.deactivation_epoch = ULONG_MAX;
    1150          72 :       return 0;
    1151          72 :     } else {
    1152          66 :       *custom_err = FD_STAKE_ERR_TOO_SOON_TO_REDELEGATE;
    1153          66 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1154          66 :     }
    1155         138 :   }
    1156             : 
    1157             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L114-L118
    1158         123 :   stake->delegation.stake              = stake_lamports;
    1159         123 :   stake->delegation.activation_epoch   = clock->epoch;
    1160         123 :   stake->delegation.deactivation_epoch = ULONG_MAX;
    1161         123 :   stake->delegation.voter_pubkey       = *voter_pubkey;
    1162         123 :   stake->credits_observed              = get_credits( vote_state );
    1163         123 :   return 0;
    1164         261 : }
    1165             : 
    1166             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L202
    1167             : static fd_stake_t
    1168             : new_stake( ulong                   stake,
    1169             :            fd_pubkey_t const *     voter_pubkey,
    1170             :            fd_vote_state_t const * vote_state,
    1171         210 :            ulong                   activation_epoch ) {
    1172             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L208
    1173         210 :   return ( fd_stake_t ){
    1174         210 :       .delegation       = {.voter_pubkey         = *voter_pubkey,
    1175         210 :                            .stake                = stake,
    1176         210 :                            .activation_epoch     = activation_epoch,
    1177         210 :                            .deactivation_epoch   = ULONG_MAX,
    1178         210 :                            .warmup_cooldown_rate = DEFAULT_WARMUP_COOLDOWN_RATE},
    1179         210 :       .credits_observed = get_credits( vote_state ),
    1180         210 :   };
    1181         210 : }
    1182             : 
    1183             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L214
    1184             : static int
    1185             : initialize( fd_exec_instr_ctx_t const *   ctx,
    1186             :             fd_borrowed_account_t const * stake_account,
    1187             :             ulong                         stake_acc_idx,
    1188             :             fd_stake_authorized_t const * authorized,
    1189             :             fd_stake_lockup_t const *     lockup,
    1190         450 :             fd_rent_t const *             rent ) {
    1191             : 
    1192             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L220
    1193             : 
    1194         450 :   if( FD_UNLIKELY( stake_account->const_meta->dlen!=stake_state_v2_size_of() ) )
    1195         117 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1196             : 
    1197             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L224
    1198         333 :   fd_stake_state_v2_t stake_state = {0};
    1199         333 :   do {
    1200         333 :     int rc = get_state( stake_account, fd_scratch_virtual(), &stake_state );
    1201         333 :     if( FD_UNLIKELY( rc ) ) return rc;
    1202         333 :   } while(0);
    1203             : 
    1204         327 :   if( FD_LIKELY( stake_state.discriminant==fd_stake_state_v2_enum_uninitialized ) ) {
    1205             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L225
    1206         297 :     ulong rent_exempt_reserve = fd_rent_exempt_minimum_balance( rent, stake_account->const_meta->dlen );
    1207             : 
    1208             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L226
    1209         297 :     if( FD_LIKELY( stake_account->const_meta->info.lamports>=rent_exempt_reserve ) ) {
    1210         243 :       fd_stake_state_v2_t initialized = {
    1211         243 :         .discriminant = fd_stake_state_v2_enum_initialized,
    1212         243 :         .inner = { .initialized = { .meta = { .rent_exempt_reserve = rent_exempt_reserve,
    1213         243 :                                               .authorized          = *authorized,
    1214         243 :                                               .lockup              = *lockup } } } };
    1215         243 :       return set_state( ctx, stake_acc_idx, &initialized );
    1216         243 :     } else {
    1217             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L233
    1218          54 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1219          54 :     }
    1220             : 
    1221         297 :   } else {
    1222             : 
    1223             :     /// https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L236
    1224          30 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1225             : 
    1226          30 :   }
    1227         327 : }
    1228             : 
    1229             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L243
    1230             : static int
    1231             : authorize( fd_exec_instr_ctx_t const *   ctx,
    1232             :            fd_borrowed_account_t *       stake_account,
    1233             :            ulong                         stake_acc_idx,
    1234             :            fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1235             :            fd_pubkey_t const *           new_authority,
    1236             :            fd_stake_authorize_t const *  stake_authorize,
    1237             :            fd_sol_sysvar_clock_t const * clock,
    1238             :            fd_pubkey_t const *           custodian,
    1239         921 :            uint *                        custom_err ) {
    1240         921 :   int                 rc;
    1241         921 :   fd_stake_state_v2_t stake_state = {0};
    1242             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L251
    1243         921 :   rc = get_state( stake_account, fd_scratch_virtual(), &stake_state );
    1244         921 :   if( FD_UNLIKELY( rc ) ) return rc;
    1245         774 :   switch( stake_state.discriminant ) {
    1246             :   /* FIXME check if the compiler can optimize away branching (given the layout of `meta` in both
    1247             :    * union members) and instead fallthrough */
    1248         207 :   case fd_stake_state_v2_enum_stake: {
    1249             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L252
    1250         207 :     fd_stake_meta_t * meta = &stake_state.inner.stake.meta;
    1251             : 
    1252         207 :     fd_stake_lockup_custodian_args_t lockup_custodian_args = {
    1253         207 :         .lockup = meta->lockup, .clock = *clock, .custodian = (fd_pubkey_t *)custodian };
    1254         207 :     rc = authorized_authorize(
    1255         207 :         &meta->authorized, /* &mut self */
    1256         207 :         signers,
    1257         207 :         new_authority,
    1258         207 :         stake_authorize,
    1259         207 :         &lockup_custodian_args,
    1260         207 :         custom_err );
    1261         207 :     if( FD_UNLIKELY( rc ) ) return rc;
    1262             : 
    1263          51 :     return set_state( ctx, stake_acc_idx, &stake_state );
    1264         207 :   }
    1265         540 :   case fd_stake_state_v2_enum_initialized: {
    1266             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L261
    1267         540 :     fd_stake_meta_t * meta = &stake_state.inner.initialized.meta;
    1268             : 
    1269         540 :     fd_stake_lockup_custodian_args_t lockup_custodian_args = {
    1270         540 :         .lockup = meta->lockup, .clock = *clock, .custodian = (fd_pubkey_t *)custodian };
    1271         540 :     rc = authorized_authorize(
    1272         540 :         &meta->authorized,
    1273         540 :         signers,
    1274         540 :         new_authority,
    1275         540 :         stake_authorize,
    1276         540 :         &lockup_custodian_args,
    1277         540 :         custom_err );
    1278         540 :     if( FD_UNLIKELY( rc ) ) return rc;
    1279             : 
    1280         273 :     return set_state( ctx, stake_acc_idx, &stake_state );
    1281         540 :   }
    1282          27 :   default:
    1283             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L270
    1284          27 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1285         774 :   }
    1286           0 :   return rc;
    1287         774 : }
    1288             : 
    1289             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L275
    1290             : static int
    1291             : authorize_with_seed( fd_exec_instr_ctx_t const *   ctx,
    1292             :                      fd_borrowed_account_t *       stake_account,
    1293             :                      ulong                         stake_acc_idx,
    1294             :                      uchar                         authority_base_index,
    1295             :                      char const *                  authority_seed,
    1296             :                      ulong                         authority_seed_len,
    1297             :                      fd_pubkey_t const *           authority_owner,
    1298             :                      fd_pubkey_t const *           new_authority,
    1299             :                      fd_stake_authorize_t const *  stake_authorize,
    1300             :                      fd_sol_sysvar_clock_t const * clock,
    1301         429 :                      fd_pubkey_t const *           custodian ) {
    1302         429 :   int                 rc;
    1303         429 :   fd_pubkey_t const * signers[FD_TXN_SIG_MAX] = {0};
    1304         429 :   fd_pubkey_t         out                     = {0};
    1305         429 :   if( FD_LIKELY( fd_instr_acc_is_signer_idx( ctx->instr, authority_base_index ) ) ) {
    1306             : 
    1307             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L289
    1308         363 :     fd_pubkey_t const * base_pubkey = &ctx->instr->acct_pubkeys[authority_base_index];
    1309             : 
    1310             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L293
    1311         363 :     rc = fd_pubkey_create_with_seed( ctx,
    1312         363 :                                      base_pubkey->uc,
    1313         363 :                                      authority_seed,
    1314         363 :                                      authority_seed_len,
    1315         363 :                                      authority_owner->uc,
    1316         363 :                                      /* out */ out.uc );
    1317         363 :     if( FD_UNLIKELY( rc ) ) return rc;
    1318         216 :     signers[0] = &out;
    1319         216 :   }
    1320             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L299
    1321         282 :   return authorize( ctx,
    1322         282 :                     stake_account,
    1323         282 :                     stake_acc_idx,
    1324         282 :                     signers,
    1325         282 :                     new_authority,
    1326         282 :                     stake_authorize,
    1327         282 :                     clock,
    1328         282 :                     custodian,
    1329         282 :                     &ctx->txn_ctx->custom_err );
    1330         429 : }
    1331             : 
    1332             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L310
    1333             : static int
    1334             : delegate( fd_exec_instr_ctx_t const *   ctx,
    1335             :           uchar                         stake_account_index,
    1336             :           uchar                         vote_account_index,
    1337             :           fd_sol_sysvar_clock_t const * clock,
    1338             :           fd_stake_history_t const *    stake_history,
    1339        1272 :           fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX] ) {
    1340        1272 :   int rc;
    1341             : 
    1342        1272 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1343             : 
    1344        1272 :   fd_pubkey_t const * vote_pubkey;
    1345        1272 :   fd_vote_state_versioned_t vote_state = {0};
    1346        1272 :   int vote_get_state_rc;
    1347             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L321
    1348        5088 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, vote_account_index, vote_account ) {
    1349             : 
    1350             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L323
    1351        1272 :   if( FD_UNLIKELY( memcmp( &vote_account->const_meta->info.owner, fd_solana_vote_program_id.key, 32UL ) ) )
    1352          39 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    1353             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L3326
    1354        1233 :   vote_pubkey = vote_account->pubkey;
    1355             :   // https://github.com/anza-xyz/agave/blob/a60fbc2288d626a4f1846052c8fcb98d3f9ea58d/programs/stake/src/stake_state.rs#L327
    1356        1233 :   vote_get_state_rc = fd_vote_get_state( vote_account, scratch_valloc, &vote_state );
    1357             : 
    1358        1272 :   } FD_BORROWED_ACCOUNT_DROP( vote_account );
    1359             : 
    1360        1233 :   fd_stake_state_v2_t stake_state = {0};
    1361             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L330
    1362        4932 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account ) {
    1363             :   
    1364        1233 :   rc = get_state( stake_account, fd_scratch_virtual(), &stake_state );
    1365        1233 :   if( FD_UNLIKELY( rc ) ) return rc;
    1366             : 
    1367             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L332
    1368        1083 :   switch( stake_state.discriminant ) {
    1369         519 :   case fd_stake_state_v2_enum_initialized: {
    1370         519 :     fd_stake_meta_t meta = stake_state.inner.initialized.meta;
    1371             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L334
    1372         519 :     rc = authorized_check( &meta.authorized, signers, STAKE_AUTHORIZE_STAKER );
    1373         519 :     if( FD_UNLIKELY( rc ) ) return rc;
    1374             : 
    1375             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L335-L336
    1376         264 :     validated_delegated_info_t validated_delegated_info;
    1377         264 :     rc = validate_delegated_amount( stake_account,
    1378         264 :                                     &meta,
    1379         264 :                                     ctx->slot_ctx,
    1380         264 :                                     &validated_delegated_info,
    1381         264 :                                     &ctx->txn_ctx->custom_err );
    1382         264 :     if( FD_UNLIKELY( rc ) ) return rc;
    1383         213 :     ulong stake_amount = validated_delegated_info.stake_amount;
    1384             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L340
    1385         213 :     if( FD_UNLIKELY( vote_get_state_rc ) ) return vote_get_state_rc;
    1386         210 :     fd_vote_convert_to_current( &vote_state, scratch_valloc ); // FIXME
    1387         210 :     fd_stake_t stake =
    1388         210 :         new_stake( stake_amount, vote_pubkey, &vote_state.inner.current, clock->epoch );
    1389             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L343
    1390         210 :     fd_stake_state_v2_t new_stake_state = { .discriminant = fd_stake_state_v2_enum_stake,
    1391         210 :                                             .inner        = { .stake = {
    1392         210 :                                                                   .meta        = meta,
    1393         210 :                                                                   .stake       = stake,
    1394         210 :                                                                   .stake_flags = STAKE_FLAGS_EMPTY } } };
    1395         210 :     return set_state( ctx, stake_account_index, &new_stake_state );
    1396         213 :   }
    1397         540 :   case fd_stake_state_v2_enum_stake: {
    1398         540 :     fd_stake_meta_t  meta        = stake_state.inner.stake.meta;
    1399         540 :     fd_stake_t       stake       = stake_state.inner.stake.stake;
    1400         540 :     fd_stake_flags_t stake_flags = stake_state.inner.stake.stake_flags;
    1401             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L346
    1402         540 :     rc = authorized_check( &meta.authorized, signers, STAKE_AUTHORIZE_STAKER );
    1403         540 :     if( FD_UNLIKELY( rc ) ) return rc;
    1404             :     
    1405             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L347-L348
    1406         366 :     validated_delegated_info_t validated_delegated_info;
    1407         366 :     rc = validate_delegated_amount( stake_account,
    1408         366 :                                     &meta,
    1409         366 :                                     ctx->slot_ctx,
    1410         366 :                                     &validated_delegated_info,
    1411         366 :                                     &ctx->txn_ctx->custom_err );
    1412         366 :     if( FD_UNLIKELY( rc ) ) return rc;
    1413         267 :     ulong stake_amount = validated_delegated_info.stake_amount;
    1414             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L354
    1415         267 :     if( FD_UNLIKELY( vote_get_state_rc ) ) return vote_get_state_rc;
    1416         261 :     fd_vote_convert_to_current( &vote_state, scratch_valloc );
    1417             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L349
    1418         261 :     rc = redelegate_stake( ctx,
    1419         261 :                            &stake,
    1420         261 :                            stake_amount,
    1421         261 :                            vote_pubkey,
    1422         261 :                            &vote_state.inner.current,
    1423         261 :                            clock,
    1424         261 :                            stake_history,
    1425         261 :                            &ctx->txn_ctx->custom_err );
    1426         261 :     if( FD_UNLIKELY( rc ) ) return rc;
    1427             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L358
    1428         195 :     fd_stake_state_v2_t new_stake_state = { .discriminant = fd_stake_state_v2_enum_stake,
    1429         195 :                                             .inner        = { .stake = {
    1430         195 :                                                                   .meta        = meta,
    1431         195 :                                                                   .stake       = stake,
    1432         195 :                                                                   .stake_flags = stake_flags } } };
    1433             :      
    1434         195 :     return set_state( ctx, stake_account_index, &new_stake_state );
    1435         261 :   }
    1436          24 :   default:
    1437             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L360
    1438          24 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1439        1083 :   }
    1440        1233 :   } FD_BORROWED_ACCOUNT_DROP( stake_account );
    1441        1233 : }
    1442             : 
    1443             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L364
    1444             : static int
    1445             : deactivate( fd_exec_instr_ctx_t const *   ctx,
    1446             :             fd_borrowed_account_t *       stake_account,
    1447             :             ulong                         stake_acc_idx,
    1448             :             fd_sol_sysvar_clock_t const * clock,
    1449             :             fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1450         366 :             uint *                        custom_err ) {
    1451         366 :   int rc;
    1452             : 
    1453         366 :   fd_stake_state_v2_t state = {0};
    1454         366 :   rc                        = get_state( stake_account, fd_scratch_virtual(), &state );
    1455         366 :   if( FD_UNLIKELY( rc ) ) return rc;
    1456             : 
    1457             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L370
    1458         282 :   if( state.discriminant==fd_stake_state_v2_enum_stake ) {
    1459         213 :     fd_stake_meta_t * meta  = &state.inner.stake.meta;
    1460         213 :     fd_stake_t *      stake = &state.inner.stake.stake;
    1461             : 
    1462             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L371
    1463         213 :     rc = authorized_check( &meta->authorized, signers, STAKE_AUTHORIZE_STAKER );
    1464         213 :     if( FD_UNLIKELY( rc ) ) return rc;
    1465             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L372
    1466         168 :     rc = stake_deactivate( stake, clock->epoch, custom_err );
    1467         168 :     if( FD_UNLIKELY( rc ) ) return rc;
    1468             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L373
    1469         141 :     return set_state( ctx, stake_acc_idx, &state );
    1470         168 :   } else {
    1471             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L375
    1472          69 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1473          69 :   }
    1474         282 : }
    1475             : 
    1476             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L379
    1477             : static int
    1478             : set_lockup( fd_exec_instr_ctx_t const *   ctx,
    1479             :             fd_borrowed_account_t *       stake_account,
    1480             :             ulong                         stake_acc_idx,
    1481             :             fd_lockup_args_t const *      lockup,
    1482             :             fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1483         723 :             fd_sol_sysvar_clock_t const * clock ) {
    1484         723 :   int rc;
    1485             : 
    1486             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L385
    1487         723 :   fd_stake_state_v2_t state = {0};
    1488         723 :   rc = get_state( stake_account, fd_scratch_virtual(), &state );
    1489         723 :   if( FD_UNLIKELY( rc ) ) return rc;
    1490             : 
    1491         558 :   switch( state.discriminant ) {
    1492             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L386
    1493         222 :   case fd_stake_state_v2_enum_initialized: {
    1494         222 :     fd_stake_meta_t * meta = &state.inner.initialized.meta;
    1495         222 :     rc                     = set_lockup_meta( meta, lockup, signers, clock );
    1496         222 :     if( FD_UNLIKELY( rc ) ) return rc;
    1497          48 :     return set_state( ctx, stake_acc_idx, &state );
    1498         222 :   }
    1499             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L390
    1500         303 :   case fd_stake_state_v2_enum_stake: {
    1501         303 :     fd_stake_meta_t * meta = &state.inner.stake.meta;
    1502         303 :     rc                     = set_lockup_meta( meta, lockup, signers, clock );
    1503         303 :     if( FD_UNLIKELY( rc ) ) return rc;
    1504          69 :     return set_state( ctx, stake_acc_idx, &state );
    1505         303 :   }
    1506          33 :   default:
    1507             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L394
    1508          33 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1509         558 :   }
    1510         558 : }
    1511             : 
    1512             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L398
    1513             : static int
    1514             : split( fd_exec_instr_ctx_t const * ctx,
    1515             :        uchar                       stake_account_index,
    1516             :        ulong                       lamports,
    1517             :        uchar                       split_index,
    1518        2781 :        fd_pubkey_t const *         signers[static FD_TXN_SIG_MAX] ) {
    1519        2781 :   int rc;
    1520             : 
    1521        2781 :   ulong split_lamport_balance = 0;
    1522             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L407
    1523       11124 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, split_index, split ) {
    1524             : 
    1525             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L409
    1526        2781 :   if( FD_UNLIKELY( memcmp( &split->const_meta->info.owner, fd_solana_stake_program_id.key, 32UL ) ) )
    1527          81 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    1528             : 
    1529             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L412
    1530        2700 :   if( FD_UNLIKELY( split->const_meta->dlen!=stake_state_v2_size_of() ) )
    1531         336 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1532             : 
    1533             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L415
    1534        2364 :   fd_stake_state_v2_t split_get_state = {0};
    1535        2364 :   rc = get_state( split, fd_scratch_virtual(), &split_get_state );
    1536        2364 :   if( FD_UNLIKELY( rc ) ) return rc;
    1537        2361 :   if( FD_UNLIKELY( split_get_state.discriminant!=fd_stake_state_v2_enum_uninitialized ) ) {
    1538          75 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1539          75 :   }
    1540             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L418
    1541        2286 :   split_lamport_balance = split->const_meta->info.lamports;
    1542             : 
    1543        2781 :   } FD_BORROWED_ACCOUNT_DROP( split );
    1544             : 
    1545        2286 :   fd_stake_state_v2_t stake_state = {0};
    1546             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L420
    1547        9144 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account) {
    1548             :   
    1549             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L422
    1550        2286 :   if( FD_UNLIKELY( lamports>stake_account->const_meta->info.lamports ) )
    1551         351 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1552             :     
    1553        1935 :   rc = get_state( stake_account, fd_scratch_virtual(), &stake_state );
    1554        1935 :   if( FD_UNLIKELY( rc ) ) return rc;
    1555             : 
    1556        2286 :   } FD_BORROWED_ACCOUNT_DROP( stake_account );
    1557             : 
    1558             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L428
    1559        1893 :   switch( stake_state.discriminant ) {
    1560        1128 :   case fd_stake_state_v2_enum_stake: {
    1561        1128 :     fd_stake_meta_t *  meta        = &stake_state.inner.stake.meta;
    1562        1128 :     fd_stake_t *       stake       = &stake_state.inner.stake.stake;
    1563        1128 :     fd_stake_flags_t * stake_flags = &stake_state.inner.stake.stake_flags;
    1564             : 
    1565             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L430
    1566        1128 :     rc = authorized_check( &meta->authorized, signers, STAKE_AUTHORIZE_STAKER );
    1567        1128 :     if( FD_UNLIKELY( rc ) ) return rc;
    1568             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L431
    1569        1071 :     ulong minimum_delegation = get_minimum_delegation( ctx->slot_ctx );
    1570             :     
    1571        1071 :     int   is_active;
    1572        1071 :     if( FD_UNLIKELY( FD_FEATURE_ACTIVE( ctx->slot_ctx,
    1573        1071 :                                          require_rent_exempt_split_destination ) ) ) {
    1574             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L434
    1575        1071 :       fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    1576        1071 :       if( FD_UNLIKELY( !clock ) )
    1577           0 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1578             : 
    1579             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L435
    1580        1071 :       fd_stake_activation_status_t status = {0};
    1581        1071 :       rc = get_stake_status( ctx, stake, clock, &status );
    1582        1071 :       if( FD_UNLIKELY( rc ) ) return rc;
    1583             : 
    1584        1065 :       is_active = status.effective>0;
    1585        1065 :     } else {
    1586           0 :       is_active = 0;
    1587           0 :     }
    1588             : 
    1589             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L438
    1590        1065 :     validated_split_info_t validated_split_info = {0};
    1591        1065 :     rc = validate_split_amount( ctx,
    1592        1065 :                                 stake_account_index,
    1593        1065 :                                 split_index,
    1594        1065 :                                 lamports,
    1595        1065 :                                 meta,
    1596        1065 :                                 minimum_delegation,
    1597        1065 :                                 is_active,
    1598        1065 :                                 &validated_split_info );
    1599        1065 :     if( FD_UNLIKELY( rc ) ) return rc;
    1600             : 
    1601         606 :     ulong remaining_stake_delta;
    1602         606 :     ulong split_stake_amount;
    1603             :     // FIXME FD_LIKELY
    1604             :     
    1605         606 :     if( validated_split_info.source_remaining_balance==0 ) {
    1606             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L456
    1607         249 :       remaining_stake_delta = fd_ulong_sat_sub( lamports, meta->rent_exempt_reserve );
    1608         249 :       split_stake_amount    = remaining_stake_delta;
    1609         357 :     } else {
    1610             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L469
    1611         357 :       if( FD_UNLIKELY( fd_ulong_sat_sub( stake->delegation.stake, lamports ) <
    1612         357 :                         minimum_delegation ) ) {
    1613          36 :         ctx->txn_ctx->custom_err = FD_STAKE_ERR_INSUFFICIENT_DELEGATION;
    1614          36 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1615          36 :       }
    1616             : 
    1617         321 :       remaining_stake_delta = lamports;
    1618         321 :       split_stake_amount =
    1619         321 :           fd_ulong_sat_sub( lamports,
    1620         321 :                             fd_ulong_sat_sub( validated_split_info.destination_rent_exempt_reserve,
    1621         321 :                                               split_lamport_balance )
    1622             : 
    1623         321 :           );
    1624         321 :     }
    1625             : 
    1626             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L487
    1627         570 :     if( FD_UNLIKELY( split_stake_amount<minimum_delegation ) ) {
    1628          27 :       ctx->txn_ctx->custom_err = FD_STAKE_ERR_INSUFFICIENT_DELEGATION;
    1629          27 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1630          27 :     }
    1631             : 
    1632             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L491-L493
    1633         543 :     fd_stake_t split_stake = {0};
    1634         543 :     rc = stake_split( stake,
    1635         543 :                       remaining_stake_delta,
    1636         543 :                       split_stake_amount,
    1637         543 :                       &ctx->txn_ctx->custom_err,
    1638         543 :                       &split_stake );
    1639         543 :     if( FD_UNLIKELY( rc ) ) return rc;
    1640         543 :     fd_stake_meta_t split_meta     = *meta;
    1641         543 :     split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
    1642             : 
    1643             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L495
    1644        2172 :     FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account ) {
    1645             : 
    1646             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L497
    1647         543 :     rc = set_state( ctx, stake_account_index, &stake_state );
    1648         543 :     if( FD_UNLIKELY( rc ) ) return rc;
    1649             : 
    1650         543 :     } FD_BORROWED_ACCOUNT_DROP( stake_account );
    1651             : 
    1652             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L499
    1653        2124 :     FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, split_index, split ) {
    1654             : 
    1655             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L501
    1656         531 :     fd_stake_state_v2_t temp = { .discriminant = fd_stake_state_v2_enum_stake,
    1657         531 :                                  .inner        = { .stake = { .meta        = split_meta,
    1658         531 :                                                               .stake       = split_stake,
    1659         531 :                                                               .stake_flags = *stake_flags } } };
    1660         531 :     rc = set_state( ctx, split_index, &temp );
    1661         531 :     if( FD_UNLIKELY( rc ) ) return rc;
    1662             : 
    1663         531 :     } FD_BORROWED_ACCOUNT_DROP( split );
    1664         522 :     break;
    1665         531 :   }
    1666         540 :   case fd_stake_state_v2_enum_initialized: {
    1667             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L504
    1668         540 :     fd_stake_meta_t * meta = &stake_state.inner.initialized.meta;
    1669         540 :     rc                     = authorized_check( &meta->authorized, signers, STAKE_AUTHORIZE_STAKER );
    1670         540 :     if( FD_UNLIKELY( rc ) ) return rc;
    1671             : 
    1672             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L505
    1673         465 :     validated_split_info_t validated_split_info = {0};
    1674         465 :     rc = validate_split_amount( ctx,
    1675         465 :                                 stake_account_index,
    1676         465 :                                 split_index,
    1677         465 :                                 lamports,
    1678         465 :                                 meta,
    1679         465 :                                 0,
    1680         465 :                                 0,
    1681         465 :                                 &validated_split_info );
    1682         465 :     if( FD_UNLIKELY( rc ) ) return rc;
    1683             : 
    1684             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L516
    1685         318 :     fd_stake_meta_t split_meta     = *meta;
    1686         318 :     split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
    1687             : 
    1688             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L518
    1689        1272 :     FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, split_index, split ) {
    1690             :     
    1691             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L520
    1692         318 :     fd_stake_state_v2_t temp = { .discriminant = fd_stake_state_v2_enum_initialized,
    1693         318 :                                  .inner        = { .initialized = { .meta = split_meta } } };
    1694         318 :     rc = set_state( ctx, split_index, &temp );
    1695         318 :     if( FD_UNLIKELY( rc ) ) return rc;
    1696             : 
    1697         318 :     } FD_BORROWED_ACCOUNT_DROP( split );
    1698         315 :     break;
    1699         318 :   }
    1700         315 :   case fd_stake_state_v2_enum_uninitialized: {
    1701             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L523
    1702         222 :     fd_pubkey_t const * stake_pubkey = &ctx->instr->acct_pubkeys[stake_account_index];
    1703         222 :     if( FD_UNLIKELY( !fd_instr_signers_contains( signers, stake_pubkey ) ) ) {
    1704             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L527
    1705          69 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1706          69 :     }
    1707         153 :     break;
    1708         222 :   }
    1709         153 :   default:
    1710             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L531
    1711           3 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1712        1893 :   }
    1713             : 
    1714             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L535
    1715        3960 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account ) {
    1716             : 
    1717             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L537
    1718         990 :   if( FD_UNLIKELY( lamports==stake_account->const_meta->info.lamports ) ) {
    1719         411 :     fd_stake_state_v2_t uninitialized = {0};
    1720         411 :     uninitialized.discriminant        = fd_stake_state_v2_enum_uninitialized;
    1721         411 :     rc                                = set_state( ctx, stake_account_index, &uninitialized );
    1722         411 :     if( FD_UNLIKELY( rc ) ) return rc;
    1723         987 :   };
    1724             : 
    1725         990 :   } FD_BORROWED_ACCOUNT_DROP( stake_account );
    1726             : 
    1727             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L542
    1728        3948 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, split_index, split ) {
    1729             :   
    1730             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L544
    1731         987 :   rc = fd_account_checked_add_lamports( ctx, split_index, lamports );
    1732         987 :   if( FD_UNLIKELY( rc ) ) return rc;
    1733             : 
    1734             : 
    1735         987 :   } FD_BORROWED_ACCOUNT_DROP( split );
    1736             : 
    1737             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L546
    1738        3804 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account ) {
    1739             : 
    1740             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L548
    1741         951 :   rc = fd_account_checked_sub_lamports( ctx, stake_account_index, lamports );
    1742         951 :   if( FD_UNLIKELY( rc ) ) return rc;
    1743             : 
    1744         951 :   } FD_BORROWED_ACCOUNT_DROP( stake_account );
    1745         939 :   return 0;
    1746         951 : }
    1747             : 
    1748             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L552
    1749             : static int
    1750             : merge( fd_exec_instr_ctx_t *         ctx, // not const to log
    1751             :        uchar                         stake_account_index,
    1752             :        uchar                         source_account_index,
    1753             :        fd_sol_sysvar_clock_t const * clock,
    1754             :        fd_stake_history_t const *    stake_history,
    1755        1635 :        fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX] ) {
    1756        1635 :   int rc;
    1757             : 
    1758             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L562
    1759        6540 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, source_account_index, source_account  ) {
    1760             : 
    1761             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L565
    1762        1635 :   if( FD_UNLIKELY( memcmp( &source_account->const_meta->info.owner, fd_solana_stake_program_id.key, 32UL ) ) )
    1763          42 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    1764             : 
    1765             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L569
    1766        1593 :   if( FD_UNLIKELY( !memcmp( &ctx->instr->acct_pubkeys[stake_account_index], &ctx->instr->acct_pubkeys[source_account_index], sizeof(fd_pubkey_t) ) ) )
    1767          24 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1768             : 
    1769             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L575
    1770        6276 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account  ) {
    1771             : 
    1772        1569 :   fd_stake_state_v2_t stake_account_state = {0};
    1773        1569 :   rc = get_state( stake_account, fd_scratch_virtual(), &stake_account_state );
    1774        1569 :   if( FD_UNLIKELY( rc ) ) return rc;
    1775             : 
    1776        1479 :   merge_kind_t stake_merge_kind = {0};
    1777        1479 :   fd_log_collector_msg_literal( ctx, "Checking if destination stake is mergeable" );
    1778             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L579
    1779        1479 :   rc = get_if_mergeable( ctx,
    1780        1479 :                          &stake_account_state,
    1781        1479 :                          stake_account->const_meta->info.lamports,
    1782        1479 :                          clock,
    1783        1479 :                          stake_history,
    1784        1479 :                          &stake_merge_kind,
    1785        1479 :                          &ctx->txn_ctx->custom_err );
    1786        1479 :   if( FD_UNLIKELY( rc ) )
    1787         579 :     return rc;
    1788             : 
    1789             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L588
    1790         900 :   rc = authorized_check( &meta( &stake_merge_kind )->authorized, signers, STAKE_AUTHORIZE_STAKER );
    1791         900 :   if( FD_UNLIKELY( rc ) )
    1792         327 :     return rc;
    1793             : 
    1794         573 :   fd_stake_state_v2_t source_account_state = {0};
    1795         573 :   rc = get_state( source_account, fd_scratch_virtual(), &source_account_state );
    1796         573 :   if( FD_UNLIKELY( rc ) ) return rc;
    1797             : 
    1798         543 :   merge_kind_t source_merge_kind = {0};
    1799         543 :   fd_log_collector_msg_literal( ctx, "Checking if source stake is mergeable" );
    1800             :   //https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L594
    1801         543 :   rc = get_if_mergeable( ctx,
    1802         543 :                          &source_account_state,
    1803         543 :                          source_account->const_meta->info.lamports,
    1804         543 :                          clock,
    1805         543 :                          stake_history,
    1806         543 :                          &source_merge_kind,
    1807         543 :                          &ctx->txn_ctx->custom_err );
    1808         543 :   if( FD_UNLIKELY( rc ) ) return rc;
    1809             : 
    1810         426 :   fd_stake_state_v2_t merged_state = {0};
    1811         426 :   int                 is_some      = 0;
    1812         426 :   fd_log_collector_msg_literal( ctx, "Merging stake accounts" );
    1813             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L603
    1814         426 :   rc = merge_kind_merge( stake_merge_kind,
    1815         426 :                          ctx,
    1816         426 :                          source_merge_kind,
    1817         426 :                          clock,
    1818         426 :                          &merged_state,
    1819         426 :                          &is_some,
    1820         426 :                          &ctx->txn_ctx->custom_err );
    1821         426 :   if( FD_UNLIKELY( rc ) ) return rc;
    1822         174 :   if( is_some ) {
    1823             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L608
    1824          69 :     rc = set_state( ctx, stake_account_index, &merged_state );
    1825          69 :     if( FD_UNLIKELY( rc ) ) return rc;
    1826          69 :   }
    1827             : 
    1828             :   //  https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L608
    1829         171 :   fd_stake_state_v2_t uninitialized = {0};
    1830         171 :   uninitialized.discriminant        = fd_stake_state_v2_enum_uninitialized;
    1831         171 :   rc                                = set_state( ctx, source_account_index, &uninitialized );
    1832         171 :   if( FD_UNLIKELY( rc ) ) return rc;
    1833             : 
    1834             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L611-L613
    1835         141 :   ulong lamports = source_account->const_meta->info.lamports;
    1836         141 :   rc = fd_account_checked_sub_lamports( ctx, source_account_index, lamports );
    1837         141 :   if( FD_UNLIKELY( rc ) ) return rc;
    1838         141 :   rc = fd_account_checked_add_lamports( ctx, stake_account_index, lamports );
    1839         141 :   if( FD_UNLIKELY( rc ) ) return rc;
    1840             : 
    1841        1569 :   } FD_BORROWED_ACCOUNT_DROP( stake_account );
    1842        1635 :   } FD_BORROWED_ACCOUNT_DROP( source_account );
    1843             : 
    1844         135 :   return 0;
    1845        1635 : }
    1846             : 
    1847             : // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L136
    1848             : static int 
    1849             : move_stake_or_lamports_shared_checks( fd_exec_instr_ctx_t *   invoke_context, // not const to log
    1850             :                                       fd_borrowed_account_t * source_account,
    1851             :                                       ulong                   lamports,
    1852             :                                       fd_borrowed_account_t * destination_account,
    1853             :                                       ulong                   stake_authority_index,
    1854             :                                       merge_kind_t *          source_merge_kind,
    1855             :                                       merge_kind_t *          destination_merge_kind,
    1856         768 :                                       uint *                  custom_err ) {
    1857         768 :     int rc;
    1858             : 
    1859             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L145-L153
    1860         768 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( invoke_context->instr, stake_authority_index ) ) ) { 
    1861         300 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1862         300 :     }
    1863             : 
    1864         468 :     fd_pubkey_t const * stake_authority_pubkey = &invoke_context->instr->acct_pubkeys[stake_authority_index];
    1865         468 :     fd_pubkey_t const * signers[FD_TXN_SIG_MAX] = { stake_authority_pubkey };
    1866             : 
    1867             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L158
    1868         468 :     if( FD_UNLIKELY( memcmp( &source_account->const_meta->info.owner, fd_solana_stake_program_id.key, sizeof(fd_pubkey_t) ) ||
    1869         468 :                      memcmp( &destination_account->const_meta->info.owner, fd_solana_stake_program_id.key, sizeof(fd_pubkey_t) ) ) )
    1870           9 :       return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    1871             : 
    1872             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L163
    1873         459 :     if( FD_UNLIKELY( !memcmp( &source_account->pubkey, &destination_account->pubkey, sizeof(fd_pubkey_t) ) ) )
    1874           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1875             : 
    1876             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L168
    1877         459 :     if( FD_UNLIKELY( !fd_instr_acc_is_writable( invoke_context->instr, source_account->pubkey ) ||
    1878         459 :                      !fd_instr_acc_is_writable( invoke_context->instr, destination_account->pubkey ) ) )
    1879         174 :         return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1880             : 
    1881             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L173
    1882         285 :     if( lamports==0 )
    1883           3 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1884             :     
    1885             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L177-L180
    1886         282 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( invoke_context->slot_ctx->sysvar_cache );
    1887         282 :     if( FD_UNLIKELY( !clock ) )
    1888           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1889             : 
    1890         282 :     fd_stake_history_t const * stake_history = fd_sysvar_cache_stake_history( invoke_context->slot_ctx->sysvar_cache );
    1891         282 :     if( FD_UNLIKELY( !stake_history ) )
    1892           3 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1893             : 
    1894             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L182
    1895         279 :     fd_stake_state_v2_t source_account_state = {0};
    1896         279 :     rc = get_state( source_account, fd_scratch_virtual(), &source_account_state );
    1897         279 :     if( FD_UNLIKELY( rc ) ) return rc;
    1898             : 
    1899         267 :     rc = get_if_mergeable( invoke_context,
    1900         267 :                          &source_account_state,
    1901         267 :                          source_account->const_meta->info.lamports,
    1902         267 :                          clock,
    1903         267 :                          stake_history,
    1904         267 :                          source_merge_kind,
    1905         267 :                          &invoke_context->txn_ctx->custom_err );
    1906         267 :     if( FD_UNLIKELY( rc ) ) return rc;
    1907             : 
    1908             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L191
    1909         264 :     rc = authorized_check( &meta( source_merge_kind )->authorized, signers, STAKE_AUTHORIZE_STAKER );
    1910         264 :     if( FD_UNLIKELY( rc ) ) return rc;
    1911             : 
    1912             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L197
    1913         261 :     fd_stake_state_v2_t destination_account_state = {0};
    1914         261 :     rc = get_state( destination_account, fd_scratch_virtual(), &destination_account_state );
    1915         261 :     if( FD_UNLIKELY( rc ) ) return rc;
    1916             : 
    1917         246 :     rc = get_if_mergeable( invoke_context,
    1918         246 :                          &destination_account_state,
    1919         246 :                          destination_account->const_meta->info.lamports,
    1920         246 :                          clock,
    1921         246 :                          stake_history,
    1922         246 :                          destination_merge_kind,
    1923         246 :                          &invoke_context->txn_ctx->custom_err );
    1924         246 :     if( FD_UNLIKELY( rc ) ) return rc;
    1925             :     
    1926             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L206
    1927         234 :     rc = metas_can_merge( invoke_context, meta( source_merge_kind ), meta( destination_merge_kind ), clock, custom_err );
    1928         234 :     if( FD_UNLIKELY( rc ) ) return rc;
    1929             : 
    1930         171 :   return 0;
    1931         234 : }
    1932             : 
    1933             : // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L789
    1934             : static int
    1935             : move_stake(fd_exec_instr_ctx_t * ctx, // not const to log
    1936             :            ulong                 source_account_index,
    1937             :            ulong                 lamports,
    1938             :            ulong                 destination_account_index,
    1939             :            ulong                 stake_authority_index,
    1940         477 :            uint *                custom_err ) {
    1941         477 :   int rc;
    1942             : 
    1943             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L798-L804
    1944        1908 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, source_account_index, source_account ) {
    1945        1908 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, destination_account_index, destination_account ) {
    1946             :   
    1947             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L804
    1948         477 :   merge_kind_t source_merge_kind = {0};
    1949         477 :   merge_kind_t destination_merge_kind = {0};
    1950         477 :   rc = move_stake_or_lamports_shared_checks( ctx,
    1951         477 :                                              source_account,
    1952         477 :                                              lamports,
    1953         477 :                                              destination_account,
    1954         477 :                                              stake_authority_index,
    1955         477 :                                              &source_merge_kind,
    1956         477 :                                              &destination_merge_kind,
    1957         477 :                                              &ctx->txn_ctx->custom_err );
    1958         477 :   if( FD_UNLIKELY( rc ) ) return rc;
    1959             : 
    1960             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L816
    1961          72 :   if( FD_UNLIKELY( source_account->const_meta->dlen!=stake_state_v2_size_of() ||
    1962          72 :                    destination_account->const_meta->dlen!=stake_state_v2_size_of() ) )
    1963           6 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1964             : 
    1965             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L823
    1966          66 :   if( source_merge_kind.discriminant!=merge_kind_fully_active )
    1967           6 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1968          60 :   fd_stake_meta_t * source_meta = &source_merge_kind.inner.fully_active.meta;
    1969          60 :   fd_stake_t * source_stake = &source_merge_kind.inner.fully_active.stake;
    1970             : 
    1971             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L827
    1972          60 :   ulong minimum_delegation = get_minimum_delegation( ctx->slot_ctx );  
    1973             : 
    1974             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L831
    1975          60 :   if( FD_UNLIKELY( source_stake->delegation.stake<lamports ) )
    1976           3 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1977             : 
    1978          57 :   ulong source_final_stake = source_stake->delegation.stake - lamports;
    1979             : 
    1980             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L836 
    1981          57 :   if( FD_UNLIKELY( source_final_stake!=0 && source_final_stake<minimum_delegation ) )
    1982           3 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1983             :   
    1984             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L841
    1985          54 :   fd_stake_meta_t * destination_meta = NULL;
    1986          54 :   switch( destination_merge_kind.discriminant ) {
    1987          27 :   case merge_kind_fully_active: {
    1988          27 :     fd_stake_t * destination_stake = &destination_merge_kind.inner.fully_active.stake;
    1989             : 
    1990             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L844
    1991          27 :     if( FD_UNLIKELY( memcmp( &source_stake->delegation.voter_pubkey, &destination_stake->delegation.voter_pubkey, sizeof(fd_pubkey_t) ) ) ) {
    1992           3 :       *custom_err = FD_STAKE_ERR_VOTE_ADDRESS_MISMATCH;
    1993           3 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1994           3 :     }
    1995             : 
    1996             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L848
    1997          24 :     ulong destination_effective_stake = 0;
    1998          24 :     rc = fd_ulong_checked_add( destination_stake->delegation.stake, lamports, &destination_effective_stake );
    1999          24 :     if( FD_UNLIKELY( rc ) ) return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
    2000             : 
    2001             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L855
    2002          21 :     if( FD_UNLIKELY( destination_effective_stake<minimum_delegation ) ) {
    2003           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2004           0 :     }
    2005             : 
    2006             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L859
    2007          21 :     rc = merge_delegation_stake_and_credits_observed(
    2008          21 :       ctx, destination_stake, lamports, source_stake->credits_observed );
    2009          21 :     if( FD_UNLIKELY( rc ) ) return rc;
    2010          21 :     destination_meta = &destination_merge_kind.inner.fully_active.meta;
    2011             : 
    2012             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L867
    2013          21 :     fd_stake_state_v2_t new_destination_state = {
    2014          21 :       .discriminant = fd_stake_state_v2_enum_stake,
    2015          21 :       .inner        = { .stake = {
    2016          21 :                             .meta        = *destination_meta,
    2017          21 :                             .stake       = *destination_stake,
    2018          21 :                             .stake_flags = STAKE_FLAGS_EMPTY} } };
    2019          21 :     rc = set_state( ctx, destination_account_index, &new_destination_state );
    2020          21 :     if( FD_UNLIKELY( rc ) ) return rc;
    2021             :   
    2022          18 :     break;
    2023          21 :   }
    2024          24 :   case merge_kind_inactive: {
    2025             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L877
    2026          24 :     if( lamports<minimum_delegation ) {
    2027           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2028           0 :     }
    2029             : 
    2030             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L881
    2031          24 :     fd_stake_t * destination_stake = source_stake;
    2032          24 :     destination_stake->delegation.stake = lamports;
    2033             : 
    2034          24 :     destination_meta = &destination_merge_kind.inner.inactive.meta;
    2035             : 
    2036             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L886
    2037          24 :     fd_stake_state_v2_t new_destination_state = {
    2038          24 :       .discriminant = fd_stake_state_v2_enum_stake,
    2039          24 :       .inner        = { .stake = {
    2040          24 :                             .meta        = *destination_meta,
    2041          24 :                             .stake       = *destination_stake,
    2042          24 :                             .stake_flags = STAKE_FLAGS_EMPTY} } };
    2043          24 :     rc = set_state( ctx, destination_account_index, &new_destination_state );
    2044          24 :     if( FD_UNLIKELY( rc ) ) return rc;
    2045          21 :     break;
    2046          24 :   }
    2047          21 :   default:
    2048             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L894
    2049           3 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    2050          54 :   }
    2051             : 
    2052             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L897-L910
    2053          39 :   if( source_final_stake==0) {
    2054          21 :     fd_stake_state_v2_t new_source_state = { .discriminant = fd_stake_state_v2_enum_initialized,
    2055          21 :                                  .inner        = { .initialized = { .meta =  *source_meta} } };
    2056          21 :     rc = set_state( ctx, source_account_index, &new_source_state );
    2057          21 :     if( FD_UNLIKELY( rc ) ) return rc;
    2058             :     
    2059          21 :   } else {
    2060          18 :     source_stake->delegation.stake = source_final_stake;
    2061             :   
    2062          18 :     fd_stake_state_v2_t new_source_state = { .discriminant = fd_stake_state_v2_enum_stake,
    2063          18 :                                .inner        = { .stake = { .meta = *source_meta,
    2064          18 :                                                             .stake = *source_stake,
    2065          18 :                                                             .stake_flags = STAKE_FLAGS_EMPTY } } };
    2066          18 :     rc = set_state( ctx, source_account_index, &new_source_state );
    2067          18 :     if( FD_UNLIKELY( rc ) ) return rc;
    2068          18 :   }
    2069             : 
    2070             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L911-L914
    2071          33 :   rc = fd_account_checked_sub_lamports( ctx, source_account_index, lamports );
    2072          33 :   if( FD_UNLIKELY( rc ) ) return rc;
    2073          30 :   rc = fd_account_checked_add_lamports( ctx, destination_account_index, lamports );
    2074          30 :   if( FD_UNLIKELY( rc ) ) return rc;
    2075             : 
    2076             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L915-L923
    2077          18 :   if( FD_UNLIKELY( fd_account_get_lamports2( ctx, source_account_index )<source_meta->rent_exempt_reserve ) ||
    2078          18 :                    fd_account_get_lamports2( ctx, destination_account_index )<destination_meta->rent_exempt_reserve ) {
    2079          12 :     fd_log_collector_msg_literal( ctx, "Delegation calculations violated lamport balance assumptions" );
    2080          12 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;                 
    2081          12 :   }
    2082             : 
    2083         477 :   } FD_BORROWED_ACCOUNT_DROP( destination_account );
    2084         477 :   } FD_BORROWED_ACCOUNT_DROP( source_account );
    2085             : 
    2086           6 :   return FD_EXECUTOR_INSTR_SUCCESS;
    2087         477 : }
    2088             : 
    2089             : // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L928
    2090             : static int
    2091             : move_lamports(fd_exec_instr_ctx_t * ctx, // not const to log
    2092             :               ulong                 source_account_index,
    2093             :               ulong                 lamports,
    2094             :               ulong                 destination_account_index,
    2095         291 :               ulong                 stake_authority_index ) {
    2096         291 :   int rc;
    2097             : 
    2098             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L937-L942
    2099        1164 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, source_account_index, source_account ) {
    2100        1164 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, destination_account_index, destination_account ) {
    2101             : 
    2102             : 
    2103             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L943
    2104         291 :   merge_kind_t source_merge_kind = {0};
    2105         291 :   merge_kind_t destination_merge_kind = {0};
    2106         291 :   rc = move_stake_or_lamports_shared_checks( ctx,
    2107         291 :                                              source_account,
    2108         291 :                                              lamports,
    2109         291 :                                              destination_account,
    2110         291 :                                              stake_authority_index,
    2111         291 :                                              &source_merge_kind,
    2112         291 :                                              &destination_merge_kind,
    2113         291 :                                              &ctx->txn_ctx->custom_err );
    2114         291 :   if( FD_UNLIKELY( rc ) ) return rc;
    2115             : 
    2116             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L953-L963
    2117          99 :   ulong source_free_lamports;
    2118          99 :   switch( source_merge_kind.discriminant ) {
    2119          21 :     case merge_kind_fully_active: {
    2120          21 :       source_free_lamports = fd_ulong_sat_sub( fd_ulong_sat_sub( source_account->const_meta->info.lamports,
    2121          21 :                                                                  source_merge_kind.inner.fully_active.stake.delegation.stake ),
    2122          21 :                                                 source_merge_kind.inner.fully_active.meta.rent_exempt_reserve );
    2123             :       
    2124          21 :       break;
    2125           0 :     }
    2126          72 :     case merge_kind_inactive: {
    2127          72 :       source_free_lamports = fd_ulong_sat_sub( source_merge_kind.inner.inactive.active_stake,
    2128          72 :                                                source_merge_kind.inner.inactive.meta.rent_exempt_reserve );
    2129          72 :       break;
    2130           0 :     }
    2131           6 :     default:
    2132           6 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    2133          99 :   }
    2134             : 
    2135             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L964
    2136          93 :   if( FD_UNLIKELY( lamports>source_free_lamports ) ) {
    2137          51 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    2138          51 :   }
    2139             : 
    2140             :   // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_state.rs#L968-L970
    2141          42 :   rc = fd_account_checked_sub_lamports( ctx, source_account_index, lamports );
    2142          42 :   if( FD_UNLIKELY( rc ) ) return rc;
    2143             : 
    2144          39 :   rc = fd_account_checked_add_lamports( ctx, destination_account_index, lamports );
    2145          39 :   if( FD_UNLIKELY( rc ) ) return rc;
    2146             : 
    2147         291 :   } FD_BORROWED_ACCOUNT_DROP( destination_account );
    2148         291 :   } FD_BORROWED_ACCOUNT_DROP( source_account );
    2149             : 
    2150          30 :   return FD_EXECUTOR_INSTR_SUCCESS;
    2151         291 : }
    2152             : 
    2153             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L797
    2154             : static int
    2155             : withdraw( fd_exec_instr_ctx_t const *   ctx,
    2156             :           uchar                         stake_account_index,
    2157             :           ulong                         lamports,
    2158             :           uchar                         to_index,
    2159             :           fd_sol_sysvar_clock_t const * clock,
    2160             :           fd_stake_history_t const *    stake_history,
    2161             :           uchar                         withdraw_authority_index,
    2162             :           uchar *                       custodian_index,
    2163         651 :           ulong *                       new_rate_activation_epoch ) {
    2164             : 
    2165         651 :   int rc;
    2166             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L809
    2167         651 :   fd_pubkey_t const * withdraw_authority_pubkey = &ctx->instr->acct_pubkeys[withdraw_authority_index];
    2168             : 
    2169             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L813
    2170         651 :   int is_signer = fd_instr_acc_is_signer_idx( ctx->instr, withdraw_authority_index );
    2171         651 :   if( FD_UNLIKELY( !is_signer ) ) return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2172             : 
    2173             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L817
    2174         576 :   fd_pubkey_t const * signers[FD_TXN_SIG_MAX] = { withdraw_authority_pubkey };
    2175             : 
    2176             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L819
    2177        2304 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, stake_account_index, stake_account ) {
    2178             :   
    2179             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L821
    2180         576 :   fd_stake_state_v2_t stake_state = {0};
    2181         576 :   rc = get_state( stake_account, fd_scratch_virtual(), &stake_state );
    2182         576 :   if( FD_UNLIKELY( rc ) ) return rc;
    2183             : 
    2184         552 :   fd_stake_lockup_t lockup;
    2185         552 :   ulong             reserve;
    2186         552 :   int               is_staked;
    2187             : 
    2188         552 :   switch( stake_state.discriminant ) {
    2189         213 :   case fd_stake_state_v2_enum_stake: {
    2190             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L822
    2191         213 :     fd_stake_meta_t * meta  = &stake_state.inner.stake.meta;
    2192         213 :     fd_stake_t *      stake = &stake_state.inner.stake.stake;
    2193             : 
    2194             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L823
    2195         213 :     rc = authorized_check( &meta->authorized, signers, STAKE_AUTHORIZE_WITHDRAWER );
    2196         213 :     if( FD_UNLIKELY( rc ) ) return rc;
    2197             : 
    2198             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L826
    2199         183 :     ulong staked = fd_ulong_if(
    2200         183 :         clock->epoch>=stake->delegation.deactivation_epoch,
    2201         183 :         delegation_stake(
    2202         183 :             &stake->delegation, clock->epoch, stake_history, new_rate_activation_epoch ),
    2203         183 :         stake->delegation.stake );
    2204             : 
    2205             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L837
    2206         183 :     ulong staked_and_reserve = ULONG_MAX;
    2207         183 :     rc = fd_ulong_checked_add( staked, meta->rent_exempt_reserve, &staked_and_reserve );
    2208         183 :     if( FD_UNLIKELY( rc ) ) return rc;
    2209             : 
    2210             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L838
    2211         180 :     lockup    = meta->lockup;
    2212         180 :     reserve   = staked_and_reserve;
    2213         180 :     is_staked = staked!=0;
    2214         180 :     break;
    2215         183 :   }
    2216         264 :   case fd_stake_state_v2_enum_initialized: {
    2217             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L840
    2218         264 :     fd_stake_meta_t * meta = &stake_state.inner.initialized.meta;
    2219             : 
    2220             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L841
    2221         264 :     rc = authorized_check( &meta->authorized, signers, STAKE_AUTHORIZE_WITHDRAWER );
    2222         264 :     if( FD_UNLIKELY( rc ) ) return rc;
    2223             : 
    2224             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L844
    2225         228 :     lockup    = meta->lockup;
    2226         228 :     reserve   = meta->rent_exempt_reserve;
    2227         228 :     is_staked = 0;
    2228         228 :     break;
    2229         264 :   }
    2230          54 :   case fd_stake_state_v2_enum_uninitialized: {
    2231             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L846
    2232          54 :     if( FD_UNLIKELY( !fd_instr_signers_contains( signers, stake_account->pubkey ) ) ) {
    2233          36 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2234          36 :     }
    2235             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L850
    2236          18 :     memset( &lockup, 0, sizeof( fd_stake_lockup_t ) ); /* Lockup::default(); */
    2237          18 :     reserve   = 0;
    2238          18 :     is_staked = 0;
    2239          18 :     break;
    2240          54 :   }
    2241          21 :   default:
    2242             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L852
    2243          21 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    2244         552 :   }
    2245             : 
    2246             :   // FIXME FD_LIKELY
    2247             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L857-L871
    2248         426 :   fd_pubkey_t custodian_pubkey_ = {0};
    2249         426 :   fd_pubkey_t const * custodian_pubkey  = &custodian_pubkey_;
    2250         426 :   if( custodian_index ) {
    2251          75 :     int is_signer = fd_instr_acc_is_signer_idx( ctx->instr, *custodian_index );
    2252          75 :     if( is_signer ) {
    2253          57 :       custodian_pubkey = &ctx->instr->acct_pubkeys[*custodian_index];
    2254          57 :     } else {
    2255          18 :       custodian_pubkey = NULL;
    2256          18 :     }
    2257         351 :   } else {
    2258         351 :     custodian_pubkey = NULL;
    2259         351 :   }
    2260             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L871
    2261         426 :   if( FD_UNLIKELY( lockup_is_in_force( &lockup, clock, custodian_pubkey ) ) ) {
    2262          33 :     ctx->txn_ctx->custom_err = FD_STAKE_ERR_LOCKUP_IN_FORCE;
    2263          33 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    2264         393 :   };
    2265             : 
    2266             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L875
    2267         393 :   ulong lamports_and_reserve = ULONG_MAX;
    2268         393 :   rc                         = fd_ulong_checked_add( lamports, reserve, &lamports_and_reserve );
    2269         393 :   if( FD_UNLIKELY( rc ) ) return rc;
    2270             : 
    2271             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L877
    2272         369 :   if( FD_UNLIKELY( is_staked && lamports_and_reserve>stake_account->const_meta->info.lamports ) ) {
    2273          57 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    2274          57 :   }
    2275             : 
    2276             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L883
    2277         312 :   if( FD_UNLIKELY( lamports!=stake_account->const_meta->info.lamports &&
    2278         312 :                     lamports_and_reserve>stake_account->const_meta->info.lamports ) ) {
    2279             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L886
    2280          75 :     FD_TEST( !is_staked );
    2281          75 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    2282          75 :   }
    2283             : 
    2284             :   // FIXME FD_LIKELY
    2285             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L891
    2286         237 :   if( lamports==stake_account->const_meta->info.lamports ) {
    2287         126 :     fd_stake_state_v2_t uninitialized = {0};
    2288         126 :     uninitialized.discriminant        = fd_stake_state_v2_enum_uninitialized;
    2289         126 :     rc                                = set_state( ctx, stake_account_index, &uninitialized );
    2290         126 :     if( FD_UNLIKELY( rc ) ) return rc;
    2291         126 :   }
    2292             : 
    2293             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L895
    2294         237 :   rc = fd_account_checked_sub_lamports( ctx, stake_account_index, lamports );
    2295         237 :   if( FD_UNLIKELY( rc ) ) return rc;
    2296             : 
    2297         576 :   } FD_BORROWED_ACCOUNT_DROP( stake_account );
    2298             : 
    2299             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L897
    2300         924 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, to_index, to ) {
    2301             : 
    2302             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L899
    2303         231 :   rc = fd_account_checked_add_lamports( ctx, to_index, lamports );
    2304         231 :   if( FD_UNLIKELY( rc ) ) return rc;
    2305             : 
    2306         231 :   } FD_BORROWED_ACCOUNT_DROP( to );
    2307             :   
    2308         207 :   return 0;
    2309         231 : }
    2310             : 
    2311             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L903
    2312             : static int
    2313             : deactivate_delinquent( fd_exec_instr_ctx_t *   ctx,
    2314             :                        fd_borrowed_account_t * stake_account,
    2315             :                        ulong                   stake_acc_index,
    2316             :                        ulong                   delinquent_vote_account_index,
    2317             :                        ulong                   reference_vote_account_index,
    2318             :                        ulong                   current_epoch,
    2319        1326 :                        uint *                  custom_err ) {
    2320        1326 :   int rc;
    2321             : 
    2322        1326 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    2323             : 
    2324             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L911
    2325        1326 :   fd_pubkey_t const * delinquent_vote_account_pubkey =
    2326        1326 :       &ctx->instr->acct_pubkeys[delinquent_vote_account_index];
    2327             : 
    2328             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L915
    2329        5067 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, delinquent_vote_account_index, delinquent_vote_account ) {
    2330             : 
    2331             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L917
    2332        1089 :   if( FD_UNLIKELY( memcmp( &delinquent_vote_account->const_meta->info.owner, fd_solana_vote_program_id.key, 32UL ) ) )
    2333          48 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    2334             : 
    2335             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L920-L922
    2336        1041 :   fd_vote_state_versioned_t delinquent_vote_state_versioned = {0};
    2337        1041 :   rc = fd_vote_get_state( delinquent_vote_account, scratch_valloc, &delinquent_vote_state_versioned );
    2338        1041 :   if( FD_UNLIKELY( rc ) ) return rc;
    2339         696 :   fd_vote_convert_to_current( &delinquent_vote_state_versioned, scratch_valloc );
    2340         696 :   fd_vote_state_t delinquent_vote_state = delinquent_vote_state_versioned.inner.current;
    2341             : 
    2342             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L924
    2343        2784 :   FD_BORROWED_ACCOUNT_TRY_BORROW_IDX( ctx, reference_vote_account_index, reference_vote_account ) {
    2344             : 
    2345             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L926
    2346         696 :   if( FD_UNLIKELY( memcmp( &reference_vote_account->const_meta->info.owner, fd_solana_vote_program_id.key, 32UL ) ) )
    2347           9 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID;
    2348             : 
    2349             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L929-L932
    2350         687 :   fd_vote_state_versioned_t reference_vote_state_versioned = {0};
    2351         687 :   rc = fd_vote_get_state( reference_vote_account, scratch_valloc, &reference_vote_state_versioned );
    2352         687 :   if( FD_UNLIKELY( rc ) ) return rc;
    2353         681 :   fd_vote_convert_to_current( &reference_vote_state_versioned, scratch_valloc );
    2354         681 :   fd_vote_state_t reference_vote_state = reference_vote_state_versioned.inner.current;
    2355             : 
    2356             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L933
    2357         681 :   if( !acceptable_reference_epoch_credits( reference_vote_state.epoch_credits, current_epoch ) ) {
    2358         189 :     ctx->txn_ctx->custom_err = FD_STAKE_ERR_INSUFFICIENT_REFERENCE_VOTES;
    2359         189 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    2360         189 :   }
    2361             : 
    2362         492 :   fd_stake_state_v2_t stake_state = {0};
    2363         492 :   rc = get_state( stake_account, fd_scratch_virtual(), &stake_state );
    2364         492 :   if( FD_UNLIKELY( rc ) ) return rc;
    2365             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L937
    2366         492 :   if( FD_LIKELY( stake_state.discriminant==fd_stake_state_v2_enum_stake ) ) {
    2367         492 :     fd_stake_t * stake = &stake_state.inner.stake.stake;
    2368             : 
    2369         492 :     if( FD_UNLIKELY( memcmp( &stake->delegation.voter_pubkey, delinquent_vote_account_pubkey, sizeof(fd_pubkey_t) ) ) ) {
    2370             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L939
    2371          24 :       *custom_err = FD_STAKE_ERR_VOTE_ADDRESS_MISMATCH;
    2372          24 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    2373          24 :     }
    2374             : 
    2375             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L944 
    2376         468 :     if( FD_LIKELY( eligible_for_deactivate_delinquent( delinquent_vote_state.epoch_credits,
    2377         468 :                                                         current_epoch ) ) ) {
    2378         264 :       rc = stake_deactivate( stake, current_epoch, custom_err );
    2379         264 :       if( FD_UNLIKELY( rc ) ) return rc;
    2380          72 :       rc = set_state( ctx, stake_acc_index, &stake_state );
    2381         204 :     } else {
    2382             :       // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L948
    2383         204 :       *custom_err = FD_STAKE_ERR_MINIMUM_DELIQUENT_EPOCHS_FOR_DEACTIVATION_NOT_MET;
    2384         204 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    2385         204 :     }
    2386         468 :   } else {
    2387             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L951
    2388           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    2389           0 :   }
    2390             : 
    2391         696 :   } FD_BORROWED_ACCOUNT_DROP( reference_vote_account );
    2392        1089 :   } FD_BORROWED_ACCOUNT_DROP( delinquent_vote_account );
    2393             : 
    2394          72 :   return rc;
    2395        1326 : }
    2396             : 
    2397             : /**********************************************************************/
    2398             : /* mod stake_instruction                                              */
    2399             : /**********************************************************************/
    2400             : 
    2401             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L25
    2402             : static int
    2403             : get_optional_pubkey( fd_exec_instr_ctx_t *          ctx,
    2404             :                      ulong                          acc_idx,
    2405             :                      int                            should_be_signer,
    2406        1311 :                      /* out */ fd_pubkey_t const ** pubkey ) {
    2407             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L32
    2408        1311 :   if( FD_LIKELY( acc_idx<ctx->instr->acct_cnt ) ) {
    2409             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L33
    2410         648 :     if( FD_UNLIKELY( should_be_signer && !fd_instr_acc_is_signer_idx( ctx->instr, acc_idx ) ) ) {
    2411          63 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2412          63 :     }
    2413             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L39
    2414         585 :     *pubkey = &ctx->instr->acct_pubkeys[acc_idx];
    2415         663 :   } else {
    2416         663 :     *pubkey = NULL;
    2417         663 :   }
    2418        1248 :   return 0;
    2419        1311 : }
    2420             : 
    2421             : // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L60
    2422             : static int
    2423             : get_stake_account( fd_exec_instr_ctx_t const * ctx,
    2424       12882 :                    fd_borrowed_account_t **    out ) {
    2425             : 
    2426       12882 :   if( FD_UNLIKELY( ctx->instr->acct_cnt<1 ) )
    2427          96 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2428             : 
    2429             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L61
    2430       12786 :   do {
    2431       12786 :     int err = fd_instr_borrowed_account_view_idx( ctx, 0, out );
    2432       12786 :     if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_instr_borrowed_account_view_idx failed (%d-%s)", err, fd_acc_mgr_strerror( err ) ));
    2433       12786 :   } while(0);
    2434             : 
    2435       12786 :   fd_borrowed_account_t * account = *out;
    2436       12786 :   if( FD_UNLIKELY( !fd_borrowed_account_acquire_write( account ) ) )
    2437           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
    2438             : 
    2439             :   // https://github.com/https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L62-L65
    2440       12786 :   if( FD_UNLIKELY( memcmp( account->const_meta->info.owner, fd_solana_stake_program_id.key, 32UL ) ) )
    2441         663 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
    2442             : 
    2443       12123 :   return FD_EXECUTOR_INSTR_SUCCESS;
    2444       12786 : }
    2445             : 
    2446             : /**********************************************************************/
    2447             : /* Public API                                                         */
    2448             : /**********************************************************************/
    2449             : 
    2450             : int
    2451       21243 : fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) {
    2452       21243 :   FD_EXEC_CU_UPDATE( ctx, DEFAULT_COMPUTE_UNITS );
    2453             : 
    2454             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L77
    2455       17373 :   fd_pubkey_t const * signers[FD_TXN_SIG_MAX] = {0};
    2456       17373 :   fd_instr_get_signers( ctx->instr, signers );
    2457             : 
    2458       17373 :   if( FD_UNLIKELY( ctx->instr->data==NULL ) ) {
    2459          69 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2460          69 :   }
    2461             : 
    2462             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L79
    2463       17304 :   fd_valloc_t valloc = fd_scratch_virtual();
    2464       17304 :   fd_bincode_decode_ctx_t decode =
    2465       17304 :     { .valloc  = valloc,
    2466       17304 :       .data    = ctx->instr->data,
    2467       17304 :       .dataend = ctx->instr->data + ctx->instr->data_sz };
    2468             : 
    2469       17304 :   fd_stake_instruction_t instruction[1];
    2470       17304 :   int decode_result = fd_stake_instruction_decode( instruction, &decode );
    2471             :   /* Fail if the number of bytes consumed by deserialize exceeds 1232
    2472             :      (hardcoded constant by Agave limited_deserialize) */
    2473       17304 :   if( decode_result!=FD_BINCODE_SUCCESS ||
    2474       17304 :       (ulong)ctx->instr->data + 1232UL<(ulong)decode.data )
    2475         984 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2476             : 
    2477             :   /* The EpochRewards sysvar only exists after partitioned epoch rewards is activated.
    2478             :      If the sysvar exists, check the `active` field */
    2479       16320 :   fd_sysvar_epoch_rewards_t const * rewards = fd_sysvar_cache_epoch_rewards( ctx->slot_ctx->sysvar_cache );
    2480       16320 :   int epoch_rewards_active = (NULL != rewards) ? rewards->active : false;
    2481             : 
    2482       16320 :   if (epoch_rewards_active && instruction->discriminant!=fd_stake_instruction_enum_get_minimum_delegation) {
    2483         234 :     ctx->txn_ctx->custom_err = FD_STAKE_ERR_EPOCH_REWARDS_ACTIVE;
    2484         234 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    2485         234 :   }
    2486             : 
    2487             :   /* Replicate stake account changes to bank caches after processing the
    2488             :      transaction's instructions. */
    2489       16086 :   ctx->txn_ctx->dirty_stake_acc = 1;
    2490             : 
    2491       16086 :   int rc;
    2492             :   // PLEASE PRESERVE SWITCH-CASE ORDERING TO MIRROR AGAVE IMPL:
    2493             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L84
    2494       16086 :   switch( instruction->discriminant ) {
    2495             : 
    2496             :   /* Initialize
    2497             :    *
    2498             :    * Instruction:
    2499             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L110
    2500             :    *
    2501             :    * Processor:
    2502             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L85
    2503             :    */
    2504         507 :   case fd_stake_instruction_enum_initialize: {
    2505         507 :     fd_stake_authorized_t const * authorized = &instruction->inner.initialize.authorized;
    2506         507 :     fd_stake_lockup_t const *     lockup     = &instruction->inner.initialize.lockup;
    2507             : 
    2508             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L86
    2509         507 :     fd_borrowed_account_t * me = NULL;
    2510         507 :     rc = get_stake_account( ctx, &me );  /* acquire_write */
    2511         507 :     if( FD_UNLIKELY( rc ) ) return rc;
    2512             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L87
    2513         396 :     fd_rent_t const * rent = fd_sysvar_from_instr_acct_rent( ctx, 1, &rc );
    2514         396 :     if( FD_UNLIKELY( !rent ) ) return rc;
    2515             : 
    2516             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L88
    2517         354 :     rc = initialize( ctx, me, 0, authorized, lockup, rent );
    2518             : 
    2519         354 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2520         354 :     break;
    2521         396 :   }
    2522             : 
    2523             :   /* Authorize
    2524             :    *
    2525             :    * Instruction:
    2526             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L120
    2527             :    *
    2528             :    * Processor:
    2529             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L90
    2530             :    */
    2531         567 :   case fd_stake_instruction_enum_authorize: {
    2532         567 :     fd_pubkey_t const *          authorized_pubkey = &instruction->inner.authorize.pubkey;
    2533         567 :     fd_stake_authorize_t const * stake_authorize   = &instruction->inner.authorize.stake_authorize;
    2534             : 
    2535             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L91
    2536         567 :     fd_borrowed_account_t * me = NULL;
    2537         567 :     rc = get_stake_account( ctx, &me );
    2538         567 :     if( FD_UNLIKELY( rc ) ) return rc;
    2539             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L92
    2540         516 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 1, &rc );
    2541         516 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2542             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L94
    2543         438 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<3 ) )
    2544           0 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2545             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L95
    2546         438 :     fd_pubkey_t const * custodian_pubkey = NULL;
    2547         438 :     rc = get_optional_pubkey( ctx, 3, 0, &custodian_pubkey );
    2548         438 :     if( FD_UNLIKELY( rc ) ) return rc;
    2549             : 
    2550             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L98
    2551         438 :     rc = authorize( ctx,
    2552         438 :                     me,
    2553         438 :                     0,
    2554         438 :                     signers,
    2555         438 :                     authorized_pubkey,
    2556         438 :                     stake_authorize,
    2557         438 :                     clock,
    2558         438 :                     custodian_pubkey,
    2559         438 :                     &ctx->txn_ctx->custom_err );
    2560             : 
    2561         438 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2562         438 :     break;
    2563         438 :   }
    2564             : 
    2565             :   /* AuthorizeWithSeed
    2566             :    *
    2567             :    * Instruction:
    2568             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L211
    2569             :    *
    2570             :    * Processor:
    2571             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L107
    2572             :    */
    2573         378 :   case fd_stake_instruction_enum_authorize_with_seed: {
    2574         378 :     fd_authorize_with_seed_args_t args = instruction->inner.authorize_with_seed;
    2575             : 
    2576             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L108
    2577         378 :     fd_borrowed_account_t * me = NULL;
    2578         378 :     rc                         = get_stake_account( ctx, &me );
    2579         378 :     if( FD_UNLIKELY( rc ) ) return rc;
    2580             : 
    2581             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L109
    2582         363 :     if( ctx->instr->acct_cnt<2 )
    2583           0 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2584             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L110
    2585         363 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 2, &rc );
    2586         363 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2587             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L112
    2588         351 :     fd_pubkey_t const * custodian_pubkey = NULL;
    2589         351 :     rc = get_optional_pubkey( ctx, 3, 0, &custodian_pubkey );
    2590         351 :     if( FD_UNLIKELY( rc ) ) return rc;
    2591             : 
    2592             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L115
    2593         351 :     rc = authorize_with_seed( ctx,
    2594         351 :                               me,
    2595         351 :                               0,
    2596         351 :                               1,
    2597         351 :                               (char const *)args.authority_seed,
    2598         351 :                               args.authority_seed_len,
    2599         351 :                               &args.authority_owner,
    2600         351 :                               &args.new_authorized_pubkey,
    2601         351 :                               &args.stake_authorize,
    2602         351 :                               clock,
    2603         351 :                               custodian_pubkey );
    2604             : 
    2605         351 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2606         351 :     break;
    2607         351 :   }
    2608             : 
    2609             :   /* DelegateStake
    2610             :    *
    2611             :    * Instruction:
    2612             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L135
    2613             :    *
    2614             :    * Processor:
    2615             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L128
    2616             :    */
    2617        1479 :   case fd_stake_instruction_enum_delegate_stake: {
    2618             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L129
    2619        1479 :     fd_borrowed_account_t * me = NULL;
    2620        1479 :     rc                         = get_stake_account( ctx, &me );
    2621        1479 :     if( FD_UNLIKELY( rc ) ) return rc;
    2622             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L130
    2623        1449 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<2 ) )
    2624          42 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2625             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L131
    2626        1407 :     fd_sol_sysvar_clock_t const * clock =
    2627        1407 :       fd_sysvar_from_instr_acct_clock( ctx, 2, &rc );
    2628        1407 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2629             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L133
    2630        1284 :     fd_stake_history_t const * stake_history =
    2631        1284 :       fd_sysvar_from_instr_acct_stake_history( ctx, 3, &rc );
    2632        1284 :     if( FD_UNLIKELY( !stake_history ) ) return rc;
    2633             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L138
    2634        1275 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<5 ) )
    2635           3 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2636        1272 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2637             : 
    2638             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L140
    2639        1272 :     rc = delegate( ctx,
    2640        1272 :                    0,
    2641        1272 :                    1,
    2642        1272 :                    clock,
    2643        1272 :                    stake_history,
    2644        1272 :                    signers );
    2645             : 
    2646        1272 :     break;
    2647        1275 :   }
    2648             : 
    2649             :   /* Split
    2650             :    *
    2651             :    * Instruction:
    2652             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L143
    2653             :    *
    2654             :    * Processor:
    2655             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L152
    2656             :    */
    2657        2847 :   case fd_stake_instruction_enum_split: {
    2658        2847 :     ulong lamports = instruction->inner.split;
    2659             : 
    2660             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L153
    2661        2847 :     fd_borrowed_account_t * me = NULL;
    2662        2847 :     rc                         = get_stake_account( ctx, &me );
    2663        2847 :     if( FD_UNLIKELY( rc ) ) return rc;
    2664             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L154
    2665        2781 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<2 ) )
    2666           0 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2667        2781 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2668             : 
    2669             :     //https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L156
    2670        2781 :     rc = split( ctx, 0, lamports, 1, signers );
    2671        2781 :     break;
    2672        2781 :   }
    2673             : 
    2674             :   /* Merge
    2675             :    *
    2676             :    * Instruction:
    2677             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L201
    2678             :    *
    2679             :    * Processor:
    2680             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L166
    2681             :    */
    2682        2004 :   case fd_stake_instruction_enum_merge: {
    2683             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L167
    2684        2004 :     fd_borrowed_account_t * me = NULL;
    2685        2004 :     rc                         = get_stake_account( ctx, &me );
    2686        2004 :     if( FD_UNLIKELY( rc ) ) return rc;
    2687             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L168
    2688        1956 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<2 ) )
    2689           0 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2690             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L169
    2691        1956 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 2, &rc );
    2692        1956 :     if( FD_UNLIKELY( rc ) ) return rc;
    2693             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L171
    2694        1647 :     fd_stake_history_t const * stake_history = fd_sysvar_from_instr_acct_stake_history( ctx, 3, &rc );
    2695        1647 :     if( FD_UNLIKELY( rc ) ) return rc;
    2696             : 
    2697        1635 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2698             : 
    2699             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L177
    2700        1635 :     rc = merge( ctx, 0, 1, clock, stake_history, signers );
    2701        1635 :     break;
    2702        1647 :   }
    2703             : 
    2704             :   /* Withdraw
    2705             :    *
    2706             :    * Instruction:
    2707             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L157
    2708             :    *
    2709             :    * Processor:
    2710             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L188
    2711             :    */
    2712         894 :   case fd_stake_instruction_enum_withdraw: FD_SCRATCH_SCOPE_BEGIN {
    2713         894 :     ulong lamports = instruction->inner.withdraw;
    2714             : 
    2715             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L189
    2716         894 :     fd_borrowed_account_t * me = NULL;
    2717         894 :     rc = get_stake_account( ctx, &me );  /* calls acquire_write */
    2718         894 :     if( FD_UNLIKELY( rc ) ) return rc;
    2719             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L190
    2720         861 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<2 ) )
    2721          24 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2722             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L191
    2723         837 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 2, &rc );
    2724         837 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2725             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L193
    2726         687 :     fd_stake_history_t const * stake_history = fd_sysvar_from_instr_acct_stake_history( ctx, 3, &rc );
    2727         687 :     if( FD_UNLIKELY( !stake_history ) ) return rc;
    2728             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L198
    2729         654 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<5 ) )
    2730           3 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2731             : 
    2732         651 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2733             : 
    2734         651 :     uchar custodian_index           = 5;
    2735         651 :     ulong new_rate_activation_epoch = ULONG_MAX;
    2736         651 :     int   err;
    2737         651 :     int   is_some = new_warmup_cooldown_rate_epoch( ctx, &new_rate_activation_epoch, &err );
    2738         651 :     if( FD_UNLIKELY( err ) ) return err;
    2739             : 
    2740             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L200
    2741         651 :     rc = withdraw(
    2742         651 :         ctx,
    2743         651 :         0,
    2744         651 :         lamports,
    2745         651 :         1,
    2746         651 :         clock,
    2747         651 :         stake_history,
    2748         651 :         4,
    2749             :         // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L209-L215
    2750         651 :         fd_ptr_if( ctx->instr->acct_cnt>=6, &custodian_index, NULL ),
    2751         651 :         fd_ptr_if( is_some, &new_rate_activation_epoch, NULL ) );
    2752             : 
    2753         894 :     } FD_SCRATCH_SCOPE_END;
    2754         651 :     break;
    2755             : 
    2756             :   /* Deactivate
    2757             :    *
    2758             :    * Instruction:
    2759             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L165
    2760             :    * 
    2761             :    * Processor:
    2762             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L217
    2763             :    */
    2764         651 :   case fd_stake_instruction_enum_deactivate: {
    2765             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L218
    2766         579 :     fd_borrowed_account_t * me = NULL;
    2767         579 :     rc                         = get_stake_account( ctx, &me );
    2768         579 :     if( FD_UNLIKELY( rc ) ) return rc;
    2769             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L219
    2770         462 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 1, &rc );
    2771         462 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2772             : 
    2773             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L221
    2774         366 :     rc = deactivate( ctx, me, 0, clock, signers, &ctx->txn_ctx->custom_err );
    2775             : 
    2776         366 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2777         366 :     break;
    2778         462 :   }
    2779             : 
    2780             :   /* SetLockup
    2781             :    *
    2782             :    * Instruction:
    2783             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L175
    2784             :    *
    2785             :    * Processor:
    2786             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L223
    2787             :    */
    2788         606 :   case fd_stake_instruction_enum_set_lockup: {
    2789         606 :     fd_lockup_args_t * lockup = &instruction->inner.set_lockup;
    2790             : 
    2791             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L224
    2792         606 :     fd_borrowed_account_t * me = NULL;
    2793         606 :     rc = get_stake_account( ctx, &me );
    2794         606 :     if( FD_UNLIKELY( rc ) ) return rc;
    2795             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L225
    2796         543 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2797         543 :     if( FD_UNLIKELY( !clock ) )
    2798           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2799             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L226
    2800         543 :     rc = set_lockup( ctx, me, 0, lockup, signers, clock );
    2801             : 
    2802         543 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2803         543 :     break;
    2804         543 :   }
    2805             : 
    2806             :   /* InitializeChecked
    2807             :    *
    2808             :    * Instruction:
    2809             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L224
    2810             :    *
    2811             :    * Processor:
    2812             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L228
    2813             :    */
    2814         186 :   case fd_stake_instruction_enum_initialize_checked: {
    2815             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L229
    2816         186 :     fd_borrowed_account_t * me = NULL;
    2817         186 :     rc = get_stake_account( ctx, &me );
    2818         186 :     if( FD_UNLIKELY( rc ) ) return rc;
    2819             : 
    2820             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L230
    2821         150 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<4 ) )
    2822           6 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2823             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L231-L236
    2824         144 :     fd_pubkey_t const * staker_pubkey     = &ctx->instr->acct_pubkeys[2];
    2825         144 :     fd_pubkey_t const * withdrawer_pubkey = &ctx->instr->acct_pubkeys[3];
    2826             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L237
    2827         144 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, 3 ) ) )
    2828          45 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2829             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L241
    2830          99 :     fd_stake_authorized_t authorized = { .staker     = *staker_pubkey,
    2831          99 :                                           .withdrawer = *withdrawer_pubkey };
    2832             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L246
    2833          99 :     fd_rent_t const * rent = fd_sysvar_from_instr_acct_rent( ctx, 1, &rc );
    2834          99 :     if( FD_UNLIKELY( !rent ) ) return rc;
    2835             : 
    2836          96 :     fd_stake_lockup_t lockup_default = {0};
    2837             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L247
    2838          96 :     rc = initialize( ctx, me, 0, &authorized, &lockup_default, rent );
    2839             : 
    2840          96 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2841          96 :     break;
    2842          99 :   }
    2843             : 
    2844             :   /* AuthorizeChecked
    2845             :    *
    2846             :    * Instruction:
    2847             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L238
    2848             :    *
    2849             :    * Processor:
    2850             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L249
    2851             :    */
    2852         381 :   case fd_stake_instruction_enum_authorize_checked: {
    2853         381 :     fd_stake_authorize_t const * stake_authorize = &instruction->inner.authorize_checked;
    2854             : 
    2855             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L250
    2856         381 :     fd_borrowed_account_t * me = NULL;
    2857         381 :     rc                         = get_stake_account( ctx, &me );
    2858         381 :     if( FD_UNLIKELY( rc ) ) return rc;
    2859             : 
    2860             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L251
    2861         348 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 1, &rc );
    2862         348 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2863             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L253
    2864         330 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<4 ) )
    2865           6 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2866             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L254
    2867         324 :     fd_pubkey_t const * authorized_pubkey = &ctx->instr->acct_pubkeys[3];
    2868             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L257
    2869         324 :     int is_signer = fd_instr_acc_is_signer_idx( ctx->instr, 3 );
    2870         324 :     if( FD_UNLIKELY( !is_signer ) ) return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2871             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L260
    2872         201 :     fd_pubkey_t const * custodian_pubkey = NULL;
    2873         201 :     rc = get_optional_pubkey( ctx, 4, 0, &custodian_pubkey );
    2874         201 :     if( FD_UNLIKELY( rc ) ) return rc;
    2875             : 
    2876             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L263
    2877         201 :     rc = authorize( ctx,
    2878         201 :                     me,
    2879         201 :                     0,
    2880         201 :                     signers,
    2881         201 :                     authorized_pubkey,
    2882         201 :                     stake_authorize,
    2883         201 :                     clock,
    2884         201 :                     custodian_pubkey,
    2885         201 :                     &ctx->txn_ctx->custom_err );
    2886             : 
    2887         201 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2888         201 :     break;
    2889         201 :   }
    2890             : 
    2891             :   /* AuthorizeCheckedWithSeed
    2892             :    *
    2893             :    * Instruction:
    2894             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L252
    2895             :    *
    2896             :    * Processor:
    2897             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L272
    2898             :    */
    2899         171 :   case fd_stake_instruction_enum_authorize_checked_with_seed: {
    2900         171 :     fd_authorize_checked_with_seed_args_t const * args =
    2901         171 :         &instruction->inner.authorize_checked_with_seed;
    2902             : 
    2903             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L273
    2904         171 :     fd_borrowed_account_t * me = NULL;
    2905         171 :     rc                         = get_stake_account( ctx, &me );
    2906         171 :     if( FD_UNLIKELY( rc ) ) return rc;
    2907             : 
    2908             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L274
    2909         153 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<2 ) )
    2910           0 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2911             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L276
    2912         153 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 2, &rc );
    2913         153 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2914             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L277
    2915         141 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<4 ) )
    2916           3 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2917             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L278
    2918         138 :     fd_pubkey_t const * authorized_pubkey = &ctx->instr->acct_pubkeys[3];
    2919             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L281
    2920         138 :     int is_signer = fd_instr_acc_is_signer_idx( ctx->instr, 3 );
    2921         138 :     if( FD_UNLIKELY( !is_signer ) ) return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2922             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L284
    2923          78 :     fd_pubkey_t const * custodian_pubkey = NULL;
    2924          78 :     rc = get_optional_pubkey( ctx, 4, 0, &custodian_pubkey );
    2925          78 :     if( FD_UNLIKELY( rc ) ) return rc;
    2926             : 
    2927             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L287
    2928          78 :     rc = authorize_with_seed( ctx,
    2929          78 :                               me,
    2930          78 :                               0,
    2931          78 :                               1,
    2932          78 :                               (char const *)args->authority_seed,
    2933          78 :                               args->authority_seed_len,
    2934          78 :                               &args->authority_owner,
    2935          78 :                               authorized_pubkey,
    2936          78 :                               &args->stake_authorize,
    2937          78 :                               clock,
    2938          78 :                               custodian_pubkey );
    2939             : 
    2940          78 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2941          78 :     break;
    2942          78 :   }
    2943             : 
    2944             :   /* SetLockupChecked
    2945             :    *
    2946             :    * Instruction:
    2947             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L266
    2948             :    *
    2949             :    * Processor:
    2950             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L300
    2951             :    */
    2952         300 :   case fd_stake_instruction_enum_set_lockup_checked: {
    2953         300 :     fd_lockup_checked_args_t * lockup_checked = &instruction->inner.set_lockup_checked;
    2954             : 
    2955             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L301
    2956         300 :     fd_borrowed_account_t * me = NULL;
    2957         300 :     rc = get_stake_account( ctx, &me );  /* acquire_write */
    2958         300 :     if( FD_UNLIKELY( rc ) ) return rc;
    2959             : 
    2960             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L302
    2961         243 :     fd_pubkey_t const * custodian_pubkey = NULL;
    2962         243 :     rc = get_optional_pubkey( ctx, 2, 1, &custodian_pubkey );
    2963         243 :     if( FD_UNLIKELY( rc ) ) return rc;
    2964             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L305
    2965         180 :     fd_lockup_args_t lockup = { .unix_timestamp = lockup_checked->unix_timestamp,
    2966         180 :                                 .epoch          = lockup_checked->epoch,
    2967         180 :                                 .custodian      = (fd_pubkey_t *)custodian_pubkey }; // FIXME
    2968             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L310
    2969         180 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2970         180 :     if( FD_UNLIKELY( !clock ) )
    2971           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2972             : 
    2973             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L311
    2974         180 :     rc = set_lockup( ctx, me, 0, &lockup, signers, clock );
    2975             : 
    2976         180 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    2977         180 :     break;
    2978         180 :   }
    2979             : 
    2980             :   /* GetMinimumDelegation
    2981             :    *
    2982             :    * Instruction:
    2983             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L278
    2984             :    *
    2985             :    * Processor:
    2986             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L313
    2987             :    */
    2988        2223 :   case fd_stake_instruction_enum_get_minimum_delegation: {
    2989        2223 :     ulong minimum_delegation = get_minimum_delegation( ctx->slot_ctx );
    2990        2223 :     fd_memcpy( &ctx->txn_ctx->return_data.program_id, fd_solana_stake_program_id.key, sizeof(fd_pubkey_t));
    2991        2223 :     fd_memcpy(ctx->txn_ctx->return_data.data, (uchar*)(&minimum_delegation), sizeof(ulong));
    2992        2223 :     ctx->txn_ctx->return_data.len = sizeof(ulong);
    2993        2223 :     rc = 0;
    2994        2223 :     goto done;
    2995         180 :   }
    2996             : 
    2997             :   /* DeactivateDelinquent
    2998             :    *
    2999             :    * Instruction:
    3000             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/instruction.rs#L291
    3001             :    *
    3002             :    * Processor:
    3003             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L321
    3004             :    */
    3005        1434 :   case fd_stake_instruction_enum_deactivate_delinquent: {
    3006             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L322
    3007        1434 :     fd_borrowed_account_t * me = NULL;
    3008        1434 :     rc                         = get_stake_account( ctx, &me );
    3009        1434 :     if( FD_UNLIKELY( rc ) ) return rc;
    3010             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L323
    3011        1377 :     if( FD_UNLIKELY( ctx->instr->acct_cnt<3 ) )
    3012          51 :       return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    3013             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L325
    3014        1326 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    3015        1326 :     if( FD_UNLIKELY( !clock ) )
    3016           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    3017             : 
    3018             :     // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L326
    3019        1326 :     rc = deactivate_delinquent( ctx, me, 0, 1, 2, clock->epoch, &ctx->txn_ctx->custom_err );
    3020             : 
    3021        1326 :     fd_borrowed_account_release_write( me );  /* implicit drop */
    3022        1326 :     break;
    3023        1326 :   }
    3024             : 
    3025             :   /* Redelegate
    3026             :    *
    3027             :    * Deprecated:
    3028             :    * https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L336
    3029             :    */
    3030         549 :   case fd_stake_instruction_enum_redelegate: {
    3031         549 :     fd_borrowed_account_t * me = NULL;
    3032         549 :     rc                         = get_stake_account( ctx, &me );
    3033         549 :     if( FD_UNLIKELY( rc ) ) return rc;
    3034             : 
    3035         525 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    3036         549 :   }
    3037             :   /* MoveStake
    3038             :    *
    3039             :    * Instruction:
    3040             :    * https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/sdk/program/src/stake/instruction.rs#L330 
    3041             :    * 
    3042             :    * Processor:
    3043             :    * https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L356
    3044             :    */
    3045         600 :   case fd_stake_instruction_enum_move_stake: {
    3046             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L359
    3047         600 :     if( FD_LIKELY( FD_FEATURE_ACTIVE( ctx->slot_ctx, move_stake_and_move_lamports_ixs ) ) ) {
    3048             :       // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L361
    3049         480 :       if( FD_UNLIKELY( ctx->instr->acct_cnt<3 ) )
    3050           3 :         return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    3051             : 
    3052         477 :       ulong lamports = instruction->inner.move_stake;
    3053             :       // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L362
    3054         477 :       rc = move_stake( ctx,
    3055         477 :                        0UL,
    3056         477 :                        lamports,
    3057         477 :                        1UL,
    3058         477 :                        2UL,
    3059         477 :                        &ctx->txn_ctx->custom_err );
    3060         477 :     } else {
    3061             :       // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L372
    3062         120 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    3063         120 :     }
    3064         477 :     break;
    3065         600 :   }
    3066             :   /* MoveLamports
    3067             :    *
    3068             :    * Instruction:
    3069             :    * https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/sdk/program/src/stake/instruction.rs#L345 
    3070             :    * 
    3071             :    * Processor:
    3072             :    * https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L375
    3073             :    */
    3074         477 :   case fd_stake_instruction_enum_move_lamports: {
    3075             :     // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L378
    3076         381 :     if( FD_LIKELY( FD_FEATURE_ACTIVE( ctx->slot_ctx, move_stake_and_move_lamports_ixs ) ) ) {
    3077             :       // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L380
    3078         294 :       if( FD_UNLIKELY( ctx->instr->acct_cnt<3 ) )
    3079           3 :         return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    3080             : 
    3081             :       // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L381
    3082         291 :       ulong lamports = instruction->inner.move_lamports;
    3083             : 
    3084             :       // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L381
    3085         291 :       rc = move_lamports( ctx,
    3086         291 :                        0UL,
    3087         291 :                        lamports,
    3088         291 :                        1UL,
    3089         291 :                        2UL );
    3090         291 :     } else {
    3091             :       // https://github.com/anza-xyz/agave/blob/cdff19c7807b006dd63429114fb1d9573bf74172/programs/stake/src/stake_instruction.rs#L391
    3092          87 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    3093          87 :     }
    3094         291 :     break;
    3095         381 :   }
    3096         291 :   default:
    3097           0 :     FD_LOG_ERR(( "unsupported stake instruction: %u", instruction->discriminant ));
    3098       16086 :   }
    3099             : 
    3100       13263 : done:
    3101       13263 :   return rc;
    3102       16086 : }
    3103             : 
    3104             : /* Public API *********************************************************/
    3105             : 
    3106             : static void
    3107           0 : write_stake_config( fd_exec_slot_ctx_t * slot_ctx, fd_stake_config_t const * stake_config ) {
    3108           0 :   ulong                   data_sz  = fd_stake_config_size( stake_config );
    3109           0 :   fd_pubkey_t const *     acc_key  = &fd_solana_stake_program_config_id;
    3110           0 :   fd_account_meta_t *     acc_meta = NULL;
    3111           0 :   uchar *                 acc_data = NULL;
    3112           0 :   FD_BORROWED_ACCOUNT_DECL(rec);
    3113           0 :   int err = fd_acc_mgr_modify( slot_ctx->acc_mgr, slot_ctx->funk_txn, acc_key, 1, data_sz, rec );
    3114           0 :   FD_TEST( !err );
    3115             : 
    3116           0 :   acc_meta                  = rec->meta;
    3117           0 :   acc_data                  = rec->data;
    3118           0 :   acc_meta->dlen            = data_sz;
    3119           0 :   acc_meta->info.lamports   = 960480UL;
    3120           0 :   acc_meta->info.rent_epoch = 0UL;
    3121           0 :   acc_meta->info.executable = 0;
    3122             : 
    3123           0 :   fd_bincode_encode_ctx_t ctx3;
    3124           0 :   ctx3.data    = acc_data;
    3125           0 :   ctx3.dataend = acc_data + data_sz;
    3126           0 :   if( fd_stake_config_encode( stake_config, &ctx3 ) )
    3127           0 :     FD_LOG_ERR( ( "fd_stake_config_encode failed" ) );
    3128             : 
    3129           0 :   fd_memset( acc_data, 0, data_sz );
    3130           0 :   fd_memcpy( acc_data, stake_config, sizeof( fd_stake_config_t ) );
    3131           0 : }
    3132             : 
    3133             : void
    3134           0 : fd_stake_program_config_init( fd_exec_slot_ctx_t * slot_ctx ) {
    3135             :   // https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/sdk/program/src/stake/config.rs#L26
    3136           0 :   fd_stake_config_t stake_config = {
    3137           0 :       .warmup_cooldown_rate = DEFAULT_WARMUP_COOLDOWN_RATE,
    3138           0 :       .slash_penalty        = DEFAULT_SLASH_PENALTY,
    3139           0 :   };
    3140           0 :   write_stake_config( slot_ctx, &stake_config );
    3141           0 : }
    3142             : 
    3143             : int
    3144             : fd_stake_get_state( fd_borrowed_account_t const * self,
    3145             :                     fd_valloc_t const *           valloc,
    3146           0 :                     fd_stake_state_v2_t *         out ) {
    3147           0 :   return get_state( self, *valloc, out );
    3148           0 : }
    3149             : 
    3150             : fd_stake_history_entry_t
    3151             : fd_stake_activating_and_deactivating( fd_delegation_t const *    self,
    3152             :                                       ulong                      target_epoch,
    3153             :                                       fd_stake_history_t const * stake_history,
    3154           0 :                                       ulong *                    new_rate_activation_epoch ) {
    3155           0 :   return stake_activating_and_deactivating(
    3156           0 :     self, target_epoch, stake_history, new_rate_activation_epoch );
    3157           0 : }
    3158             : 
    3159             : /* Removes stake delegation from epoch stakes and updates vote account */
    3160             : static void
    3161           0 : fd_stakes_remove_stake_delegation( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * stake_account ) {
    3162           0 :   fd_stake_accounts_pair_t_mapnode_t key;
    3163           0 :   fd_memcpy( key.elem.key.uc, stake_account->pubkey->uc, sizeof(fd_pubkey_t) );
    3164           0 :   if( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool==NULL ) {
    3165           0 :     FD_LOG_DEBUG(("Stake accounts pool does not exist"));
    3166           0 :     return;
    3167           0 :   }
    3168           0 :   fd_stake_accounts_pair_t_mapnode_t * entry = fd_stake_accounts_pair_t_map_find( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, slot_ctx->slot_bank.stake_account_keys.stake_accounts_root, &key );
    3169           0 :   if (FD_UNLIKELY( entry )) {
    3170           0 :     fd_stake_accounts_pair_t_map_remove( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, &slot_ctx->slot_bank.stake_account_keys.stake_accounts_root, entry);
    3171             :     // TODO: do we need a release here?
    3172           0 :   }
    3173           0 : }
    3174             : 
    3175             : /* Updates stake delegation in epoch stakes */
    3176             : static void
    3177           0 : fd_stakes_upsert_stake_delegation( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * stake_account ) {
    3178           0 :   FD_TEST( stake_account->const_meta->info.lamports!=0 );
    3179           0 :   fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
    3180           0 :   fd_stakes_t * stakes = &epoch_bank->stakes;
    3181             : 
    3182           0 :   fd_delegation_pair_t_mapnode_t key;
    3183           0 :   fd_memcpy(&key.elem.account, stake_account->pubkey->uc, sizeof(fd_pubkey_t));
    3184             : 
    3185           0 :   if( stakes->stake_delegations_pool==NULL) {
    3186           0 :     FD_LOG_DEBUG(("Stake delegations pool does not exist"));
    3187           0 :     return;
    3188           0 :   }
    3189             : 
    3190           0 :   fd_delegation_pair_t_mapnode_t * entry = fd_delegation_pair_t_map_find( stakes->stake_delegations_pool, stakes->stake_delegations_root, &key);
    3191           0 :   if( FD_UNLIKELY( !entry ) ) {
    3192           0 :     fd_stake_accounts_pair_t_mapnode_t key;
    3193           0 :     fd_memcpy( key.elem.key.uc, stake_account->pubkey->uc, sizeof(fd_pubkey_t) );
    3194           0 :     if( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool==NULL) {
    3195           0 :       FD_LOG_DEBUG(("Stake accounts pool does not exist"));
    3196           0 :       return;
    3197           0 :     }
    3198           0 :     fd_stake_accounts_pair_t_mapnode_t * stake_entry = fd_stake_accounts_pair_t_map_find( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, slot_ctx->slot_bank.stake_account_keys.stake_accounts_root, &key );
    3199           0 :     if( stake_entry ) {
    3200           0 :       stake_entry->elem.exists = 1;
    3201           0 :     } else {
    3202           0 :       fd_stake_accounts_pair_t_mapnode_t * new_node = fd_stake_accounts_pair_t_map_acquire( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool );
    3203           0 :       ulong size = fd_stake_accounts_pair_t_map_size( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, slot_ctx->slot_bank.stake_account_keys.stake_accounts_root );
    3204           0 :       FD_LOG_DEBUG(("Curr stake account size %lu %p", size, (void *)slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool));
    3205           0 :       if( new_node==NULL ) {
    3206           0 :         FD_LOG_ERR(("Stake accounts keys map full %lu", size));
    3207           0 :       }
    3208           0 :       new_node->elem.exists = 1;
    3209           0 :       fd_memcpy( new_node->elem.key.uc, stake_account->pubkey->uc, sizeof(fd_pubkey_t) );
    3210           0 :       fd_stake_accounts_pair_t_map_insert( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, &slot_ctx->slot_bank.stake_account_keys.stake_accounts_root, new_node );
    3211           0 :     }
    3212           0 :   }
    3213           0 : }
    3214             : 
    3215           0 : void fd_store_stake_delegation( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * stake_account ) {
    3216           0 :   fd_pubkey_t const * owner = (fd_pubkey_t const *)stake_account->const_meta->info.owner;
    3217             : 
    3218           0 :   if( memcmp( owner->uc, fd_solana_stake_program_id.key, sizeof(fd_pubkey_t) ) ) {
    3219           0 :       return;
    3220           0 :   }
    3221             : 
    3222           0 :   int is_empty  = stake_account->const_meta->info.lamports==0;
    3223           0 :   int is_uninit = 1;
    3224           0 :   if( stake_account->const_meta->dlen>=4 ) {
    3225           0 :     uint prefix = FD_LOAD( uint, stake_account->const_data );
    3226           0 :     is_uninit = ( prefix==fd_stake_state_v2_enum_uninitialized );
    3227           0 :   }
    3228             : 
    3229           0 :   if( is_empty || is_uninit ) {
    3230           0 :     fd_stakes_remove_stake_delegation( slot_ctx, stake_account );
    3231           0 :   } else {
    3232           0 :     fd_stakes_upsert_stake_delegation( slot_ctx, stake_account );
    3233           0 :   }
    3234           0 : }

Generated by: LCOV version 1.14