Line data Source code
1 : #include "fd_borrowed_account.h" 2 : 3 : int 4 : fd_borrowed_account_get_data_mut( fd_borrowed_account_t * borrowed_acct, 5 : uchar * * data_out, 6 0 : ulong * dlen_out ) { 7 0 : fd_txn_account_t * acct = borrowed_acct->acct; 8 : 9 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L824 */ 10 0 : int err; 11 0 : fd_borrowed_account_can_data_be_changed( borrowed_acct, &err ); 12 0 : if( FD_UNLIKELY( err ) ) { 13 0 : return err; 14 0 : } 15 : 16 0 : if ( data_out != NULL ) 17 0 : *data_out = acct->vt->get_data_mut( acct ); 18 0 : if ( dlen_out != NULL ) 19 0 : *dlen_out = acct->vt->get_data_len( acct ); 20 : 21 0 : return FD_EXECUTOR_INSTR_SUCCESS; 22 0 : } 23 : 24 : int 25 : fd_borrowed_account_set_owner( fd_borrowed_account_t * borrowed_acct, 26 0 : fd_pubkey_t const * owner ) { 27 0 : fd_txn_account_t * acct = borrowed_acct->acct; 28 : 29 : /* Only the owner can assign a new owner 30 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L741 */ 31 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_owned_by_current_program( borrowed_acct ) ) ) { 32 0 : return FD_EXECUTOR_INSTR_ERR_MODIFIED_PROGRAM_ID; 33 0 : } 34 : 35 : /* And only if the account is writable 36 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L745 */ 37 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_writable( borrowed_acct ) ) ) { 38 0 : return FD_EXECUTOR_INSTR_ERR_MODIFIED_PROGRAM_ID; 39 0 : } 40 : 41 : /* And only if the account is not executable 42 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L749 */ 43 0 : if( FD_UNLIKELY( fd_borrowed_account_is_executable_internal( borrowed_acct ) ) ) { 44 0 : return FD_EXECUTOR_INSTR_ERR_MODIFIED_PROGRAM_ID; 45 0 : } 46 : 47 : /* And only if the data is zero-initialized or empty 48 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L753 */ 49 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_zeroed( borrowed_acct ) ) ) { 50 0 : return FD_EXECUTOR_INSTR_ERR_MODIFIED_PROGRAM_ID; 51 0 : } 52 : 53 : /* Don't copy the account if the owner does not change 54 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L757 */ 55 0 : if( !memcmp( acct->vt->get_owner( acct ), owner, sizeof( fd_pubkey_t ) ) ) { 56 0 : return FD_EXECUTOR_INSTR_SUCCESS; 57 0 : } 58 : 59 : /* Agave self.touch() is a no-op */ 60 : 61 : /* Copy into owner 62 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L761 */ 63 0 : acct->vt->set_owner( acct, owner ); 64 0 : return FD_EXECUTOR_INSTR_SUCCESS; 65 0 : } 66 : 67 : /* Overwrites the number of lamports of this account (transaction wide) 68 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L773 */ 69 : int 70 : fd_borrowed_account_set_lamports( fd_borrowed_account_t * borrowed_acct, 71 0 : ulong lamports ) { 72 0 : fd_txn_account_t * acct = borrowed_acct->acct; 73 : 74 : /* An account not owned by the program cannot have its blanace decrease 75 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L775 */ 76 0 : if( FD_UNLIKELY( ( !fd_borrowed_account_is_owned_by_current_program( borrowed_acct ) ) && 77 0 : ( lamports < acct->vt->get_lamports( acct ) ) ) ) { 78 0 : return FD_EXECUTOR_INSTR_ERR_EXTERNAL_ACCOUNT_LAMPORT_SPEND; 79 0 : } 80 : 81 : /* The balance of read-only may not change 82 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L779 */ 83 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_writable( borrowed_acct ) ) ) { 84 0 : return FD_EXECUTOR_INSTR_ERR_READONLY_LAMPORT_CHANGE; 85 0 : } 86 : 87 : /* The balance of executable accounts may not change 88 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L783 */ 89 0 : if( FD_UNLIKELY( fd_borrowed_account_is_executable_internal( borrowed_acct ) ) ) { 90 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_LAMPORT_CHANGE; 91 0 : } 92 : 93 : /* Don't copy the account if the lamports do not change 94 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L787 */ 95 0 : if( acct->vt->get_lamports( acct ) == lamports ) { 96 0 : return FD_EXECUTOR_INSTR_SUCCESS; 97 0 : } 98 : 99 : /* Agave self.touch() is a no-op */ 100 : 101 0 : acct->vt->set_lamports( acct, lamports ); 102 0 : return FD_EXECUTOR_INSTR_SUCCESS; 103 0 : } 104 : 105 : int 106 : fd_borrowed_account_set_data_from_slice( fd_borrowed_account_t * borrowed_acct, 107 : uchar const * data, 108 0 : ulong data_sz ) { 109 0 : fd_txn_account_t * acct = borrowed_acct->acct; 110 : 111 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L865 */ 112 0 : int err; 113 0 : if ( FD_UNLIKELY( !fd_borrowed_account_can_data_be_resized( borrowed_acct, data_sz, &err ) ) ) { 114 0 : return err; 115 0 : } 116 : 117 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L866 */ 118 0 : if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_changed( borrowed_acct, &err ) ) ) { 119 0 : return err; 120 0 : } 121 : 122 : /* Agave self.touch() is a no-op */ 123 : 124 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L868 */ 125 0 : if( FD_UNLIKELY( !fd_borrowed_account_update_accounts_resize_delta( borrowed_acct, data_sz, &err ) ) ) { 126 0 : return err; 127 0 : } 128 : 129 : /* AccountSharedData::set_data_from_slice() */ 130 0 : acct->vt->set_data( acct, data, data_sz ); 131 : 132 0 : return FD_EXECUTOR_INSTR_SUCCESS; 133 0 : } 134 : 135 : int 136 : fd_borrowed_account_set_data_length( fd_borrowed_account_t * borrowed_acct, 137 0 : ulong new_len ) { 138 0 : fd_txn_account_t * acct = borrowed_acct->acct; 139 0 : int err = FD_EXECUTOR_INSTR_SUCCESS; 140 : 141 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L883 */ 142 0 : if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_resized( borrowed_acct, new_len, &err ) ) ) { 143 0 : return err; 144 0 : } 145 : 146 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L884 */ 147 0 : if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_changed( borrowed_acct, &err ) ) ) { 148 0 : return err; 149 0 : } 150 : 151 0 : ulong old_len = acct->vt->get_data_len( acct ); 152 : 153 : /* Don't copy the account if the length does not change 154 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L886 */ 155 0 : if( old_len==new_len ) { 156 0 : return FD_EXECUTOR_INSTR_SUCCESS; 157 0 : } 158 : 159 : /* Agave self.touch() is a no-op */ 160 : 161 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L890 */ 162 0 : if( FD_UNLIKELY( !fd_borrowed_account_update_accounts_resize_delta( borrowed_acct, new_len, &err ) ) ) { 163 0 : return err; 164 0 : } 165 : 166 : /* Resize the account 167 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L891 */ 168 0 : acct->vt->resize( acct, new_len ); 169 0 : return FD_EXECUTOR_INSTR_SUCCESS; 170 0 : } 171 : 172 : int 173 : fd_borrowed_account_set_executable( fd_borrowed_account_t * borrowed_acct, 174 0 : int is_executable ) { 175 0 : fd_txn_account_t * acct = borrowed_acct->acct; 176 : 177 : /* To become executable an account must be rent exempt 178 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1003-L1006 */ 179 0 : fd_rent_t const * rent = fd_bank_rent_query( borrowed_acct->instr_ctx->txn_ctx->bank ); 180 0 : if( FD_UNLIKELY( acct->vt->get_lamports( acct ) < fd_rent_exempt_minimum_balance( rent, acct->vt->get_data_len( acct ) ) ) ) { 181 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_ACCOUNT_NOT_RENT_EXEMPT; 182 0 : } 183 : 184 : /* Only the owner can set the exectuable flag 185 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1011 */ 186 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_owned_by_current_program( borrowed_acct ) ) ) { 187 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED; 188 0 : } 189 : 190 : /* And only if the account is writable 191 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1015 */ 192 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_writable( borrowed_acct ) ) ) { 193 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED; 194 0 : } 195 : 196 : /* One can not clear the executable flag 197 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1019 */ 198 0 : if( FD_UNLIKELY( fd_borrowed_account_is_executable_internal( borrowed_acct ) && !is_executable ) ) { 199 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED; 200 0 : } 201 : 202 : /* Don't copy the account if the exectuable flag does not change 203 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1023 */ 204 0 : if( fd_borrowed_account_is_executable( borrowed_acct ) == is_executable ) { 205 0 : return FD_EXECUTOR_INSTR_SUCCESS; 206 0 : } 207 : 208 : /* Agave self.touch() is a no-op */ 209 : 210 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1027 */ 211 0 : acct->vt->set_executable( acct, is_executable ); 212 : 213 0 : return FD_EXECUTOR_INSTR_SUCCESS; 214 0 : } 215 : 216 : int 217 : fd_borrowed_account_update_accounts_resize_delta( fd_borrowed_account_t * borrowed_acct, 218 : ulong new_len, 219 0 : int * err ) { 220 0 : fd_exec_instr_ctx_t const * instr_ctx = borrowed_acct->instr_ctx; 221 0 : fd_txn_account_t * acct = borrowed_acct->acct; 222 0 : ulong size_delta = fd_ulong_sat_sub( new_len, acct->vt->get_data_len( acct ) ); 223 : 224 : /* TODO: The size delta should never exceed the value of ULONG_MAX so this 225 : could be replaced with a normal addition. However to match execution with 226 : the agave client, this is being left as a sat add */ 227 0 : instr_ctx->txn_ctx->accounts_resize_delta = fd_ulong_sat_add( instr_ctx->txn_ctx->accounts_resize_delta, size_delta ); 228 0 : *err = FD_EXECUTOR_INSTR_SUCCESS; 229 0 : return 1; 230 0 : }