Line data Source code
1 : #include "../fd_executor.h"
2 : #include "fd_system_program.h"
3 : #include "../fd_acc_mgr.h"
4 : #include "../fd_borrowed_account.h"
5 : #include "../fd_system_ids.h"
6 : #include "../fd_pubkey_utils.h"
7 : #include "../sysvar/fd_sysvar_rent.h"
8 : #include "../context/fd_exec_epoch_ctx.h"
9 : #include "../context/fd_exec_slot_ctx.h"
10 : #include "../context/fd_exec_txn_ctx.h"
11 :
12 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L42-L68
13 :
14 : Partial port of system_processor::Address::create, only covering the
15 : case of the "seed" input actually existing. Note that this doesn't
16 : "create" an address, but rather re-derives from PDA inputs and checks
17 : that the result matches some expected value. */
18 :
19 : static int
20 : verify_seed_address( fd_exec_instr_ctx_t * ctx,
21 : fd_pubkey_t const * expected,
22 : fd_pubkey_t const * base,
23 : char const * seed,
24 : ulong seed_sz,
25 0 : fd_pubkey_t const * owner ) {
26 :
27 0 : fd_pubkey_t actual[1];
28 0 : do {
29 0 : int err = fd_pubkey_create_with_seed(
30 0 : ctx,
31 0 : base->uc,
32 0 : seed,
33 0 : seed_sz,
34 0 : owner->uc,
35 0 : actual->uc );
36 0 : if( FD_UNLIKELY( err ) ) return err;
37 0 : } while(0);
38 :
39 0 : if( FD_UNLIKELY( 0!=memcmp( actual->uc, expected->uc, sizeof(fd_pubkey_t) ) ) ) {
40 : /* Log msg_sz can be more or less than 127 bytes */
41 0 : fd_log_collector_printf_inefficient_max_512( ctx,
42 0 : "Create: address %s does not match derived address %s",
43 0 : FD_BASE58_ENC_32_ALLOCA( expected ),
44 0 : FD_BASE58_ENC_32_ALLOCA( actual ) );
45 0 : ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
46 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
47 0 : }
48 :
49 0 : return 0;
50 0 : }
51 :
52 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L183
53 : https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L182
54 :
55 : Matches Solana Labs system_processor::transfer_verified */
56 :
57 : static int
58 : fd_system_program_transfer_verified( fd_exec_instr_ctx_t * ctx,
59 : ulong transfer_amount,
60 : ulong from_acct_idx,
61 0 : ulong to_acct_idx ) {
62 0 : int err;
63 :
64 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L191-L192 */
65 :
66 0 : fd_guarded_borrowed_account_t from;
67 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, from_acct_idx, &from );
68 :
69 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L193-L196 */
70 :
71 0 : if( from.acct->const_meta->dlen != 0UL ) {
72 0 : fd_log_collector_msg_literal( ctx, "Transfer: `from` must not carry data" );
73 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
74 0 : }
75 :
76 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L197-L205 */
77 :
78 0 : if( transfer_amount > from.acct->const_meta->info.lamports ) {
79 : /* Max msg_sz: 45 - 6 + 20 + 20 = 79 < 127 => we can use printf */
80 0 : fd_log_collector_printf_dangerous_max_127( ctx, "Transfer: insufficient lamports %lu, need %lu", from.acct->const_meta->info.lamports, transfer_amount );
81 0 : ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_RESULT_WITH_NEGATIVE_LAMPORTS;
82 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
83 0 : }
84 :
85 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L207 */
86 :
87 0 : err = fd_borrowed_account_checked_sub_lamports( &from, transfer_amount );
88 : /* Note: this err can never happen because of the check above */
89 0 : if( FD_UNLIKELY( err ) ) return err;
90 :
91 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L208 */
92 :
93 0 : fd_borrowed_account_drop( &from );
94 :
95 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L209-L210 */
96 :
97 0 : fd_guarded_borrowed_account_t to;
98 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, to_acct_idx, &to );
99 :
100 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L211 */
101 :
102 0 : err = fd_borrowed_account_checked_add_lamports( &to, transfer_amount );
103 0 : if( FD_UNLIKELY( err ) ) return err;
104 :
105 0 : return 0;
106 0 : }
107 :
108 : /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L214
109 :
110 : Matches system_processor::transfer */
111 :
112 : static int
113 : fd_system_program_transfer( fd_exec_instr_ctx_t * ctx,
114 : ulong transfer_amount,
115 : ulong from_acct_idx,
116 0 : ulong to_acct_idx ) {
117 :
118 : /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L222-L232 */
119 :
120 0 : if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, from_acct_idx ) ) ) {
121 : /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
122 0 : fd_log_collector_printf_dangerous_max_127( ctx,
123 0 : "Transfer: `from` account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->instr->acct_pubkeys[ from_acct_idx ] ) );
124 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
125 0 : }
126 :
127 : /* https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L234-L241 */
128 :
129 0 : return fd_system_program_transfer_verified( ctx, transfer_amount, from_acct_idx, to_acct_idx );
130 0 : }
131 :
132 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L71-L111
133 : https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L70
134 :
135 : Based on Solana Labs system_processor::allocate() */
136 :
137 : static int
138 : fd_system_program_allocate( fd_exec_instr_ctx_t * ctx,
139 : fd_borrowed_account_t * account,
140 : ulong space,
141 0 : fd_pubkey_t const * authority ) {
142 0 : int err;
143 :
144 : /* Assumes that acct_idx was bounds checked */
145 :
146 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L78-L85 */
147 :
148 0 : if( FD_UNLIKELY( !fd_instr_any_signed( ctx->instr, authority ) ) ) {
149 : /* Max msg_sz: 35 - 2 + 45 = 78 < 127 => we can use printf */
150 0 : fd_log_collector_printf_dangerous_max_127( ctx,
151 0 : "Allocate: 'to' account %s must sign", FD_BASE58_ENC_32_ALLOCA( authority ) );
152 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
153 0 : }
154 :
155 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L87-L96 */
156 :
157 0 : if( FD_UNLIKELY( ( account->acct->const_meta->dlen != 0UL ) |
158 0 : ( 0!=memcmp( account->acct->const_meta->info.owner, fd_solana_system_program_id.uc, 32UL ) ) ) ) {
159 : /* Max msg_sz: 35 - 2 + 45 = 78 < 127 => we can use printf */
160 0 : fd_log_collector_printf_dangerous_max_127( ctx,
161 0 : "Allocate: account %s already in use", FD_BASE58_ENC_32_ALLOCA( account->acct->pubkey ) );
162 0 : ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
163 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
164 0 : }
165 :
166 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L98-L106 */
167 :
168 0 : if( FD_UNLIKELY( space > FD_ACC_SZ_MAX ) ) {
169 : /* Max msg_sz: 48 - 6 + 2*20 = 82 < 127 => we can use printf */
170 0 : fd_log_collector_printf_dangerous_max_127( ctx,
171 0 : "Allocate: requested %lu, max allowed %lu", space, FD_ACC_SZ_MAX );
172 0 : ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_INVALID_ACCT_DATA_LEN;
173 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
174 0 : }
175 :
176 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L108 */
177 :
178 0 : err = fd_borrowed_account_set_data_length( account, space );
179 0 : if( FD_UNLIKELY( err ) ) {
180 0 : return err;
181 0 : }
182 :
183 0 : return FD_EXECUTOR_INSTR_SUCCESS;
184 0 : }
185 :
186 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L113-L131
187 : https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L112
188 :
189 : Based on Solana Labs system_processor::assign() */
190 :
191 : static int
192 : fd_system_program_assign( fd_exec_instr_ctx_t * ctx,
193 : fd_borrowed_account_t * account,
194 : fd_pubkey_t const * owner,
195 0 : fd_pubkey_t const * authority ) {
196 : /* Assumes addr_idx was bounds checked */
197 :
198 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L121-L123 */
199 :
200 0 : if( 0==memcmp( account->acct->const_meta->info.owner, owner->uc, sizeof(fd_pubkey_t) ) )
201 0 : return 0;
202 :
203 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L125-L128 */
204 :
205 0 : if( FD_UNLIKELY( !fd_instr_any_signed( ctx->instr, authority ) ) ) {
206 : /* Max msg_sz: 28 - 2 + 45 = 71 < 127 => we can use printf */
207 0 : fd_log_collector_printf_dangerous_max_127( ctx,
208 0 : "Assign: account %s must sign", FD_BASE58_ENC_32_ALLOCA( authority ) );
209 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
210 0 : }
211 :
212 0 : return fd_borrowed_account_set_owner( account, owner );
213 0 : }
214 :
215 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L133-L143
216 :
217 : Based on Solana Labs system_processor::allocate_and_assign() */
218 :
219 : static int
220 : fd_system_program_allocate_and_assign( fd_exec_instr_ctx_t * ctx,
221 : fd_borrowed_account_t * account,
222 : ulong space,
223 : fd_pubkey_t const * owner,
224 0 : fd_pubkey_t const * authority ) {
225 :
226 0 : do {
227 0 : int err = fd_system_program_allocate( ctx, account, space, authority );
228 0 : if( FD_UNLIKELY( err ) ) return err;
229 0 : } while(0);
230 0 : return fd_system_program_assign( ctx, account, owner, authority );
231 :
232 0 : }
233 :
234 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L146-L181
235 : https://github.com/anza-xyz/agave/blob/v2.0.9/programs/system/src/system_processor.rs#L145
236 :
237 : Matches Solana Labs system_processor::create_account() */
238 :
239 : static int
240 : fd_system_program_create_account( fd_exec_instr_ctx_t * ctx,
241 : ulong from_acct_idx,
242 : ulong to_acct_idx,
243 : ulong lamports,
244 : ulong space,
245 : fd_pubkey_t const * owner,
246 0 : fd_pubkey_t const * authority ) {
247 0 : int err;
248 :
249 : /* if it looks like the to account is already in use, bail
250 : https://github.com/anza-xyz/agave/blob/v2.1.14/programs/system/src/system_processor.rs#L159-L172 */
251 :
252 0 : do {
253 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L160-L161 */
254 :
255 0 : fd_guarded_borrowed_account_t to;
256 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, to_acct_idx, &to );
257 :
258 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L162-L169 */
259 :
260 0 : if( FD_UNLIKELY( to.acct->const_meta->info.lamports ) ) {
261 : /* Max msg_sz: 41 - 2 + 45 = 84 < 127 => we can use printf */
262 0 : fd_log_collector_printf_dangerous_max_127( ctx,
263 0 : "Create Account: account %s already in use", FD_BASE58_ENC_32_ALLOCA( to.acct->pubkey ) );
264 0 : ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ACCT_ALREADY_IN_USE;
265 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
266 0 : }
267 :
268 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L171 */
269 :
270 0 : err = fd_system_program_allocate_and_assign( ctx, &to, space, owner, authority );
271 0 : if( FD_UNLIKELY( err ) ) return err;
272 :
273 : /* Implicit drop
274 : https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L172 */
275 0 : } while (0);
276 :
277 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L173-L180 */
278 :
279 0 : return fd_system_program_transfer( ctx, lamports, from_acct_idx, to_acct_idx );
280 0 : }
281 :
282 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L327-L352
283 :
284 : Matches Solana Labs system_processor SystemInstruction::CreateAccount { ... } => { ... } */
285 :
286 : int
287 : fd_system_program_exec_create_account( fd_exec_instr_ctx_t * ctx,
288 0 : fd_system_program_instruction_create_account_t const * create_acc ) {
289 :
290 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L332 */
291 :
292 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
293 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
294 :
295 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L333-L339
296 : Authorization check is lifted out from 'allocate' to here. */
297 :
298 0 : ulong const from_acct_idx = 0UL;
299 0 : ulong const to_acct_idx = 1UL;
300 0 : return fd_system_program_create_account(
301 0 : ctx,
302 0 : from_acct_idx,
303 0 : to_acct_idx,
304 0 : create_acc->lamports,
305 0 : create_acc->space,
306 0 : &create_acc->owner,
307 0 : &ctx->instr->acct_pubkeys[to_acct_idx] );
308 0 : }
309 :
310 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L381-L393
311 :
312 : Matches Solana Labs system_processor SystemInstruction::Assign { ... } => { ... } */
313 :
314 : int
315 : fd_system_program_exec_assign( fd_exec_instr_ctx_t * ctx,
316 0 : fd_pubkey_t const * owner ) {
317 0 : int err;
318 :
319 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L382 */
320 :
321 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
322 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
323 :
324 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L383-L384 */
325 :
326 0 : fd_guarded_borrowed_account_t account;
327 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
328 :
329 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L385-L391
330 : system_processor::Address::create eliminated (dead code) */
331 :
332 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L392 */
333 :
334 0 : err = fd_system_program_assign( ctx, &account, owner, account.acct->pubkey );
335 0 : if( FD_UNLIKELY( err ) ) return err;
336 :
337 : /* Implicit drop */
338 :
339 0 : return 0;
340 0 : }
341 :
342 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L394-L404
343 :
344 : Matches Solana Labs system_processor SystemInstruction::Transfer { ... } => { ... } */
345 :
346 : int
347 : fd_system_program_exec_transfer( fd_exec_instr_ctx_t * ctx,
348 0 : ulong transfer_amount ) {
349 :
350 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L395 */
351 :
352 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) )
353 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
354 :
355 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L396-L402 */
356 :
357 0 : return fd_system_program_transfer( ctx, transfer_amount, 0UL, 1UL );
358 0 : }
359 :
360 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L353
361 :
362 : Matches Solana Labs system_processor SystemInstruction::CreateAccountWithSeed { ... } => { ... } */
363 :
364 : int
365 : fd_system_program_exec_create_account_with_seed( fd_exec_instr_ctx_t * ctx,
366 0 : fd_system_program_instruction_create_account_with_seed_t const * args ) {
367 :
368 0 : fd_instr_info_t const * instr = ctx->instr;
369 :
370 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L360 */
371 :
372 0 : if( FD_UNLIKELY( instr->acct_cnt < 2 ) )
373 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
374 :
375 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L361-L367 */
376 :
377 0 : do {
378 0 : int err = verify_seed_address(
379 0 : ctx,
380 0 : &instr->acct_pubkeys[1],
381 0 : &args->base,
382 0 : (char const *)args->seed,
383 0 : args->seed_len,
384 0 : &args->owner );
385 0 : if( FD_UNLIKELY( err ) ) return err;
386 0 : } while(0);
387 :
388 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L368-L379 */
389 :
390 0 : ulong const from_acct_idx = 0UL;
391 0 : ulong const to_acct_idx = 1UL;
392 0 : return fd_system_program_create_account(
393 0 : ctx,
394 0 : from_acct_idx,
395 0 : to_acct_idx,
396 0 : args->lamports,
397 0 : args->space,
398 0 : &args->owner,
399 0 : &args->base );
400 0 : }
401 :
402 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L504-L516
403 :
404 : Matches Solana Labs system_processor SystemInstruction::Allocate { ... } => { ... } */
405 :
406 : int
407 : fd_system_program_exec_allocate( fd_exec_instr_ctx_t * ctx,
408 0 : ulong space ) {
409 0 : int err;
410 :
411 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L505 */
412 :
413 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
414 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
415 :
416 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L506-L507 */
417 0 : fd_guarded_borrowed_account_t account;
418 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
419 :
420 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L508-L514
421 : system_processor::Address::create eliminated (dead code) */
422 :
423 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L515
424 : Authorization check is lifted out from 'allocate' to here. */
425 :
426 0 : err = fd_system_program_allocate( ctx, &account, space, account.acct->pubkey );
427 0 : if( FD_UNLIKELY( err ) ) return err;
428 :
429 : /* Implicit drop */
430 :
431 0 : return 0;
432 0 : }
433 :
434 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L517-L541
435 :
436 : Matches Solana Labs system_processor SystemInstruction::AllocateWithSeed { ... } => { ... } */
437 :
438 : int
439 : fd_system_program_exec_allocate_with_seed( fd_exec_instr_ctx_t * ctx,
440 0 : fd_system_program_instruction_allocate_with_seed_t const * args ) {
441 0 : int err;
442 :
443 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L523 */
444 :
445 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
446 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
447 :
448 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#524-525 */
449 :
450 0 : fd_guarded_borrowed_account_t account;
451 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
452 :
453 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L526-L532 */
454 :
455 0 : err = verify_seed_address(
456 0 : ctx,
457 0 : account.acct->pubkey,
458 0 : &args->base,
459 0 : (char const *)args->seed,
460 0 : args->seed_len,
461 0 : &args->owner );
462 0 : if( FD_UNLIKELY( err ) ) return err;
463 :
464 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L533-L540
465 : Authorization check is lifted out from 'allocate' to here. */
466 :
467 0 : err = fd_system_program_allocate_and_assign(
468 0 : ctx,
469 0 : &account,
470 0 : args->space,
471 0 : &args->owner,
472 0 : &args->base );
473 0 : if( FD_UNLIKELY( err ) ) return err;
474 :
475 : /* Implicit drop */
476 :
477 0 : return 0;
478 0 : }
479 :
480 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L542-L554
481 :
482 : Matches Solana Labs system_processor SystemInstruction::AssignWithSeed { ... } => { ... } */
483 :
484 : int
485 : fd_system_program_exec_assign_with_seed( fd_exec_instr_ctx_t * ctx,
486 0 : fd_system_program_instruction_assign_with_seed_t const * args ) {
487 0 : int err;
488 :
489 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#543 */
490 :
491 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) )
492 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
493 :
494 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L544-L545 */
495 :
496 0 : fd_guarded_borrowed_account_t account;
497 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &account );
498 :
499 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L546-L552 */
500 :
501 0 : err = verify_seed_address(
502 0 : ctx,
503 0 : account.acct->pubkey,
504 0 : &args->base,
505 0 : (char const *)args->seed,
506 0 : args->seed_len,
507 0 : &args->owner );
508 0 : if( FD_UNLIKELY( err ) ) return err;
509 :
510 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L553
511 : Authorization check is lifted out from 'assign' to here. */
512 :
513 0 : err = fd_system_program_assign( ctx, &account, &args->owner, &args->base );
514 0 : if( FD_UNLIKELY( err ) ) return err;
515 :
516 : /* Implicit drop */
517 :
518 0 : return 0;
519 0 : }
520 :
521 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L405-L422
522 :
523 : Matches Solana Labs system_processor SystemInstruction::TransferWithSeed { ... } => { ... } */
524 :
525 : int
526 : fd_system_program_exec_transfer_with_seed( fd_exec_instr_ctx_t * ctx,
527 0 : fd_system_program_instruction_transfer_with_seed_t const * args ) {
528 :
529 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L410 */
530 :
531 0 : if( FD_UNLIKELY( ctx->instr->acct_cnt < 3 ) )
532 0 : return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
533 :
534 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L411-L421
535 : Inlined call to system_processor::transfer_with_seed */
536 :
537 0 : ulong const from_idx = 0UL;
538 0 : ulong const from_base_idx = 1UL;
539 0 : ulong const to_idx = 2UL;
540 :
541 0 : if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, from_base_idx ) ) ) {
542 : /* Max msg_sz: 37 - 2 + 45 = 80 < 127 => we can use printf */
543 0 : fd_log_collector_printf_dangerous_max_127( ctx,
544 0 : "Transfer: 'from' account %s must sign", FD_BASE58_ENC_32_ALLOCA( &ctx->instr->acct_pubkeys[ from_base_idx ] ) );
545 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
546 0 : }
547 :
548 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L283-L290 */
549 :
550 0 : fd_pubkey_t address_from_seed[1];
551 0 : do {
552 0 : int err = fd_pubkey_create_with_seed(
553 0 : ctx,
554 0 : ctx->instr->acct_pubkeys[ from_base_idx ].uc,
555 0 : (char const *)args->from_seed,
556 0 : args->from_seed_len,
557 0 : args->from_owner.uc,
558 0 : address_from_seed->uc );
559 0 : if( FD_UNLIKELY( err ) ) return err;
560 0 : } while(0);
561 :
562 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L292-L303 */
563 :
564 0 : if( FD_UNLIKELY( 0!=memcmp( address_from_seed->uc,
565 0 : ctx->instr->acct_pubkeys[ from_idx ].uc,
566 0 : sizeof(fd_pubkey_t) ) ) ) {
567 : /* Log msg_sz can be more or less than 127 bytes */
568 0 : fd_log_collector_printf_inefficient_max_512( ctx,
569 0 : "Transfer: 'from' address %s does not match derived address %s",
570 0 : FD_BASE58_ENC_32_ALLOCA( &ctx->instr->acct_pubkeys[ from_idx ] ),
571 0 : FD_BASE58_ENC_32_ALLOCA( address_from_seed ) );
572 0 : ctx->txn_ctx->custom_err = FD_SYSTEM_PROGRAM_ERR_ADDR_WITH_SEED_MISMATCH;
573 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
574 0 : }
575 :
576 : /* https://github.com/solana-labs/solana/blob/v1.17.22/programs/system/src/system_processor.rs#L305-L312 */
577 0 : return fd_system_program_transfer_verified( ctx, args->lamports, from_idx, to_idx );
578 0 : }
579 :
580 : int
581 0 : fd_system_program_execute( fd_exec_instr_ctx_t * ctx ) {
582 0 : FD_EXEC_CU_UPDATE( ctx, 150UL );
583 :
584 : /* Deserialize the SystemInstruction enum */
585 0 : uchar * data = ctx->instr->data;
586 0 : if( FD_UNLIKELY( data==NULL ) ) {
587 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
588 0 : }
589 :
590 0 : fd_bincode_decode_ctx_t decode = {
591 0 : .data = data,
592 0 : .dataend = data + ctx->instr->data_sz
593 0 : };
594 :
595 0 : ulong total_sz = 0UL;
596 0 : int decode_err = fd_system_program_instruction_decode_footprint( &decode, &total_sz );
597 0 : if( FD_UNLIKELY( decode_err ) ) {
598 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
599 0 : }
600 :
601 0 : uchar * mem = fd_spad_alloc( ctx->txn_ctx->spad, fd_system_program_instruction_align(), total_sz );
602 0 : if( FD_UNLIKELY( !mem ) ) {
603 0 : FD_LOG_ERR(( "Unable to allocate memory for system program instruction" ));
604 0 : }
605 :
606 0 : fd_system_program_instruction_t * instruction = fd_system_program_instruction_decode( mem, &decode );
607 : /* If the decoder consumes more than the TXN_MTU (1232) bytes, the transaction
608 : should fail. */
609 0 : if( FD_UNLIKELY( (ulong)data + FD_TXN_MTU < (ulong)decode.data ) ) {
610 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
611 0 : }
612 :
613 0 : int result = FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
614 :
615 0 : switch( instruction->discriminant ) {
616 0 : case fd_system_program_instruction_enum_create_account: {
617 0 : result = fd_system_program_exec_create_account(
618 0 : ctx, &instruction->inner.create_account );
619 0 : break;
620 0 : }
621 0 : case fd_system_program_instruction_enum_assign: {
622 0 : result = fd_system_program_exec_assign(
623 0 : ctx, &instruction->inner.assign );
624 0 : break;
625 0 : }
626 0 : case fd_system_program_instruction_enum_transfer: {
627 0 : result = fd_system_program_exec_transfer(
628 0 : ctx, instruction->inner.transfer );
629 0 : break;
630 0 : }
631 0 : case fd_system_program_instruction_enum_create_account_with_seed: {
632 0 : result = fd_system_program_exec_create_account_with_seed(
633 0 : ctx, &instruction->inner.create_account_with_seed );
634 0 : break;
635 0 : }
636 0 : case fd_system_program_instruction_enum_advance_nonce_account: {
637 0 : result = fd_system_program_exec_advance_nonce_account( ctx );
638 0 : break;
639 0 : }
640 0 : case fd_system_program_instruction_enum_withdraw_nonce_account: {
641 0 : result = fd_system_program_exec_withdraw_nonce_account(
642 0 : ctx, instruction->inner.withdraw_nonce_account );
643 0 : break;
644 0 : }
645 0 : case fd_system_program_instruction_enum_initialize_nonce_account: {
646 0 : result = fd_system_program_exec_initialize_nonce_account(
647 0 : ctx, &instruction->inner.initialize_nonce_account );
648 0 : break;
649 0 : }
650 0 : case fd_system_program_instruction_enum_authorize_nonce_account: {
651 0 : result = fd_system_program_exec_authorize_nonce_account(
652 0 : ctx, &instruction->inner.authorize_nonce_account );
653 0 : break;
654 0 : }
655 0 : case fd_system_program_instruction_enum_allocate: {
656 0 : result = fd_system_program_exec_allocate( ctx, instruction->inner.allocate );
657 0 : break;
658 0 : }
659 0 : case fd_system_program_instruction_enum_allocate_with_seed: {
660 : // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L525
661 0 : result = fd_system_program_exec_allocate_with_seed(
662 0 : ctx, &instruction->inner.allocate_with_seed );
663 0 : break;
664 0 : }
665 0 : case fd_system_program_instruction_enum_assign_with_seed: {
666 : // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L545
667 0 : result = fd_system_program_exec_assign_with_seed(
668 0 : ctx, &instruction->inner.assign_with_seed );
669 0 : break;
670 0 : }
671 0 : case fd_system_program_instruction_enum_transfer_with_seed: {
672 : // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L412
673 0 : result = fd_system_program_exec_transfer_with_seed(
674 0 : ctx, &instruction->inner.transfer_with_seed );
675 0 : break;
676 0 : }
677 0 : case fd_system_program_instruction_enum_upgrade_nonce_account: {
678 : // https://github.com/solana-labs/solana/blob/b00d18cec4011bb452e3fe87a3412a3f0146942e/runtime/src/system_instruction_processor.rs#L491
679 0 : result = fd_system_program_exec_upgrade_nonce_account( ctx );
680 0 : break;
681 0 : }
682 0 : }
683 :
684 0 : return result;
685 0 : }
|