Line data Source code
1 : #include <stdio.h> 2 : #include "../fd_acc_mgr.h" 3 : #include "../fd_hashes.h" 4 : #include "fd_sysvar.h" 5 : #include "../fd_runtime.h" 6 : #include "../fd_system_ids.h" 7 : #include "../context/fd_exec_slot_ctx.h" 8 : 9 1452411 : #define FD_RECENT_BLOCKHASHES_ACCOUNT_MAX_SIZE sizeof(ulong) + FD_RECENT_BLOCKHASHES_MAX_ENTRIES * (sizeof(fd_hash_t) + sizeof(ulong)) 10 : 11 : // run --ledger /home/jsiegel/test-ledger --db /home/jsiegel/funk --cmd accounts --accounts /home/jsiegel/test-ledger/accounts/ --pages 15 --index-max 120000000 --start-slot 2 --end-slot 2 --start-id 35 --end-id 37 12 : // run --ledger /home/jsiegel/test-ledger --db /home/jsiegel/funk --cmd replay --pages 15 --index-max 120000000 --start-slot 0 --end-slot 3 13 : 14 : // {meta = {write_version_obsolete = 137, 15 : // data_len = 6008, pubkey = "\006\247\325\027\031,V\216\340\212\204_sҗ\210\317\003\\1E\262\032\263D\330\006.\251@\000"}, info = {lamports = 42706560, rent_epoch = 0, owner = "\006\247\325\027\030u\367)\307=\223@\217!a \006~،v\340\214(\177\301\224`\000\000\000", executable = 0 '\000', padding = "K\000\f\376\177\000"}, hash = {value = "\302Q\316\035qTY\347\352]\260\335\213\224R\227ԯ\366R\273\063H\345֑c\377\207/k\275"}} 16 : 17 : // owner: Sysvar1111111111111111111111111111111111111 pubkey: SysvarRecentB1ockHashes11111111111111111111 hash: E5YSehyvJ7xXcNnQjWCH9UhMJ1dxDBJ1RuuPh1Y3RZgg file: /home/jsiegel/test-ledger/accounts//2.37 18 : // {blockhash = JCidNXtcMXMWQwMDM3ZQq5pxaw3hQpNbeHg1KcstjuF4, fee_calculator={lamports_per_signature = 5000}} 19 : // {blockhash = GQN3oV8G1Ra3GCX76dE1YYJ6UjMyDreNCEWM4tZ39zj1, fee_calculator={lamports_per_signature = 5000}} 20 : // {blockhash = Ha5DVgnD1xSA8oQc337jtA3atEfQ4TFX1ajeZG1Y2tUx, fee_calculator={lamports_per_signature = 0}} 21 : 22 0 : void fd_sysvar_recent_hashes_init( fd_exec_slot_ctx_t* slot_ctx ) { 23 : // https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/fee_calculator.rs#L110 24 : 25 0 : if (slot_ctx->slot_bank.slot != 0) 26 0 : return; 27 : 28 0 : ulong sz = fd_recent_block_hashes_size(&slot_ctx->slot_bank.recent_block_hashes); 29 0 : if (sz < FD_RECENT_BLOCKHASHES_ACCOUNT_MAX_SIZE) 30 0 : sz = FD_RECENT_BLOCKHASHES_ACCOUNT_MAX_SIZE; 31 0 : uchar * enc = fd_alloca(1, sz); 32 0 : fd_memset(enc, 0, sz); 33 0 : fd_bincode_encode_ctx_t ctx; 34 0 : ctx.data = enc; 35 0 : ctx.dataend = enc + sz; 36 0 : if ( fd_recent_block_hashes_encode(&slot_ctx->slot_bank.recent_block_hashes, &ctx) ) 37 0 : FD_LOG_ERR(("fd_recent_block_hashes_encode failed")); 38 : 39 0 : fd_sysvar_set( slot_ctx, fd_sysvar_owner_id.key, &fd_sysvar_recent_block_hashes_id, enc, sz, slot_ctx->slot_bank.slot ); 40 0 : } 41 : 42 : // https://github.com/anza-xyz/agave/blob/e8750ba574d9ac7b72e944bc1227dc7372e3a490/accounts-db/src/blockhash_queue.rs#L113 43 : static void 44 830595 : register_blockhash( fd_exec_slot_ctx_t* slot_ctx, fd_hash_t const * hash ) { 45 830595 : fd_block_hash_queue_t * queue = &slot_ctx->slot_bank.block_hash_queue; 46 : // https://github.com/anza-xyz/agave/blob/e8750ba574d9ac7b72e944bc1227dc7372e3a490/accounts-db/src/blockhash_queue.rs#L114 47 830595 : queue->last_hash_index++; 48 830595 : if ( fd_hash_hash_age_pair_t_map_size( queue->ages_pool, queue->ages_root ) >= queue->max_age ) { 49 33 : fd_hash_hash_age_pair_t_mapnode_t * nn; 50 9933 : for ( fd_hash_hash_age_pair_t_mapnode_t * n = fd_hash_hash_age_pair_t_map_minimum( queue->ages_pool, queue->ages_root ); n; n = nn ) { 51 9900 : nn = fd_hash_hash_age_pair_t_map_successor( queue->ages_pool, n ); 52 : /* NOTE: Yes, this check is incorrect. It should be >= which caps the blockhash queue at max_age 53 : entries, but instead max_age + 1 entries are allowed to exist in the queue at once. This mimics 54 : Agave to stay conformant with their implementation. 55 : https://github.com/anza-xyz/agave/blob/e8750ba574d9ac7b72e944bc1227dc7372e3a490/accounts-db/src/blockhash_queue.rs#L109 */ 56 9900 : if ( queue->last_hash_index - n->elem.val.hash_index > queue->max_age ) { 57 0 : fd_hash_hash_age_pair_t_map_remove( queue->ages_pool, &queue->ages_root, n ); 58 0 : fd_hash_hash_age_pair_t_map_release( queue->ages_pool, n ); 59 0 : } 60 9900 : } 61 33 : } 62 : 63 830595 : fd_hash_hash_age_pair_t_mapnode_t * node = fd_hash_hash_age_pair_t_map_acquire( queue->ages_pool ); 64 830595 : node->elem = (fd_hash_hash_age_pair_t){ 65 830595 : .key = *hash, 66 830595 : .val = (fd_hash_age_t){ .hash_index = queue->last_hash_index, .fee_calculator = (fd_fee_calculator_t){.lamports_per_signature = slot_ctx->slot_bank.lamports_per_signature}, .timestamp = (ulong)fd_log_wallclock() } 67 830595 : }; 68 : // https://github.com/anza-xyz/agave/blob/e8750ba574d9ac7b72e944bc1227dc7372e3a490/accounts-db/src/blockhash_queue.rs#L121-L128 69 830595 : fd_hash_hash_age_pair_t_map_insert( slot_ctx->slot_bank.block_hash_queue.ages_pool, &slot_ctx->slot_bank.block_hash_queue.ages_root, node ); 70 : // https://github.com/anza-xyz/agave/blob/e8750ba574d9ac7b72e944bc1227dc7372e3a490/accounts-db/src/blockhash_queue.rs#L130 71 830595 : fd_memcpy( queue->last_hash, hash, sizeof(fd_hash_t) ); 72 830595 : } 73 : 74 830595 : void fd_sysvar_recent_hashes_update( fd_exec_slot_ctx_t* slot_ctx ) { 75 : 76 830595 : fd_block_block_hash_entry_t * hashes = slot_ctx->slot_bank.recent_block_hashes.hashes; 77 830595 : fd_bincode_destroy_ctx_t ctx2 = { .valloc = slot_ctx->valloc }; 78 1036701 : while (deq_fd_block_block_hash_entry_t_cnt(hashes) >= FD_RECENT_BLOCKHASHES_MAX_ENTRIES) 79 206106 : fd_block_block_hash_entry_destroy( deq_fd_block_block_hash_entry_t_pop_tail_nocopy( hashes ), &ctx2 ); 80 : 81 830595 : FD_TEST( !deq_fd_block_block_hash_entry_t_full(hashes) ); 82 830595 : fd_block_block_hash_entry_t * elem = deq_fd_block_block_hash_entry_t_push_head_nocopy(hashes); 83 830595 : fd_block_block_hash_entry_new(elem); 84 : // bank.poh is updated in fd_runtime_block_verify 85 830595 : fd_memcpy(elem->blockhash.hash, &slot_ctx->slot_bank.poh, sizeof(slot_ctx->slot_bank.poh)); 86 : 87 830595 : elem->fee_calculator.lamports_per_signature = slot_ctx->slot_bank.lamports_per_signature; 88 : 89 830595 : ulong sz = fd_recent_block_hashes_size(&slot_ctx->slot_bank.recent_block_hashes); 90 830595 : if (sz < FD_RECENT_BLOCKHASHES_ACCOUNT_MAX_SIZE) 91 621816 : sz = FD_RECENT_BLOCKHASHES_ACCOUNT_MAX_SIZE; 92 830595 : unsigned char *enc = fd_alloca(1, sz); 93 830595 : memset(enc, 0, sz); 94 830595 : fd_bincode_encode_ctx_t ctx; 95 830595 : ctx.data = enc; 96 830595 : ctx.dataend = enc + sz; 97 830595 : if ( fd_recent_block_hashes_encode(&slot_ctx->slot_bank.recent_block_hashes, &ctx) ) 98 0 : FD_LOG_ERR(("fd_recent_block_hashes_encode failed")); 99 : 100 830595 : fd_sysvar_set( slot_ctx, fd_sysvar_owner_id.key, &fd_sysvar_recent_block_hashes_id, enc, sz, slot_ctx->slot_bank.slot ); 101 : 102 830595 : register_blockhash( slot_ctx, &slot_ctx->slot_bank.poh ); 103 830595 : }