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 123 : fd_stake_history_t * stake_history ) { 15 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/sysvar/stake_history.rs#L12 */ 16 123 : uchar __attribute__((aligned(FD_STAKE_HISTORY_ALIGN))) enc[ FD_SYSVAR_STAKE_HISTORY_BINCODE_SZ ] = {0}; 17 123 : fd_bincode_encode_ctx_t encode = 18 123 : { .data = enc, 19 123 : .dataend = enc + sizeof(enc) }; 20 123 : 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 123 : fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_stake_history_id, enc, sizeof(enc) ); 24 123 : } 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 42 : fd_stake_history_t * stake_history ) { 30 42 : fd_accdb_ro_t ro[1]; 31 42 : 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 42 : 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 42 : stake_history = fd_bincode_decode_static( 45 42 : stake_history, stake_history, 46 42 : fd_accdb_ref_data_const( ro ), 47 42 : fd_accdb_ref_data_sz( ro ) ); 48 42 : fd_accdb_close_ro( accdb, ro ); 49 42 : return stake_history; 50 42 : } 51 : 52 : void 53 : fd_sysvar_stake_history_init( fd_bank_t * bank, 54 : fd_accdb_user_t * accdb, 55 : fd_funk_txn_xid_t const * xid, 56 108 : fd_capture_ctx_t * capture_ctx ) { 57 108 : fd_stake_history_t stake_history; 58 108 : fd_stake_history_new( &stake_history ); 59 108 : write_stake_history( bank, accdb, xid, capture_ctx, &stake_history ); 60 108 : } 61 : 62 : void 63 : fd_sysvar_stake_history_update( fd_bank_t * bank, 64 : fd_accdb_user_t * accdb, 65 : fd_funk_txn_xid_t const * xid, 66 : fd_capture_ctx_t * capture_ctx, 67 15 : fd_epoch_stake_history_entry_pair_t const * pair ) { 68 : 69 15 : fd_stake_history_t stake_history[1]; 70 15 : if( FD_UNLIKELY( !fd_sysvar_stake_history_read( accdb, xid, stake_history ) ) ) { 71 0 : FD_LOG_CRIT(( "Failed to read stake history sysvar" )); 72 0 : } 73 : 74 15 : if( stake_history->fd_stake_history_offset == 0 ) { 75 15 : stake_history->fd_stake_history_offset = stake_history->fd_stake_history_size - 1; 76 15 : } else { 77 0 : stake_history->fd_stake_history_offset--; 78 0 : } 79 : 80 15 : if( stake_history->fd_stake_history_len < stake_history->fd_stake_history_size ) { 81 15 : stake_history->fd_stake_history_len++; 82 15 : } 83 : 84 : // This should be done with a bit mask 85 15 : ulong idx = stake_history->fd_stake_history_offset; 86 : 87 15 : stake_history->fd_stake_history[ idx ].epoch = pair->epoch; 88 15 : stake_history->fd_stake_history[ idx ].entry.activating = pair->entry.activating; 89 15 : stake_history->fd_stake_history[ idx ].entry.effective = pair->entry.effective; 90 15 : stake_history->fd_stake_history[ idx ].entry.deactivating = pair->entry.deactivating; 91 : 92 15 : write_stake_history( bank, accdb, xid, capture_ctx, stake_history ); 93 : 94 15 : }