Line data Source code
1 : #include "fd_sysvar_recent_hashes.h" 2 : #include "fd_sysvar.h" 3 : #include "../fd_system_ids.h" 4 : 5 : static void 6 : encode_rbh_from_blockhash_queue( fd_bank_t * bank, 7 534 : uchar out_mem[ static FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ] ) { 8 534 : fd_blockhashes_t const * bhq = &bank->f.block_hash_queue; 9 : 10 534 : ulong queue_sz = fd_blockhash_deq_cnt( bhq->d.deque ); 11 534 : ulong out_max = fd_ulong_min( queue_sz, FD_SYSVAR_RECENT_HASHES_CAP ); 12 : 13 534 : uchar * enc = out_mem; 14 534 : fd_memcpy( enc, &out_max, sizeof(ulong) ); 15 : 16 534 : enc += sizeof(ulong); 17 : 18 534 : ulong out_idx = 0UL; 19 534 : for( fd_blockhash_deq_iter_t iter = fd_blockhash_deq_iter_init_rev( bhq->d.deque ); 20 34671 : out_idx<FD_SYSVAR_RECENT_HASHES_CAP && 21 34671 : !fd_blockhash_deq_iter_done_rev( bhq->d.deque, iter ); 22 34137 : out_idx++, iter = fd_blockhash_deq_iter_prev( bhq->d.deque, iter ) ) { 23 34137 : fd_blockhash_info_t const * n = fd_blockhash_deq_iter_ele_const( bhq->d.deque, iter ); 24 34137 : fd_memcpy( enc, n->hash.uc, 32 ); 25 34137 : FD_STORE( ulong, enc+32, n->lamports_per_signature ); 26 34137 : enc += 40; 27 34137 : } 28 534 : } 29 : 30 : void 31 : fd_sysvar_recent_hashes_init( fd_bank_t * bank, 32 : fd_accdb_t * accdb, 33 3 : fd_capture_ctx_t * capture_ctx ) { 34 3 : uchar enc[ FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ] = {0}; 35 3 : encode_rbh_from_blockhash_queue( bank, enc ); 36 3 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_recent_block_hashes_id, enc, FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ); 37 3 : } 38 : 39 : // https://github.com/anza-xyz/agave/blob/e8750ba574d9ac7b72e944bc1227dc7372e3a490/accounts-db/src/blockhash_queue.rs#L113 40 : static void 41 : register_blockhash( fd_bank_t * bank, 42 531 : fd_hash_t const * hash ) { 43 531 : fd_blockhashes_t * bhq = &bank->f.block_hash_queue; 44 531 : fd_blockhash_info_t * bh = fd_blockhashes_push_new( bhq, hash ); 45 531 : bh->lamports_per_signature = bank->f.rbh_lamports_per_sig; 46 531 : } 47 : 48 : /* This implementation is more consistent with Agave's bank implementation for updating the block hashes sysvar: 49 : 1. Update the block hash queue with the latest poh 50 : 2. Take the first 150 blockhashes from the queue (or fewer if there are) 51 : 3. Manually serialize the recent blockhashes 52 : 4. Set the sysvar account with the new data */ 53 : void 54 : fd_sysvar_recent_hashes_update( fd_bank_t * bank, 55 : fd_accdb_t * accdb, 56 531 : fd_capture_ctx_t * capture_ctx ) { 57 531 : register_blockhash( bank, &bank->f.poh ); 58 : 59 531 : uchar enc[ FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ] = {0}; 60 531 : encode_rbh_from_blockhash_queue( bank, enc ); 61 531 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_recent_block_hashes_id, enc, sizeof(enc) ); 62 531 : } 63 : 64 : int 65 : fd_sysvar_recent_hashes_validate( uchar const * data, 66 7722 : ulong sz ) { 67 7722 : if( FD_UNLIKELY( sz < sizeof(ulong)) ) return 0; 68 7719 : ulong len = FD_LOAD( ulong, data ); 69 7719 : data += sizeof(ulong); sz -= sizeof(ulong); 70 7719 : ulong min_sz; 71 7719 : if( FD_UNLIKELY( __builtin_umull_overflow( len, 40UL, &min_sz ) ) ) return 0; 72 7719 : if( FD_UNLIKELY( sz < min_sz ) ) return 0; 73 7713 : return 1; 74 7719 : }