Line data Source code
1 : #include "fd_sysvar_stake_history.h" 2 : #include "fd_sysvar.h" 3 : #include "../fd_system_ids.h" 4 : #include "../context/fd_exec_slot_ctx.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_exec_slot_ctx_t * slot_ctx, 11 0 : fd_stake_history_t * stake_history ) { 12 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/sysvar/stake_history.rs#L12 */ 13 0 : uchar enc[16392] = {0}; 14 : 15 0 : fd_bincode_encode_ctx_t encode = 16 0 : { .data = enc, 17 0 : .dataend = enc + sizeof(enc) }; 18 0 : if( FD_UNLIKELY( fd_stake_history_encode( stake_history, &encode )!=FD_BINCODE_SUCCESS ) ) 19 0 : FD_LOG_ERR(("fd_stake_history_encode failed")); 20 : 21 0 : fd_sysvar_set( slot_ctx->bank, slot_ctx->funk, slot_ctx->funk_txn, &fd_sysvar_owner_id, &fd_sysvar_stake_history_id, enc, sizeof(enc), slot_ctx->slot ); 22 0 : } 23 : 24 : fd_stake_history_t * 25 : fd_sysvar_stake_history_read( fd_funk_t * funk, 26 : fd_funk_txn_t * funk_txn, 27 0 : fd_spad_t * spad ) { 28 0 : FD_TXN_ACCOUNT_DECL( stake_rec ); 29 0 : int err = fd_txn_account_init_from_funk_readonly( stake_rec, &fd_sysvar_stake_history_id, funk, funk_txn ); 30 0 : if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) { 31 0 : return NULL; 32 0 : } 33 : 34 : /* This check is needed as a quirk of the fuzzer. If a sysvar account 35 : exists in the accounts database, but doesn't have any lamports, 36 : this means that the account does not exist. This wouldn't happen 37 : in a real execution environment. */ 38 0 : if( FD_UNLIKELY( stake_rec->vt->get_lamports( stake_rec )==0 ) ) { 39 0 : return NULL; 40 0 : } 41 : 42 0 : return fd_bincode_decode_spad( 43 0 : stake_history, spad, 44 0 : stake_rec->vt->get_data( stake_rec ), 45 0 : stake_rec->vt->get_data_len( stake_rec ), 46 0 : &err ); 47 0 : } 48 : 49 : void 50 0 : fd_sysvar_stake_history_init( fd_exec_slot_ctx_t * slot_ctx ) { 51 0 : fd_stake_history_t stake_history; 52 0 : fd_stake_history_new( &stake_history ); 53 0 : write_stake_history( slot_ctx, &stake_history ); 54 0 : } 55 : 56 : void 57 : fd_sysvar_stake_history_update( fd_exec_slot_ctx_t * slot_ctx, 58 : fd_epoch_stake_history_entry_pair_t * pair, 59 0 : fd_spad_t * runtime_spad ) { 60 : // Need to make this maybe zero copies of map... 61 0 : fd_stake_history_t * stake_history = fd_sysvar_stake_history_read( slot_ctx->funk, slot_ctx->funk_txn, runtime_spad ); 62 : 63 0 : if( stake_history->fd_stake_history_offset == 0 ) { 64 0 : stake_history->fd_stake_history_offset = stake_history->fd_stake_history_size - 1; 65 0 : } else { 66 0 : stake_history->fd_stake_history_offset--; 67 0 : } 68 : 69 0 : if( stake_history->fd_stake_history_len < stake_history->fd_stake_history_size ) { 70 0 : stake_history->fd_stake_history_len++; 71 0 : } 72 : 73 : // This should be done with a bit mask 74 0 : ulong idx = stake_history->fd_stake_history_offset; 75 : 76 0 : stake_history->fd_stake_history[ idx ].epoch = pair->epoch; 77 0 : stake_history->fd_stake_history[ idx ].entry.activating = pair->entry.activating; 78 0 : stake_history->fd_stake_history[ idx ].entry.effective = pair->entry.effective; 79 0 : stake_history->fd_stake_history[ idx ].entry.deactivating = pair->entry.deactivating; 80 : 81 0 : write_stake_history( slot_ctx, stake_history ); 82 0 : }