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