1use {
2 crate::prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
3 cbe_sdk::{
4 borsh::try_from_slice_unchecked,
5 compute_budget::{self, ComputeBudgetInstruction},
6 entrypoint::HEAP_LENGTH as MIN_HEAP_FRAME_BYTES,
7 instruction::{CompiledInstruction, InstructionError},
8 pubkey::Pubkey,
9 transaction::TransactionError,
10 },
11};
12
13pub const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000;
14pub const MAX_COMPUTE_UNIT_LIMIT: u32 = 1_400_000;
15const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024;
16
17#[derive(Debug)]
21pub enum LoadedAccountsDataLimitType {
22 V0,
23 }
25
26const DEFAULT_LOADED_ACCOUNTS_DATA_LIMIT: u32 = 10 * 1024 * 1024;
29pub fn get_default_loaded_accounts_data_limit(limit_type: &LoadedAccountsDataLimitType) -> u32 {
30 match limit_type {
31 LoadedAccountsDataLimitType::V0 => DEFAULT_LOADED_ACCOUNTS_DATA_LIMIT,
32 }
33}
34const MAX_LOADED_ACCOUNTS_DATA_LIMIT: u32 = 100 * 1024 * 1024;
38pub fn get_max_loaded_accounts_data_limit(limit_type: &LoadedAccountsDataLimitType) -> u32 {
39 match limit_type {
40 LoadedAccountsDataLimitType::V0 => MAX_LOADED_ACCOUNTS_DATA_LIMIT,
41 }
42}
43
44#[cfg(RUSTC_WITH_SPECIALIZATION)]
45impl ::cbe_frozen_abi::abi_example::AbiExample for ComputeBudget {
46 fn example() -> Self {
47 ComputeBudget::default()
49 }
50}
51
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
53pub struct ComputeBudget {
54 pub compute_unit_limit: u64,
58 pub accounts_data_size_limit: u64,
60 pub log_64_units: u64,
62 pub create_program_address_units: u64,
64 pub invoke_units: u64,
67 pub max_invoke_stack_height: usize,
72 pub max_instruction_trace_length: usize,
74 pub sha256_base_cost: u64,
76 pub sha256_byte_cost: u64,
78 pub sha256_max_slices: u64,
80 pub max_call_depth: usize,
82 pub stack_frame_size: usize,
84 pub log_pubkey_units: u64,
86 pub max_cpi_instruction_size: usize,
88 pub cpi_bytes_per_unit: u64,
90 pub sysvar_base_cost: u64,
92 pub secp256k1_recover_cost: u64,
94 pub syscall_base_cost: u64,
96 pub curve25519_edwards_validate_point_cost: u64,
98 pub curve25519_edwards_add_cost: u64,
100 pub curve25519_edwards_subtract_cost: u64,
102 pub curve25519_edwards_multiply_cost: u64,
104 pub curve25519_edwards_msm_base_cost: u64,
107 pub curve25519_edwards_msm_incremental_cost: u64,
110 pub curve25519_ristretto_validate_point_cost: u64,
112 pub curve25519_ristretto_add_cost: u64,
114 pub curve25519_ristretto_subtract_cost: u64,
116 pub curve25519_ristretto_multiply_cost: u64,
118 pub curve25519_ristretto_msm_base_cost: u64,
121 pub curve25519_ristretto_msm_incremental_cost: u64,
124 pub heap_size: Option<usize>,
126 pub heap_cost: u64,
129 pub mem_op_base_cost: u64,
131 pub alt_bn128_addition_cost: u64,
133 pub alt_bn128_multiplication_cost: u64,
135 pub alt_bn128_pairing_one_pair_cost_first: u64,
138 pub alt_bn128_pairing_one_pair_cost_other: u64,
139}
140
141impl Default for ComputeBudget {
142 fn default() -> Self {
143 Self::new(MAX_COMPUTE_UNIT_LIMIT as u64)
144 }
145}
146
147impl ComputeBudget {
148 pub fn new(compute_unit_limit: u64) -> Self {
149 ComputeBudget {
150 compute_unit_limit,
151 accounts_data_size_limit: DEFAULT_LOADED_ACCOUNTS_DATA_LIMIT as u64,
152 log_64_units: 100,
153 create_program_address_units: 1500,
154 invoke_units: 1000,
155 max_invoke_stack_height: 5,
156 max_instruction_trace_length: 64,
157 sha256_base_cost: 85,
158 sha256_byte_cost: 1,
159 sha256_max_slices: 20_000,
160 max_call_depth: 64,
161 stack_frame_size: 4_096,
162 log_pubkey_units: 100,
163 max_cpi_instruction_size: 1280, cpi_bytes_per_unit: 250, sysvar_base_cost: 100,
166 secp256k1_recover_cost: 25_000,
167 syscall_base_cost: 100,
168 curve25519_edwards_validate_point_cost: 159,
169 curve25519_edwards_add_cost: 473,
170 curve25519_edwards_subtract_cost: 475,
171 curve25519_edwards_multiply_cost: 2_177,
172 curve25519_edwards_msm_base_cost: 2_273,
173 curve25519_edwards_msm_incremental_cost: 758,
174 curve25519_ristretto_validate_point_cost: 169,
175 curve25519_ristretto_add_cost: 521,
176 curve25519_ristretto_subtract_cost: 519,
177 curve25519_ristretto_multiply_cost: 2_208,
178 curve25519_ristretto_msm_base_cost: 2303,
179 curve25519_ristretto_msm_incremental_cost: 788,
180 heap_size: None,
181 heap_cost: 8,
182 mem_op_base_cost: 10,
183 alt_bn128_addition_cost: 334,
184 alt_bn128_multiplication_cost: 3_840,
185 alt_bn128_pairing_one_pair_cost_first: 36_364,
186 alt_bn128_pairing_one_pair_cost_other: 12_121,
187 }
188 }
189
190 pub fn process_instructions<'a>(
191 &mut self,
192 instructions: impl Iterator<Item = (&'a Pubkey, &'a CompiledInstruction)>,
193 default_units_per_instruction: bool,
194 support_request_units_deprecated: bool,
195 cap_transaction_accounts_data_size: bool,
196 loaded_accounts_data_limit_type: LoadedAccountsDataLimitType,
197 ) -> Result<PrioritizationFeeDetails, TransactionError> {
198 let mut num_non_compute_budget_instructions: usize = 0;
199 let mut updated_compute_unit_limit = None;
200 let mut requested_heap_size = None;
201 let mut prioritization_fee = None;
202 let mut updated_accounts_data_size_limit = None;
203
204 for (i, (program_id, instruction)) in instructions.enumerate() {
205 if compute_budget::check_id(program_id) {
206 let invalid_instruction_data_error = TransactionError::InstructionError(
207 i as u8,
208 InstructionError::InvalidInstructionData,
209 );
210 let duplicate_instruction_error = TransactionError::DuplicateInstruction(i as u8);
211
212 match try_from_slice_unchecked(&instruction.data) {
213 Ok(ComputeBudgetInstruction::RequestUnitsDeprecated {
214 units: compute_unit_limit,
215 additional_fee,
216 }) if support_request_units_deprecated => {
217 if updated_compute_unit_limit.is_some() {
218 return Err(duplicate_instruction_error);
219 }
220 if prioritization_fee.is_some() {
221 return Err(duplicate_instruction_error);
222 }
223 updated_compute_unit_limit = Some(compute_unit_limit);
224 prioritization_fee =
225 Some(PrioritizationFeeType::Deprecated(additional_fee as u64));
226 }
227 Ok(ComputeBudgetInstruction::RequestHeapFrame(bytes)) => {
228 if requested_heap_size.is_some() {
229 return Err(duplicate_instruction_error);
230 }
231 requested_heap_size = Some((bytes, i as u8));
232 }
233 Ok(ComputeBudgetInstruction::SetComputeUnitLimit(compute_unit_limit)) => {
234 if updated_compute_unit_limit.is_some() {
235 return Err(duplicate_instruction_error);
236 }
237 updated_compute_unit_limit = Some(compute_unit_limit);
238 }
239 Ok(ComputeBudgetInstruction::SetComputeUnitPrice(micro_scoobies)) => {
240 if prioritization_fee.is_some() {
241 return Err(duplicate_instruction_error);
242 }
243 prioritization_fee =
244 Some(PrioritizationFeeType::ComputeUnitPrice(micro_scoobies));
245 }
246 Ok(ComputeBudgetInstruction::SetAccountsDataSizeLimit(bytes))
247 if cap_transaction_accounts_data_size =>
248 {
249 if updated_accounts_data_size_limit.is_some() {
250 return Err(duplicate_instruction_error);
251 }
252 updated_accounts_data_size_limit = Some(bytes);
253 }
254 _ => return Err(invalid_instruction_data_error),
255 }
256 } else {
257 num_non_compute_budget_instructions =
259 num_non_compute_budget_instructions.saturating_add(1);
260 }
261 }
262
263 if let Some((bytes, i)) = requested_heap_size {
264 if bytes > MAX_HEAP_FRAME_BYTES
265 || bytes < MIN_HEAP_FRAME_BYTES as u32
266 || bytes % 1024 != 0
267 {
268 return Err(TransactionError::InstructionError(
269 i,
270 InstructionError::InvalidInstructionData,
271 ));
272 }
273 self.heap_size = Some(bytes as usize);
274 }
275
276 self.compute_unit_limit = if default_units_per_instruction {
277 updated_compute_unit_limit.or_else(|| {
278 Some(
279 (num_non_compute_budget_instructions as u32)
280 .saturating_mul(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT),
281 )
282 })
283 } else {
284 updated_compute_unit_limit
285 }
286 .unwrap_or(MAX_COMPUTE_UNIT_LIMIT)
287 .min(MAX_COMPUTE_UNIT_LIMIT) as u64;
288
289 self.accounts_data_size_limit = updated_accounts_data_size_limit
290 .unwrap_or_else(|| {
291 get_default_loaded_accounts_data_limit(&loaded_accounts_data_limit_type)
292 })
293 .min(get_max_loaded_accounts_data_limit(
294 &loaded_accounts_data_limit_type,
295 )) as u64;
296
297 Ok(prioritization_fee
298 .map(|fee_type| PrioritizationFeeDetails::new(fee_type, self.compute_unit_limit))
299 .unwrap_or_default())
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use {
306 super::*,
307 cbe_sdk::{
308 hash::Hash,
309 instruction::Instruction,
310 message::Message,
311 pubkey::Pubkey,
312 signature::Keypair,
313 signer::Signer,
314 transaction::{SanitizedTransaction, Transaction},
315 },
316 };
317
318 macro_rules! test {
319 ( $instructions: expr, $expected_result: expr, $expected_budget: expr ) => {
320 let payer_keypair = Keypair::new();
321 let tx = SanitizedTransaction::from_transaction_for_tests(Transaction::new(
322 &[&payer_keypair],
323 Message::new($instructions, Some(&payer_keypair.pubkey())),
324 Hash::default(),
325 ));
326 let mut compute_budget = ComputeBudget::default();
327 let result = compute_budget.process_instructions(
328 tx.message().program_instructions_iter(),
329 true,
330 false, true, LoadedAccountsDataLimitType::V0,
333 );
334 assert_eq!($expected_result, result);
335 assert_eq!(compute_budget, $expected_budget);
336 };
337 ( $instructions: expr, $expected_result: expr, $expected_budget: expr) => {
338 test!($instructions, $expected_result, $expected_budget);
339 };
340 }
341
342 #[test]
343 fn test_process_instructions() {
344 test!(
346 &[],
347 Ok(PrioritizationFeeDetails::default()),
348 ComputeBudget {
349 compute_unit_limit: 0,
350 ..ComputeBudget::default()
351 }
352 );
353 test!(
354 &[
355 ComputeBudgetInstruction::set_compute_unit_limit(1),
356 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
357 ],
358 Ok(PrioritizationFeeDetails::default()),
359 ComputeBudget {
360 compute_unit_limit: 1,
361 ..ComputeBudget::default()
362 }
363 );
364 test!(
365 &[
366 ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT + 1),
367 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
368 ],
369 Ok(PrioritizationFeeDetails::default()),
370 ComputeBudget {
371 compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT as u64,
372 ..ComputeBudget::default()
373 }
374 );
375 test!(
376 &[
377 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
378 ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT),
379 ],
380 Ok(PrioritizationFeeDetails::default()),
381 ComputeBudget {
382 compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT as u64,
383 ..ComputeBudget::default()
384 }
385 );
386 test!(
387 &[
388 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
389 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
390 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
391 ComputeBudgetInstruction::set_compute_unit_limit(1),
392 ],
393 Ok(PrioritizationFeeDetails::default()),
394 ComputeBudget {
395 compute_unit_limit: 1,
396 ..ComputeBudget::default()
397 }
398 );
399
400 test!(
401 &[
402 ComputeBudgetInstruction::set_compute_unit_limit(1),
403 ComputeBudgetInstruction::set_compute_unit_price(42)
404 ],
405 Ok(PrioritizationFeeDetails::new(
406 PrioritizationFeeType::ComputeUnitPrice(42),
407 1
408 )),
409 ComputeBudget {
410 compute_unit_limit: 1,
411 ..ComputeBudget::default()
412 }
413 );
414
415 test!(
417 &[],
418 Ok(PrioritizationFeeDetails::default()),
419 ComputeBudget {
420 compute_unit_limit: 0,
421 ..ComputeBudget::default()
422 }
423 );
424 test!(
425 &[
426 ComputeBudgetInstruction::request_heap_frame(40 * 1024),
427 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
428 ],
429 Ok(PrioritizationFeeDetails::default()),
430 ComputeBudget {
431 compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
432 heap_size: Some(40 * 1024),
433 ..ComputeBudget::default()
434 }
435 );
436 test!(
437 &[
438 ComputeBudgetInstruction::request_heap_frame(40 * 1024 + 1),
439 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
440 ],
441 Err(TransactionError::InstructionError(
442 0,
443 InstructionError::InvalidInstructionData,
444 )),
445 ComputeBudget::default()
446 );
447 test!(
448 &[
449 ComputeBudgetInstruction::request_heap_frame(31 * 1024),
450 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
451 ],
452 Err(TransactionError::InstructionError(
453 0,
454 InstructionError::InvalidInstructionData,
455 )),
456 ComputeBudget::default()
457 );
458 test!(
459 &[
460 ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES + 1),
461 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
462 ],
463 Err(TransactionError::InstructionError(
464 0,
465 InstructionError::InvalidInstructionData,
466 )),
467 ComputeBudget::default()
468 );
469 test!(
470 &[
471 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
472 ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES),
473 ],
474 Ok(PrioritizationFeeDetails::default()),
475 ComputeBudget {
476 compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
477 heap_size: Some(MAX_HEAP_FRAME_BYTES as usize),
478 ..ComputeBudget::default()
479 }
480 );
481 test!(
482 &[
483 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
484 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
485 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
486 ComputeBudgetInstruction::request_heap_frame(1),
487 ],
488 Err(TransactionError::InstructionError(
489 3,
490 InstructionError::InvalidInstructionData,
491 )),
492 ComputeBudget::default()
493 );
494
495 test!(
496 &[
497 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
498 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
499 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
500 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
501 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
502 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
503 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
504 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
505 ],
506 Ok(PrioritizationFeeDetails::default()),
507 ComputeBudget {
508 compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64 * 7,
509 ..ComputeBudget::default()
510 }
511 );
512
513 test!(
515 &[
516 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
517 ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES),
518 ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT),
519 ComputeBudgetInstruction::set_compute_unit_price(u64::MAX),
520 ],
521 Ok(PrioritizationFeeDetails::new(
522 PrioritizationFeeType::ComputeUnitPrice(u64::MAX),
523 MAX_COMPUTE_UNIT_LIMIT as u64,
524 )),
525 ComputeBudget {
526 compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT as u64,
527 heap_size: Some(MAX_HEAP_FRAME_BYTES as usize),
528 ..ComputeBudget::default()
529 }
530 );
531
532 test!(
533 &[
534 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
535 ComputeBudgetInstruction::set_compute_unit_limit(1),
536 ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES),
537 ComputeBudgetInstruction::set_compute_unit_price(u64::MAX),
538 ],
539 Ok(PrioritizationFeeDetails::new(
540 PrioritizationFeeType::ComputeUnitPrice(u64::MAX),
541 1
542 )),
543 ComputeBudget {
544 compute_unit_limit: 1,
545 heap_size: Some(MAX_HEAP_FRAME_BYTES as usize),
546 ..ComputeBudget::default()
547 }
548 );
549
550 test!(
552 &[
553 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
554 ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT),
555 ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT - 1),
556 ],
557 Err(TransactionError::DuplicateInstruction(2)),
558 ComputeBudget::default()
559 );
560
561 test!(
562 &[
563 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
564 ComputeBudgetInstruction::request_heap_frame(MIN_HEAP_FRAME_BYTES as u32),
565 ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES),
566 ],
567 Err(TransactionError::DuplicateInstruction(2)),
568 ComputeBudget::default()
569 );
570
571 test!(
572 &[
573 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
574 ComputeBudgetInstruction::set_compute_unit_price(0),
575 ComputeBudgetInstruction::set_compute_unit_price(u64::MAX),
576 ],
577 Err(TransactionError::DuplicateInstruction(2)),
578 ComputeBudget::default()
579 );
580
581 test!(
583 &[Instruction::new_with_borsh(
584 compute_budget::id(),
585 &compute_budget::ComputeBudgetInstruction::RequestUnitsDeprecated {
586 units: 1_000,
587 additional_fee: 10
588 },
589 vec![]
590 )],
591 Err(TransactionError::InstructionError(
592 0,
593 InstructionError::InvalidInstructionData,
594 )),
595 ComputeBudget::default()
596 );
597 }
598
599 #[test]
600 fn test_process_accounts_data_size_limit_instruction() {
601 test!(
602 &[],
603 Ok(PrioritizationFeeDetails::default()),
604 ComputeBudget {
605 compute_unit_limit: 0,
606 ..ComputeBudget::default()
607 }
608 );
609 test!(
610 &[
611 ComputeBudgetInstruction::set_accounts_data_size_limit(1),
612 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
613 ],
614 Ok(PrioritizationFeeDetails::default()),
615 ComputeBudget {
616 compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
617 accounts_data_size_limit: 1,
618 ..ComputeBudget::default()
619 }
620 );
621 test!(
622 &[
623 ComputeBudgetInstruction::set_accounts_data_size_limit(
624 get_max_loaded_accounts_data_limit(&LoadedAccountsDataLimitType::V0) + 1
625 ),
626 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
627 ],
628 Ok(PrioritizationFeeDetails::default()),
629 ComputeBudget {
630 compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
631 accounts_data_size_limit: get_max_loaded_accounts_data_limit(
632 &LoadedAccountsDataLimitType::V0
633 ) as u64,
634 ..ComputeBudget::default()
635 }
636 );
637 test!(
638 &[
639 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
640 ComputeBudgetInstruction::set_accounts_data_size_limit(
641 get_max_loaded_accounts_data_limit(&LoadedAccountsDataLimitType::V0)
642 ),
643 ],
644 Ok(PrioritizationFeeDetails::default()),
645 ComputeBudget {
646 compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
647 accounts_data_size_limit: get_max_loaded_accounts_data_limit(
648 &LoadedAccountsDataLimitType::V0
649 ) as u64,
650 ..ComputeBudget::default()
651 }
652 );
653 test!(
654 &[
655 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
656 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
657 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
658 ComputeBudgetInstruction::set_accounts_data_size_limit(1),
659 ],
660 Ok(PrioritizationFeeDetails::default()),
661 ComputeBudget {
662 compute_unit_limit: 3 * DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
663 accounts_data_size_limit: 1,
664 ..ComputeBudget::default()
665 }
666 );
667
668 test!(
669 &[
670 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
671 ComputeBudgetInstruction::set_accounts_data_size_limit(1),
672 ComputeBudgetInstruction::set_accounts_data_size_limit(1),
673 ],
674 Err(TransactionError::DuplicateInstruction(2)),
675 ComputeBudget::default()
676 );
677 }
678}