Line data Source code
1 : #include "fd_sysvar_stake_history.h" 2 : #include "fd_sysvar.h" 3 : #include "../fd_system_ids.h" 4 : #include "../../accdb/fd_accdb_sync.h" 5 : 6 : /* Ensure that the size declared by our header matches the minimum size 7 : of the corresponding fd_types entry. */ 8 : 9 : static void 10 : write_stake_history( fd_bank_t * bank, 11 : fd_accdb_user_t * accdb, 12 : fd_funk_txn_xid_t const * xid, 13 : fd_capture_ctx_t * capture_ctx, 14 33 : fd_stake_history_t * stake_history ) { 15 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/sysvar/stake_history.rs#L12 */ 16 33 : uchar __attribute__((aligned(FD_STAKE_HISTORY_ALIGN))) enc[ FD_SYSVAR_STAKE_HISTORY_BINCODE_SZ ] = {0}; 17 33 : fd_bincode_encode_ctx_t encode = 18 33 : { .data = enc, 19 33 : .dataend = enc + sizeof(enc) }; 20 33 : if( FD_UNLIKELY( fd_stake_history_encode( stake_history, &encode )!=FD_BINCODE_SUCCESS ) ) 21 0 : FD_LOG_ERR(("fd_stake_history_encode failed")); 22 : 23 33 : fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_stake_history_id, enc, sizeof(enc) ); 24 33 : } 25 : 26 : fd_stake_history_t * 27 : fd_sysvar_stake_history_read( fd_accdb_user_t * accdb, 28 : fd_funk_txn_xid_t const * xid, 29 54 : fd_stake_history_t * stake_history ) { 30 54 : fd_accdb_ro_t ro[1]; 31 54 : if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, &fd_sysvar_stake_history_id ) ) ) { 32 0 : return NULL; 33 0 : } 34 : 35 : /* This check is needed as a quirk of the fuzzer. If a sysvar account 36 : exists in the accounts database, but doesn't have any lamports, 37 : this means that the account does not exist. This wouldn't happen 38 : in a real execution environment. */ 39 54 : if( FD_UNLIKELY( fd_accdb_ref_lamports( ro )==0UL ) ) { 40 0 : fd_accdb_close_ro( accdb, ro ); 41 0 : return NULL; 42 0 : } 43 : 44 54 : stake_history = fd_bincode_decode_static( 45 54 : stake_history, stake_history, 46 54 : fd_accdb_ref_data_const( ro ), 47 54 : fd_accdb_ref_data_sz( ro ), 48 54 : NULL ); 49 54 : fd_accdb_close_ro( accdb, ro ); 50 54 : return stake_history; 51 54 : } 52 : 53 : void 54 : fd_sysvar_stake_history_init( fd_bank_t * bank, 55 : fd_accdb_user_t * accdb, 56 : fd_funk_txn_xid_t const * xid, 57 15 : fd_capture_ctx_t * capture_ctx ) { 58 15 : fd_stake_history_t stake_history; 59 15 : fd_stake_history_new( &stake_history ); 60 15 : write_stake_history( bank, accdb, xid, capture_ctx, &stake_history ); 61 15 : } 62 : 63 : void 64 : fd_sysvar_stake_history_update( fd_bank_t * bank, 65 : fd_accdb_user_t * accdb, 66 : fd_funk_txn_xid_t const * xid, 67 : fd_capture_ctx_t * capture_ctx, 68 18 : fd_epoch_stake_history_entry_pair_t const * pair ) { 69 : 70 18 : fd_stake_history_t stake_history[1]; 71 18 : if( FD_UNLIKELY( !fd_sysvar_stake_history_read( accdb, xid, stake_history ) ) ) { 72 0 : FD_LOG_CRIT(( "Failed to read stake history sysvar" )); 73 0 : } 74 : 75 18 : if( stake_history->fd_stake_history_offset == 0 ) { 76 18 : stake_history->fd_stake_history_offset = stake_history->fd_stake_history_size - 1; 77 18 : } else { 78 0 : stake_history->fd_stake_history_offset--; 79 0 : } 80 : 81 18 : if( stake_history->fd_stake_history_len < stake_history->fd_stake_history_size ) { 82 18 : stake_history->fd_stake_history_len++; 83 18 : } 84 : 85 : // This should be done with a bit mask 86 18 : ulong idx = stake_history->fd_stake_history_offset; 87 : 88 18 : stake_history->fd_stake_history[ idx ].epoch = pair->epoch; 89 18 : stake_history->fd_stake_history[ idx ].entry.activating = pair->entry.activating; 90 18 : stake_history->fd_stake_history[ idx ].entry.effective = pair->entry.effective; 91 18 : stake_history->fd_stake_history[ idx ].entry.deactivating = pair->entry.deactivating; 92 : 93 18 : write_stake_history( bank, accdb, xid, capture_ctx, stake_history ); 94 : 95 18 : }