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->pubkey, rec->meta, 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.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 : }
|