Line data Source code
1 : #include "fd_sysvar_slot_hashes.h" 2 : #include "fd_sysvar.h" 3 : #include "../fd_acc_mgr.h" 4 : #include "../fd_system_ids.h" 5 : #include "../../accdb/fd_accdb_impl_v1.h" 6 : 7 : /* FIXME These constants should be header defines */ 8 : 9 : void 10 : fd_sysvar_slot_hashes_write( 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 0 : fd_slot_hashes_global_t * slot_hashes_global ) { 15 0 : uchar __attribute__((aligned(FD_SYSVAR_SLOT_HASHES_ALIGN))) enc[ FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ] = {0}; 16 0 : fd_bincode_encode_ctx_t ctx = { 17 0 : .data = enc, 18 0 : .dataend = enc + FD_SYSVAR_SLOT_HASHES_BINCODE_SZ, 19 0 : }; 20 0 : if( fd_slot_hashes_encode_global( slot_hashes_global, &ctx ) ) { 21 0 : FD_LOG_ERR(("fd_slot_hashes_encode failed")); 22 0 : } 23 0 : fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_slot_hashes_id, enc, FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ); 24 0 : } 25 : 26 : ulong 27 0 : fd_sysvar_slot_hashes_footprint( ulong slot_hashes_cap ) { 28 0 : return sizeof(fd_slot_hashes_global_t) + 29 0 : deq_fd_slot_hash_t_footprint( slot_hashes_cap ) + deq_fd_slot_hash_t_align(); 30 0 : } 31 : 32 : void * 33 : fd_sysvar_slot_hashes_new( void * mem, 34 0 : ulong slot_hashes_cap ) { 35 0 : if( FD_UNLIKELY( !mem ) ) { 36 0 : FD_LOG_ERR(( "Unable to allocate memory for slot hashes" )); 37 0 : } 38 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_SYSVAR_SLOT_HASHES_ALIGN ) ) ) { 39 0 : FD_LOG_ERR(( "Memory for slot hashes is not aligned" )); 40 0 : } 41 : 42 0 : fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)mem; 43 : 44 0 : uchar * slot_hash_mem = (uchar*)fd_ulong_align_up( (ulong)((uchar *)mem + sizeof(fd_slot_hashes_global_t)), deq_fd_slot_hash_t_align() ); 45 0 : deq_fd_slot_hash_t_new( (void*)slot_hash_mem, slot_hashes_cap ); 46 0 : slot_hashes_global->hashes_offset = (ulong)slot_hash_mem - (ulong)slot_hashes_global; 47 : 48 0 : return slot_hashes_global; 49 0 : } 50 : 51 : fd_slot_hashes_global_t * 52 : fd_sysvar_slot_hashes_join( void * shmem, 53 0 : fd_slot_hash_t ** slot_hash ) { 54 0 : fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)shmem; 55 0 : *slot_hash = deq_fd_slot_hash_t_join( (uchar*)shmem + slot_hashes_global->hashes_offset ); 56 : 57 0 : return slot_hashes_global; 58 0 : } 59 : 60 : void * 61 : fd_sysvar_slot_hashes_leave( fd_slot_hashes_global_t * slot_hashes_global, 62 0 : fd_slot_hash_t * slot_hash ) { 63 0 : deq_fd_slot_hash_t_leave( slot_hash ); 64 : 65 0 : return slot_hashes_global; 66 0 : } 67 : 68 : void * 69 0 : fd_sysvar_slot_hashes_delete( void * mem ) { 70 0 : void * slot_hash_mem = (void *)fd_ulong_align_up( (ulong)((uchar *)mem + sizeof(fd_slot_hashes_global_t)), deq_fd_slot_hash_t_align() ); 71 0 : deq_fd_slot_hash_t_delete( slot_hash_mem ); 72 : 73 0 : return mem; 74 0 : } 75 : 76 : /* https://github.com/anza-xyz/agave/blob/b11ca828cfc658b93cb86a6c5c70561875abe237/runtime/src/bank.rs#L2283-L2294 */ 77 : void 78 : fd_sysvar_slot_hashes_update( fd_bank_t * bank, 79 : fd_accdb_user_t * accdb, 80 : fd_funk_txn_xid_t const * xid, 81 0 : fd_capture_ctx_t * capture_ctx ) { 82 0 : fd_funk_t * funk = fd_accdb_user_v1_funk( accdb ); 83 0 : uchar __attribute__((aligned(FD_SYSVAR_SLOT_HASHES_ALIGN))) slot_hashes_mem[FD_SYSVAR_SLOT_HASHES_FOOTPRINT]; 84 0 : fd_slot_hashes_global_t * slot_hashes_global = fd_sysvar_slot_hashes_read( funk, xid, slot_hashes_mem ); 85 0 : fd_slot_hash_t * hashes = NULL; 86 0 : if( FD_UNLIKELY( !slot_hashes_global ) ) { 87 : /* Note: Agave's implementation initializes a new slot_hashes if it doesn't already exist (refer to above URL). */ 88 0 : slot_hashes_global = fd_sysvar_slot_hashes_new( slot_hashes_mem, FD_SYSVAR_SLOT_HASHES_CAP ); 89 0 : } 90 0 : slot_hashes_global = fd_sysvar_slot_hashes_join( slot_hashes_global, &hashes ); 91 : 92 0 : uchar found = 0; 93 0 : for( deq_fd_slot_hash_t_iter_t iter = deq_fd_slot_hash_t_iter_init( hashes ); 94 0 : !deq_fd_slot_hash_t_iter_done( hashes, iter ); 95 0 : iter = deq_fd_slot_hash_t_iter_next( hashes, iter ) ) { 96 0 : fd_slot_hash_t * ele = deq_fd_slot_hash_t_iter_ele( hashes, iter ); 97 0 : if( ele->slot == fd_bank_parent_slot_get( bank ) ) { 98 0 : fd_hash_t const * bank_hash = fd_bank_bank_hash_query( bank ); 99 0 : memcpy( &ele->hash, bank_hash, sizeof(fd_hash_t) ); 100 0 : found = 1; 101 0 : } 102 0 : } 103 : 104 0 : if( !found ) { 105 : // https://github.com/firedancer-io/solana/blob/08a1ef5d785fe58af442b791df6c4e83fe2e7c74/runtime/src/bank.rs#L2371 106 0 : fd_slot_hash_t slot_hash = { 107 0 : .hash = fd_bank_bank_hash_get( bank ), // parent hash? 108 0 : .slot = fd_bank_parent_slot_get( bank ), // parent_slot 109 0 : }; 110 : 111 0 : if( deq_fd_slot_hash_t_full( hashes ) ) 112 0 : memset( deq_fd_slot_hash_t_pop_tail_nocopy( hashes ), 0, sizeof(fd_slot_hash_t) ); 113 : 114 0 : deq_fd_slot_hash_t_push_head( hashes, slot_hash ); 115 0 : } 116 : 117 0 : fd_sysvar_slot_hashes_write( bank, accdb, xid, capture_ctx, slot_hashes_global ); 118 0 : fd_sysvar_slot_hashes_leave( slot_hashes_global, hashes ); 119 0 : } 120 : 121 : fd_slot_hashes_global_t * 122 : fd_sysvar_slot_hashes_read( fd_funk_t * funk, 123 : fd_funk_txn_xid_t const * xid, 124 0 : uchar * slot_hashes_mem ) { 125 0 : fd_txn_account_t rec[1]; 126 0 : int err = fd_txn_account_init_from_funk_readonly( rec, (fd_pubkey_t const *)&fd_sysvar_slot_hashes_id, funk, xid ); 127 0 : if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) { 128 0 : return NULL; 129 0 : } 130 : 131 : /* This check is needed as a quirk of the fuzzer. If a sysvar account 132 : exists in the accounts database, but doesn't have any lamports, 133 : this means that the account does not exist. This wouldn't happen 134 : in a real execution environment. */ 135 0 : if( FD_UNLIKELY( fd_txn_account_get_lamports( rec )==0UL ) ) { 136 0 : return NULL; 137 0 : } 138 : 139 0 : fd_bincode_decode_ctx_t decode = { 140 0 : .data = fd_txn_account_get_data( rec ), 141 0 : .dataend = fd_txn_account_get_data( rec ) + fd_txn_account_get_data_len( rec ) 142 0 : }; 143 : 144 0 : return fd_slot_hashes_decode_global( slot_hashes_mem, &decode ); 145 0 : }