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