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