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->data; 18 0 : if ( dlen_out != NULL ) 19 0 : *dlen_out = acct->meta->dlen; 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->const_meta->info.owner, 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 : memcpy( acct->meta->info.owner, owner, sizeof(fd_pubkey_t) ); 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->const_meta->info.lamports ) ) ) { 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( fd_txn_account_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 : fd_txn_account_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->meta->dlen = data_sz; 131 0 : fd_memcpy( acct->data, data, data_sz ); 132 : 133 0 : return FD_EXECUTOR_INSTR_SUCCESS; 134 0 : } 135 : 136 : int 137 : fd_borrowed_account_set_data_length( fd_borrowed_account_t * borrowed_acct, 138 0 : ulong new_len ) { 139 0 : fd_txn_account_t * acct = borrowed_acct->acct; 140 0 : int err = FD_EXECUTOR_INSTR_SUCCESS; 141 : 142 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L883 */ 143 0 : if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_resized( borrowed_acct, new_len, &err ) ) ) { 144 0 : return err; 145 0 : } 146 : 147 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L884 */ 148 0 : if( FD_UNLIKELY( !fd_borrowed_account_can_data_be_changed( borrowed_acct, &err ) ) ) { 149 0 : return err; 150 0 : } 151 : 152 0 : ulong old_len = acct->const_meta->dlen; 153 : 154 : /* Don't copy the account if the length does not change 155 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L886 */ 156 0 : if( old_len==new_len ) { 157 0 : return FD_EXECUTOR_INSTR_SUCCESS; 158 0 : } 159 : 160 : /* Agave self.touch() is a no-op */ 161 : 162 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L890 */ 163 0 : if( FD_UNLIKELY( !fd_borrowed_account_update_accounts_resize_delta( borrowed_acct, new_len, &err ) ) ) { 164 0 : return err; 165 0 : } 166 : 167 : /* Resize the account 168 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L891 */ 169 0 : fd_txn_account_resize( acct, new_len ); 170 0 : return FD_EXECUTOR_INSTR_SUCCESS; 171 0 : } 172 : 173 : int 174 : fd_borrowed_account_set_executable( fd_borrowed_account_t * borrowed_acct, 175 0 : int is_executable ) { 176 0 : fd_txn_account_t * acct = borrowed_acct->acct; 177 : 178 : /* To become executable an account must be rent exempt 179 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1003-L1006 */ 180 0 : fd_rent_t const * rent = &borrowed_acct->instr_ctx->txn_ctx->rent; 181 0 : if( FD_UNLIKELY( acct->const_meta->info.lamports < fd_rent_exempt_minimum_balance( rent, acct->const_meta->dlen ) ) ) { 182 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_ACCOUNT_NOT_RENT_EXEMPT; 183 0 : } 184 : 185 : /* Only the owner can set the exectuable flag 186 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1011 */ 187 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_owned_by_current_program( borrowed_acct ) ) ) { 188 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED; 189 0 : } 190 : 191 : /* And only if the account is writable 192 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1015 */ 193 0 : if( FD_UNLIKELY( !fd_borrowed_account_is_writable( borrowed_acct ) ) ) { 194 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED; 195 0 : } 196 : 197 : /* One can not clear the executable flag 198 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1019 */ 199 0 : if( FD_UNLIKELY( fd_borrowed_account_is_executable_internal( borrowed_acct ) && !is_executable ) ) { 200 0 : return FD_EXECUTOR_INSTR_ERR_EXECUTABLE_MODIFIED; 201 0 : } 202 : 203 : /* Don't copy the account if the exectuable flag does not change 204 : https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1023 */ 205 0 : if( fd_borrowed_account_is_executable( borrowed_acct ) == is_executable ) { 206 0 : return FD_EXECUTOR_INSTR_SUCCESS; 207 0 : } 208 : 209 : /* Agave self.touch() is a no-op */ 210 : 211 : /* https://github.com/anza-xyz/agave/blob/v2.1.14/sdk/src/transaction_context.rs#L1027 */ 212 0 : fd_txn_account_set_executable( acct, is_executable ); 213 : 214 0 : return FD_EXECUTOR_INSTR_SUCCESS; 215 0 : } 216 : 217 : int 218 : fd_borrowed_account_update_accounts_resize_delta( fd_borrowed_account_t * borrowed_acct, 219 : ulong new_len, 220 0 : int * err ) { 221 0 : fd_exec_instr_ctx_t const * instr_ctx = borrowed_acct->instr_ctx; 222 0 : fd_txn_account_t * acct = borrowed_acct->acct; 223 0 : ulong size_delta = fd_ulong_sat_sub( new_len, acct->const_meta->dlen ); 224 : 225 : /* TODO: The size delta should never exceed the value of ULONG_MAX so this 226 : could be replaced with a normal addition. However to match execution with 227 : the agave client, this is being left as a sat add */ 228 0 : instr_ctx->txn_ctx->accounts_resize_delta = fd_ulong_sat_add( instr_ctx->txn_ctx->accounts_resize_delta, size_delta ); 229 0 : *err = FD_EXECUTOR_INSTR_SUCCESS; 230 0 : return 1; 231 0 : }