Line data Source code
1 : #include "fd_sysvar.h" 2 : #include "../fd_system_ids.h" 3 : #include "../fd_hashes.h" 4 : #include "../fd_runtime.h" 5 : 6 : #include "fd_sysvar_rent.h" 7 : 8 : /* https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank.rs#L1813 */ 9 : void 10 : fd_sysvar_account_update( 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 : fd_pubkey_t const * address, 15 : void const * data, 16 462 : ulong sz ) { 17 462 : fd_rent_t const * rent = fd_bank_rent_query( bank ); 18 462 : ulong const min_bal = fd_rent_exempt_minimum_balance( rent, sz ); 19 : 20 462 : fd_txn_account_t rec[1]; 21 462 : fd_funk_rec_prepare_t prepare = {0}; 22 462 : fd_txn_account_init_from_funk_mutable( rec, address, accdb, xid, 1, sz, &prepare ); 23 462 : fd_lthash_value_t prev_hash[1]; 24 462 : fd_hashes_account_lthash( address, fd_txn_account_get_meta( rec ), fd_txn_account_get_data( rec ), prev_hash ); 25 : 26 462 : ulong const slot = fd_bank_slot_get( bank ); 27 462 : ulong const lamports_before = fd_txn_account_get_lamports( rec ); 28 462 : ulong const lamports_after = fd_ulong_max( lamports_before, min_bal ); 29 462 : fd_txn_account_set_lamports( rec, lamports_after ); 30 462 : fd_txn_account_set_owner ( rec, &fd_sysvar_owner_id ); 31 462 : fd_txn_account_set_slot ( rec, slot ); 32 462 : fd_txn_account_set_data ( rec, data, sz ); 33 : 34 462 : ulong lamports_minted; 35 462 : if( FD_UNLIKELY( __builtin_usubl_overflow( lamports_after, lamports_before, &lamports_minted ) ) ) { 36 0 : char name[ FD_BASE58_ENCODED_32_SZ ]; fd_base58_encode_32( address->uc, NULL, name ); 37 0 : FD_LOG_CRIT(( "fd_sysvar_account_update: lamports overflowed: address=%s lamports_before=%lu lamports_after=%lu", 38 0 : name, lamports_before, lamports_after )); 39 0 : } 40 : 41 462 : if( lamports_minted ) { 42 9 : ulong cap = fd_bank_capitalization_get( bank ); 43 9 : fd_bank_capitalization_set( bank, cap+lamports_minted ); 44 453 : } else if( lamports_before==lamports_after ) { 45 : /* no balance change */ 46 453 : } else { 47 0 : __builtin_unreachable(); 48 0 : } 49 : 50 462 : fd_hashes_update_lthash( rec, prev_hash, bank, capture_ctx ); 51 462 : fd_txn_account_mutable_fini( rec, accdb, &prepare ); 52 : 53 462 : if( FD_UNLIKELY( fd_log_level_logfile()<=0 || fd_log_level_stderr()<=0 ) ) { 54 0 : char name[ FD_BASE58_ENCODED_32_SZ ]; fd_base58_encode_32( address->uc, NULL, name ); 55 0 : FD_LOG_DEBUG(( "Updated sysvar: address=%s data_sz=%lu slot=%lu lamports=%lu lamports_minted=%lu", 56 0 : name, sz, slot, lamports_after, lamports_minted )); 57 0 : } 58 462 : } 59 : 60 : int 61 : fd_sysvar_instr_acct_check( fd_exec_instr_ctx_t const * ctx, 62 : ulong idx, 63 0 : fd_pubkey_t const * addr_want ) { 64 : 65 0 : if( FD_UNLIKELY( idx >= ctx->instr->acct_cnt ) ) { 66 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_ACC; 67 0 : } 68 : 69 0 : ushort idx_in_txn = ctx->instr->accounts[idx].index_in_transaction; 70 0 : fd_pubkey_t const * addr_have = &ctx->txn_out->accounts.account_keys[ idx_in_txn ]; 71 0 : if( FD_UNLIKELY( 0!=memcmp( addr_have, addr_want, sizeof(fd_pubkey_t) ) ) ) { 72 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ARG; 73 0 : } 74 : 75 0 : return FD_EXECUTOR_INSTR_SUCCESS; 76 0 : }