@@ -2,7 +2,6 @@ use pinocchio::{
2
2
account_info:: AccountInfo , default_panic_handler, no_allocator, program_entrypoint,
3
3
program_error:: ProgramError , pubkey:: Pubkey , ProgramResult ,
4
4
} ;
5
- use spl_token_interface:: instruction:: TokenInstruction ;
6
5
7
6
use crate :: processor:: * ;
8
7
@@ -14,218 +13,245 @@ default_panic_handler!();
14
13
15
14
/// Process an instruction.
16
15
///
16
+ /// In the first stage, the entrypoint checks the discriminator of the instruction data
17
+ /// to determine whether the instruction is a "batch" instruction or a "regular" instruction.
18
+ /// This avoids nesting of "batch" instructions, since it is not sound to have a "batch"
19
+ /// instruction inside another "batch" instruction.
20
+ #[ inline( always) ]
21
+ pub fn process_instruction (
22
+ _program_id : & Pubkey ,
23
+ accounts : & [ AccountInfo ] ,
24
+ instruction_data : & [ u8 ] ,
25
+ ) -> ProgramResult {
26
+ let [ discriminator, remaining @ ..] = instruction_data else {
27
+ return Err ( ProgramError :: InvalidInstructionData ) ;
28
+ } ;
29
+
30
+ if * discriminator == 255 {
31
+ // 255 - Batch
32
+ #[ cfg( feature = "logging" ) ]
33
+ pinocchio:: msg!( "Instruction: Batch" ) ;
34
+
35
+ return process_batch ( accounts, remaining) ;
36
+ }
37
+
38
+ inner_process_instruction ( accounts, instruction_data)
39
+ }
40
+
41
+ /// Process a "regular" instruction.
42
+ ///
17
43
/// The processor of the token program is divided into two parts to reduce the overhead
18
44
/// of having a large `match` statement. The first part of the processor handles the
19
45
/// most common instructions, while the second part handles the remaining instructions.
46
+ ///
20
47
/// The rationale is to reduce the overhead of making multiple comparisons for popular
21
48
/// instructions.
22
49
///
23
- /// Instructions on the first part of the processor:
50
+ /// Instructions on the first part of the inner processor:
24
51
///
25
- /// - `0`: `InitializeMint`
26
- /// - `3`: `Transfer`
27
- /// - `7`: `MintTo`
28
- /// - `9`: `CloseAccount`
52
+ /// - `0`: `InitializeMint`
53
+ /// - `1`: `InitializeAccount`
54
+ /// - `3`: `Transfer`
55
+ /// - `7`: `MintTo`
56
+ /// - `9`: `CloseAccount`
57
+ /// - `16`: `InitializeAccount2`
29
58
/// - `18`: `InitializeAccount3`
30
59
/// - `20`: `InitializeMint2`
31
60
#[ inline( always) ]
32
- pub fn process_instruction (
33
- _program_id : & Pubkey ,
61
+ pub ( crate ) fn inner_process_instruction (
34
62
accounts : & [ AccountInfo ] ,
35
63
instruction_data : & [ u8 ] ,
36
64
) -> ProgramResult {
37
- let ( discriminator, instruction_data) = instruction_data
38
- . split_first ( )
39
- . ok_or ( ProgramError :: InvalidInstructionData ) ?;
40
- let instruction = TokenInstruction :: try_from ( * discriminator) ?;
65
+ let [ discriminator, instruction_data @ ..] = instruction_data else {
66
+ return Err ( ProgramError :: InvalidInstructionData ) ;
67
+ } ;
41
68
42
- match instruction {
69
+ match * discriminator {
43
70
// 0 - InitializeMint
44
- TokenInstruction :: InitializeMint => {
71
+ 0 => {
45
72
#[ cfg( feature = "logging" ) ]
46
73
pinocchio:: msg!( "Instruction: InitializeMint" ) ;
47
74
48
75
process_initialize_mint ( accounts, instruction_data)
49
76
}
77
+ // 1 - InitializeAccount
78
+ 1 => {
79
+ #[ cfg( feature = "logging" ) ]
80
+ pinocchio:: msg!( "Instruction: InitializeAccount" ) ;
50
81
82
+ process_initialize_account ( accounts)
83
+ }
51
84
// 3 - Transfer
52
- TokenInstruction :: Transfer => {
85
+ 3 => {
53
86
#[ cfg( feature = "logging" ) ]
54
87
pinocchio:: msg!( "Instruction: Transfer" ) ;
55
88
56
89
process_transfer ( accounts, instruction_data)
57
90
}
58
91
// 7 - MintTo
59
- TokenInstruction :: MintTo => {
92
+ 7 => {
60
93
#[ cfg( feature = "logging" ) ]
61
94
pinocchio:: msg!( "Instruction: MintTo" ) ;
62
95
63
96
process_mint_to ( accounts, instruction_data)
64
97
}
65
98
// 9 - CloseAccount
66
- TokenInstruction :: CloseAccount => {
99
+ 9 => {
67
100
#[ cfg( feature = "logging" ) ]
68
101
pinocchio:: msg!( "Instruction: CloseAccount" ) ;
69
102
70
103
process_close_account ( accounts)
71
104
}
105
+ // 16 - InitializeAccount2
106
+ 16 => {
107
+ #[ cfg( feature = "logging" ) ]
108
+ pinocchio:: msg!( "Instruction: InitializeAccount2" ) ;
109
+
110
+ process_initialize_account2 ( accounts, instruction_data)
111
+ }
72
112
// 18 - InitializeAccount3
73
- TokenInstruction :: InitializeAccount3 => {
113
+ 18 => {
74
114
#[ cfg( feature = "logging" ) ]
75
115
pinocchio:: msg!( "Instruction: InitializeAccount3" ) ;
76
116
77
117
process_initialize_account3 ( accounts, instruction_data)
78
118
}
79
119
// 20 - InitializeMint2
80
- TokenInstruction :: InitializeMint2 => {
120
+ 20 => {
81
121
#[ cfg( feature = "logging" ) ]
82
122
pinocchio:: msg!( "Instruction: InitializeMint2" ) ;
83
123
84
124
process_initialize_mint2 ( accounts, instruction_data)
85
125
}
86
- _ => process_remaining_instruction ( accounts, instruction_data, instruction ) ,
126
+ d => inner_process_remaining_instruction ( accounts, instruction_data, d ) ,
87
127
}
88
128
}
89
129
90
- /// Process the remaining instructions .
130
+ /// Process a remaining "regular" instruction .
91
131
///
92
- /// This function is called by the `process_instruction` function if the discriminator
132
+ /// This function is called by the [`inner_process_instruction`] function if the discriminator
93
133
/// does not match any of the common instructions. This function is used to reduce the
94
- /// overhead of having a large `match` statement in the `process_instruction` function.
95
- fn process_remaining_instruction (
134
+ /// overhead of having a large `match` statement in the [`inner_process_instruction`] function.
135
+ fn inner_process_remaining_instruction (
96
136
accounts : & [ AccountInfo ] ,
97
137
instruction_data : & [ u8 ] ,
98
- instruction : TokenInstruction ,
138
+ discriminator : u8 ,
99
139
) -> ProgramResult {
100
- match instruction {
101
- // 1 - InitializeAccount
102
- TokenInstruction :: InitializeAccount => {
103
- #[ cfg( feature = "logging" ) ]
104
- pinocchio:: msg!( "Instruction: InitializeAccount" ) ;
105
-
106
- process_initialize_account ( accounts)
107
- }
140
+ match discriminator {
108
141
// 2 - InitializeMultisig
109
- TokenInstruction :: InitializeMultisig => {
142
+ 2 => {
110
143
#[ cfg( feature = "logging" ) ]
111
144
pinocchio:: msg!( "Instruction: InitializeMultisig" ) ;
112
145
113
146
process_initialize_multisig ( accounts, instruction_data)
114
147
}
115
148
// 4 - Approve
116
- TokenInstruction :: Approve => {
149
+ 4 => {
117
150
#[ cfg( feature = "logging" ) ]
118
151
pinocchio:: msg!( "Instruction: Approve" ) ;
119
152
120
153
process_approve ( accounts, instruction_data)
121
154
}
122
155
// 5 - Revoke
123
- TokenInstruction :: Revoke => {
156
+ 5 => {
124
157
#[ cfg( feature = "logging" ) ]
125
158
pinocchio:: msg!( "Instruction: Revoke" ) ;
126
159
127
160
process_revoke ( accounts, instruction_data)
128
161
}
129
162
// 6 - SetAuthority
130
- TokenInstruction :: SetAuthority => {
163
+ 6 => {
131
164
#[ cfg( feature = "logging" ) ]
132
165
pinocchio:: msg!( "Instruction: SetAuthority" ) ;
133
166
134
167
process_set_authority ( accounts, instruction_data)
135
168
}
136
169
// 8 - Burn
137
- TokenInstruction :: Burn => {
170
+ 8 => {
138
171
#[ cfg( feature = "logging" ) ]
139
172
pinocchio:: msg!( "Instruction: Burn" ) ;
140
173
141
174
process_burn ( accounts, instruction_data)
142
175
}
143
176
// 10 - FreezeAccount
144
- TokenInstruction :: FreezeAccount => {
177
+ 10 => {
145
178
#[ cfg( feature = "logging" ) ]
146
179
pinocchio:: msg!( "Instruction: FreezeAccount" ) ;
147
180
148
181
process_freeze_account ( accounts)
149
182
}
150
183
// 11 - ThawAccount
151
- TokenInstruction :: ThawAccount => {
184
+ 11 => {
152
185
#[ cfg( feature = "logging" ) ]
153
186
pinocchio:: msg!( "Instruction: ThawAccount" ) ;
154
187
155
188
process_thaw_account ( accounts)
156
189
}
157
190
// 12 - TransferChecked
158
- TokenInstruction :: TransferChecked => {
191
+ 12 => {
159
192
#[ cfg( feature = "logging" ) ]
160
193
pinocchio:: msg!( "Instruction: TransferChecked" ) ;
161
194
162
195
process_transfer_checked ( accounts, instruction_data)
163
196
}
164
197
// 13 - ApproveChecked
165
- TokenInstruction :: ApproveChecked => {
198
+ 13 => {
166
199
#[ cfg( feature = "logging" ) ]
167
200
pinocchio:: msg!( "Instruction: ApproveChecked" ) ;
168
201
169
202
process_approve_checked ( accounts, instruction_data)
170
203
}
171
204
// 14 - MintToChecked
172
- TokenInstruction :: MintToChecked => {
205
+ 14 => {
173
206
#[ cfg( feature = "logging" ) ]
174
207
pinocchio:: msg!( "Instruction: MintToChecked" ) ;
175
208
176
209
process_mint_to_checked ( accounts, instruction_data)
177
210
}
178
211
// 15 - BurnChecked
179
- TokenInstruction :: BurnChecked => {
212
+ 15 => {
180
213
#[ cfg( feature = "logging" ) ]
181
214
pinocchio:: msg!( "Instruction: BurnChecked" ) ;
182
215
183
216
process_burn_checked ( accounts, instruction_data)
184
217
}
185
- // 16 - InitializeAccount2
186
- TokenInstruction :: InitializeAccount2 => {
187
- #[ cfg( feature = "logging" ) ]
188
- pinocchio:: msg!( "Instruction: InitializeAccount2" ) ;
189
-
190
- process_initialize_account2 ( accounts, instruction_data)
191
- }
192
218
// 17 - SyncNative
193
- TokenInstruction :: SyncNative => {
219
+ 17 => {
194
220
#[ cfg( feature = "logging" ) ]
195
221
pinocchio:: msg!( "Instruction: SyncNative" ) ;
196
222
197
223
process_sync_native ( accounts)
198
224
}
199
225
// 19 - InitializeMultisig2
200
- TokenInstruction :: InitializeMultisig2 => {
226
+ 19 => {
201
227
#[ cfg( feature = "logging" ) ]
202
228
pinocchio:: msg!( "Instruction: InitializeMultisig2" ) ;
203
229
204
230
process_initialize_multisig2 ( accounts, instruction_data)
205
231
}
206
232
// 21 - GetAccountDataSize
207
- TokenInstruction :: GetAccountDataSize => {
233
+ 21 => {
208
234
#[ cfg( feature = "logging" ) ]
209
235
pinocchio:: msg!( "Instruction: GetAccountDataSize" ) ;
210
236
211
237
process_get_account_data_size ( accounts)
212
238
}
213
239
// 22 - InitializeImmutableOwner
214
- TokenInstruction :: InitializeImmutableOwner => {
240
+ 22 => {
215
241
#[ cfg( feature = "logging" ) ]
216
242
pinocchio:: msg!( "Instruction: InitializeImmutableOwner" ) ;
217
243
218
244
process_initialize_immutable_owner ( accounts)
219
245
}
220
246
// 23 - AmountToUiAmount
221
- TokenInstruction :: AmountToUiAmount => {
247
+ 23 => {
222
248
#[ cfg( feature = "logging" ) ]
223
249
pinocchio:: msg!( "Instruction: AmountToUiAmount" ) ;
224
250
225
251
process_amount_to_ui_amount ( accounts, instruction_data)
226
252
}
227
253
// 24 - UiAmountToAmount
228
- TokenInstruction :: UiAmountToAmount => {
254
+ 24 => {
229
255
#[ cfg( feature = "logging" ) ]
230
256
pinocchio:: msg!( "Instruction: UiAmountToAmount" ) ;
231
257
0 commit comments