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 615 : uchar out_mem[ static FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ] ) { 8 615 : fd_blockhashes_t const * bhq = &bank->f.block_hash_queue; 9 : 10 615 : ulong queue_sz = fd_blockhash_deq_cnt( bhq->d.deque ); 11 615 : ulong out_max = fd_ulong_min( queue_sz, FD_SYSVAR_RECENT_HASHES_CAP ); 12 : 13 615 : uchar * enc = out_mem; 14 615 : fd_memcpy( enc, &out_max, sizeof(ulong) ); 15 : 16 615 : enc += sizeof(ulong); 17 : 18 615 : ulong out_idx = 0UL; 19 615 : for( fd_blockhash_deq_iter_t iter = fd_blockhash_deq_iter_init_rev( bhq->d.deque ); 20 92097 : out_idx<FD_SYSVAR_RECENT_HASHES_CAP && 21 92097 : !fd_blockhash_deq_iter_done_rev( bhq->d.deque, iter ); 22 91482 : out_idx++, iter = fd_blockhash_deq_iter_prev( bhq->d.deque, iter ) ) { 23 91482 : fd_blockhash_info_t const * n = fd_blockhash_deq_iter_ele_const( bhq->d.deque, iter ); 24 91482 : fd_memcpy( enc, n->hash.uc, 32 ); 25 91482 : FD_STORE( ulong, enc+32, n->lamports_per_signature ); 26 91482 : enc += 40; 27 91482 : } 28 615 : } 29 : 30 : void 31 : fd_sysvar_recent_hashes_init( fd_bank_t * bank, 32 : fd_accdb_t * accdb, 33 0 : fd_capture_ctx_t * capture_ctx ) { 34 0 : uchar enc[ FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ] = {0}; 35 0 : encode_rbh_from_blockhash_queue( bank, enc ); 36 0 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_recent_block_hashes_id, enc, FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ); 37 0 : } 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 615 : fd_hash_t const * hash ) { 43 615 : fd_blockhashes_t * bhq = &bank->f.block_hash_queue; 44 615 : fd_blockhash_info_t * bh = fd_blockhashes_push_new( bhq, hash ); 45 615 : bh->lamports_per_signature = bank->f.rbh_lamports_per_sig; 46 615 : } 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 615 : fd_capture_ctx_t * capture_ctx ) { 57 615 : register_blockhash( bank, &bank->f.poh ); 58 : 59 615 : uchar enc[ FD_SYSVAR_RECENT_HASHES_BINCODE_SZ ] = {0}; 60 615 : encode_rbh_from_blockhash_queue( bank, enc ); 61 615 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_recent_block_hashes_id, enc, sizeof(enc) ); 62 615 : } 63 : 64 : int 65 : fd_sysvar_recent_hashes_validate( uchar const * data, 66 61069 : ulong sz ) { 67 61069 : if( FD_UNLIKELY( sz < sizeof(ulong)) ) return 0; 68 61069 : ulong len = FD_LOAD( ulong, data ); 69 61069 : data += sizeof(ulong); sz -= sizeof(ulong); 70 61069 : ulong min_sz; 71 61069 : if( FD_UNLIKELY( __builtin_umull_overflow( len, 40UL, &min_sz ) ) ) return 0; 72 61069 : if( FD_UNLIKELY( sz < min_sz ) ) return 0; 73 61069 : return 1; 74 61069 : }