Line data Source code
1 : #include "fd_sysvar_instructions.h" 2 : #include "../fd_runtime.h" 3 : #include "../fd_system_ids.h" 4 : 5 : static ulong 6 0 : instructions_serialized_size( fd_txn_t const * txn ) { 7 0 : ushort instr_cnt = txn->instr_cnt; 8 0 : ulong serialized_size = sizeof(ushort) // num_instructions 9 0 : + (sizeof(ushort)*instr_cnt); // instruction offsets 10 : 11 0 : for( ushort i=0; i<instr_cnt; i++ ) { 12 0 : ushort data_sz = txn->instr[i].data_sz; 13 0 : ushort acct_cnt = txn->instr[i].acct_cnt; 14 : 15 0 : serialized_size += sizeof(ushort); // num_accounts; 16 : 17 0 : serialized_size += acct_cnt * ( 18 0 : sizeof(uchar) // flags (is_signer, is_writeable) 19 0 : + sizeof(fd_pubkey_t) // pubkey 20 0 : ); 21 : 22 0 : serialized_size += sizeof(fd_pubkey_t) // program_id pubkey 23 0 : + sizeof(ushort) // instr_data_len; 24 0 : + data_sz; // instr_data; 25 : 26 0 : } 27 : 28 0 : serialized_size += sizeof(ushort); // current_instr_idx 29 : 30 0 : return serialized_size; 31 0 : } 32 : 33 : /* https://github.com/anza-xyz/agave/blob/v2.1.1/svm/src/account_loader.rs#L547-L576 */ 34 : void 35 : fd_sysvar_instructions_serialize_account( fd_runtime_t * runtime, 36 : fd_txn_in_t const * txn_in, 37 : fd_txn_out_t * txn_out, 38 0 : ulong txn_idx ) { 39 0 : fd_txn_t const * txn = TXN( txn_in->txn ); 40 0 : ulong serialized_sz = instructions_serialized_size( txn ); 41 : 42 0 : fd_account_meta_t * meta = txn_out->accounts.account[ txn_idx ].meta; 43 : /* Agave sets up the borrowed account for the instructions sysvar to contain 44 : default values except for the data which is serialized into the account. */ 45 : 46 0 : fd_memcpy( meta->owner, &fd_sysvar_owner_id, sizeof(fd_pubkey_t) ); 47 0 : meta->lamports = 0UL; 48 0 : meta->executable = 0; 49 0 : meta->dlen = (uint)serialized_sz; 50 : 51 0 : runtime->accounts.starting_lamports[txn_idx] = 0UL; 52 0 : runtime->accounts.starting_dlen[txn_idx] = serialized_sz; 53 : 54 0 : uchar * serialized_instructions = fd_account_data( meta ); 55 0 : ulong offset = 0; 56 : 57 : // num_instructions 58 0 : ushort instr_cnt = txn->instr_cnt; 59 0 : FD_STORE( ushort, serialized_instructions + offset, instr_cnt); 60 0 : offset += sizeof(ushort); 61 : 62 : // instruction offsets 63 0 : uchar * serialized_instruction_offsets = serialized_instructions + offset; 64 0 : offset += (ushort)(sizeof(ushort) * instr_cnt); 65 : 66 : // serialize instructions 67 0 : for( ushort i=0; i<instr_cnt; ++i ) { 68 : // set the instruction offset 69 0 : FD_STORE( ushort, serialized_instruction_offsets, (ushort)offset ); 70 0 : serialized_instruction_offsets += sizeof(ushort); 71 : 72 0 : fd_txn_instr_t const * instr = &txn->instr[i]; 73 : 74 : // num_accounts 75 0 : FD_STORE( ushort, serialized_instructions + offset, instr->acct_cnt ); 76 0 : offset += sizeof(ushort); 77 : 78 0 : uchar const * instr_accts = fd_txn_get_instr_accts( instr, txn_in->txn->payload ); 79 0 : for( ushort j=0; j<instr->acct_cnt; j++ ) { 80 0 : uchar idx_in_txn = instr_accts[j]; 81 0 : uchar is_writable = (uchar)fd_runtime_account_is_writable_idx( txn_in, txn_out, idx_in_txn ); 82 0 : uchar is_signer = (uchar)fd_txn_is_signer( txn, idx_in_txn ); 83 0 : uchar flags = (uchar)( ((!!is_signer)*FD_INSTR_ACCT_FLAGS_IS_SIGNER) | ((!!is_writable)*FD_INSTR_ACCT_FLAGS_IS_WRITABLE) ); 84 : 85 : // flags 86 0 : FD_STORE( uchar, serialized_instructions + offset, flags ); 87 0 : offset += sizeof(uchar); 88 : 89 : // pubkey 90 0 : FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_out->accounts.keys[ idx_in_txn ] ); 91 0 : offset += sizeof(fd_pubkey_t); 92 0 : } 93 : 94 : // program_id_pubkey 95 0 : FD_STORE( fd_pubkey_t, serialized_instructions + offset, txn_out->accounts.keys[ instr->program_id ] ); 96 0 : offset += sizeof(fd_pubkey_t); 97 : 98 : // instr_data_len 99 0 : FD_STORE( ushort, serialized_instructions + offset, instr->data_sz ); 100 0 : offset += sizeof(ushort); 101 : 102 : // instr_data 103 0 : uchar const * instr_data = fd_txn_get_instr_data( instr, txn_in->txn->payload ); 104 0 : fd_memcpy( serialized_instructions + offset, instr_data, instr->data_sz ); 105 0 : offset += instr->data_sz; 106 0 : } 107 : 108 0 : FD_STORE( ushort, serialized_instructions + offset, 0 ); 109 0 : offset += sizeof(ushort); 110 0 : } 111 : 112 : /* Stores the current instruction index in the instructions sysvar account. 113 : https://github.com/anza-xyz/solana-sdk/blob/instructions-sysvar%40v2.2.1/instructions-sysvar/src/lib.rs#L164-L167 */ 114 : void 115 : fd_sysvar_instructions_update_current_instr_idx( fd_account_meta_t * meta, 116 0 : ushort current_instr_idx ) { 117 : /* Extra safety checks */ 118 0 : if( FD_UNLIKELY( meta->dlen<sizeof(ushort) ) ) { 119 0 : return; 120 0 : } 121 : 122 0 : uchar * serialized_current_instr_idx = fd_account_data( meta ) + (meta->dlen - sizeof(ushort)); 123 0 : FD_STORE( ushort, serialized_current_instr_idx, current_instr_idx ); 124 0 : }