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