| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | #![cfg(any(feature = "bpf_c", feature = "bpf_rust"))]
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[macro_use]
 | 
					
						
							|  |  |  | extern crate solana_bpf_loader_program;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  | use solana_bpf_loader_program::{
 | 
					
						
							|  |  |  |     create_vm,
 | 
					
						
							|  |  |  |     serialization::{deserialize_parameters, serialize_parameters},
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  |     ThisInstructionMeter,
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  | };
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  | use solana_rbpf::vm::Executable;
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | use solana_runtime::{
 | 
					
						
							|  |  |  |     bank::Bank,
 | 
					
						
							|  |  |  |     bank_client::BankClient,
 | 
					
						
							|  |  |  |     genesis_utils::{create_genesis_config, GenesisConfigInfo},
 | 
					
						
							|  |  |  |     loader_utils::load_program,
 | 
					
						
							|  |  |  | };
 | 
					
						
							|  |  |  | use solana_sdk::{
 | 
					
						
							| 
									
										
										
										
											2020-10-26 09:14:57 -07:00
										 |  |  |     account::Account,
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  |     bpf_loader, bpf_loader_deprecated,
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     client::SyncClient,
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |     clock::{DEFAULT_SLOTS_PER_EPOCH, MAX_PROCESSING_AGE},
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |     entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
 | 
					
						
							|  |  |  |     instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
 | 
					
						
							| 
									
										
										
										
											2020-10-26 09:14:57 -07:00
										 |  |  |     keyed_account::KeyedAccount,
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     message::Message,
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  |     process_instruction::{BpfComputeBudget, InvokeContext, MockInvokeContext},
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     pubkey::Pubkey,
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |     signature::{Keypair, Signer},
 | 
					
						
							| 
									
										
										
										
											2020-09-25 16:19:03 -07:00
										 |  |  |     sysvar::{clock, fees, rent, slot_hashes, stake_history},
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |     transaction::{Transaction, TransactionError},
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | };
 | 
					
						
							| 
									
										
										
										
											2020-10-29 10:04:47 +01:00
										 |  |  | use std::{cell::RefCell, env, fs::File, io::Read, path::PathBuf, sync::Arc};
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /// BPF program file extension
 | 
					
						
							|  |  |  | const PLATFORM_FILE_EXTENSION_BPF: &str = "so";
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Create a BPF program file name
 | 
					
						
							|  |  |  | fn create_bpf_path(name: &str) -> PathBuf {
 | 
					
						
							|  |  |  |     let mut pathbuf = {
 | 
					
						
							|  |  |  |         let current_exe = env::current_exe().unwrap();
 | 
					
						
							|  |  |  |         PathBuf::from(current_exe.parent().unwrap().parent().unwrap())
 | 
					
						
							| 
									
										
										
										
											2020-03-17 15:59:09 -07:00
										 |  |  |     };
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     pathbuf.push("bpf/");
 | 
					
						
							|  |  |  |     pathbuf.push(name);
 | 
					
						
							|  |  |  |     pathbuf.set_extension(PLATFORM_FILE_EXTENSION_BPF);
 | 
					
						
							|  |  |  |     pathbuf
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2019-03-02 21:33:02 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  | fn load_bpf_program(
 | 
					
						
							|  |  |  |     bank_client: &BankClient,
 | 
					
						
							|  |  |  |     loader_id: &Pubkey,
 | 
					
						
							|  |  |  |     payer_keypair: &Keypair,
 | 
					
						
							|  |  |  |     name: &str,
 | 
					
						
							|  |  |  | ) -> Pubkey {
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     let path = create_bpf_path(name);
 | 
					
						
							| 
									
										
										
										
											2020-10-22 17:10:42 -07:00
										 |  |  |     let mut file = File::open(&path).unwrap_or_else(|err| {
 | 
					
						
							|  |  |  |         panic!("Failed to open {}: {}", path.display(), err);
 | 
					
						
							|  |  |  |     });
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     let mut elf = Vec::new();
 | 
					
						
							|  |  |  |     file.read_to_end(&mut elf).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  |     load_program(bank_client, payer_keypair, loader_id, elf)
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-03-17 15:59:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  | fn run_program(
 | 
					
						
							|  |  |  |     name: &str,
 | 
					
						
							|  |  |  |     program_id: &Pubkey,
 | 
					
						
							|  |  |  |     parameter_accounts: &[KeyedAccount],
 | 
					
						
							|  |  |  |     instruction_data: &[u8],
 | 
					
						
							|  |  |  | ) -> Result<u64, InstructionError> {
 | 
					
						
							|  |  |  |     let path = create_bpf_path(name);
 | 
					
						
							|  |  |  |     let mut file = File::open(path).unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 17:42:37 -07:00
										 |  |  |     let mut data = vec![];
 | 
					
						
							|  |  |  |     file.read_to_end(&mut data).unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-09-11 11:07:03 -07:00
										 |  |  |     let loader_id = bpf_loader::id();
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |     let mut invoke_context = MockInvokeContext::default();
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  |     let parameter_bytes = serialize_parameters(
 | 
					
						
							|  |  |  |         &bpf_loader::id(),
 | 
					
						
							|  |  |  |         program_id,
 | 
					
						
							|  |  |  |         parameter_accounts,
 | 
					
						
							|  |  |  |         &instruction_data,
 | 
					
						
							|  |  |  |     )
 | 
					
						
							|  |  |  |     .unwrap();
 | 
					
						
							|  |  |  |     let compute_meter = invoke_context.get_compute_meter();
 | 
					
						
							|  |  |  |     let mut instruction_meter = ThisInstructionMeter { compute_meter };
 | 
					
						
							| 
									
										
										
										
											2020-09-14 17:42:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  |     let executable = Executable::from_elf(&data, None).unwrap();
 | 
					
						
							|  |  |  |     let mut vm = create_vm(
 | 
					
						
							| 
									
										
										
										
											2020-09-11 11:07:03 -07:00
										 |  |  |         &loader_id,
 | 
					
						
							| 
									
										
										
										
											2020-09-14 17:42:37 -07:00
										 |  |  |         executable.as_ref(),
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  |         ¶meter_bytes,
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |         parameter_accounts,
 | 
					
						
							|  |  |  |         &mut invoke_context,
 | 
					
						
							|  |  |  |     )
 | 
					
						
							|  |  |  |     .unwrap();
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |     assert_eq!(
 | 
					
						
							|  |  |  |         SUCCESS,
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  |         vm.execute_program_interpreted(&mut instruction_meter)
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |             .unwrap()
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  |     deserialize_parameters(&bpf_loader::id(), parameter_accounts, ¶meter_bytes).unwrap();
 | 
					
						
							|  |  |  |     Ok(vm.get_total_instruction_count())
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  | fn process_transaction_and_record_inner(
 | 
					
						
							|  |  |  |     bank: &Bank,
 | 
					
						
							|  |  |  |     tx: Transaction,
 | 
					
						
							|  |  |  | ) -> (Result<(), TransactionError>, Vec<Vec<CompiledInstruction>>) {
 | 
					
						
							|  |  |  |     let signature = tx.signatures.get(0).unwrap().clone();
 | 
					
						
							|  |  |  |     let txs = vec![tx];
 | 
					
						
							|  |  |  |     let tx_batch = bank.prepare_batch(&txs, None);
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |     let (mut results, _, mut inner, _transaction_logs) = bank.load_execute_and_commit_transactions(
 | 
					
						
							|  |  |  |         &tx_batch,
 | 
					
						
							|  |  |  |         MAX_PROCESSING_AGE,
 | 
					
						
							|  |  |  |         false,
 | 
					
						
							|  |  |  |         true,
 | 
					
						
							|  |  |  |         false,
 | 
					
						
							|  |  |  |     );
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |     let inner_instructions = inner.swap_remove(0);
 | 
					
						
							|  |  |  |     let result = results
 | 
					
						
							|  |  |  |         .fee_collection_results
 | 
					
						
							|  |  |  |         .swap_remove(0)
 | 
					
						
							|  |  |  |         .and_then(|_| bank.get_signature_status(&signature).unwrap());
 | 
					
						
							|  |  |  |     (
 | 
					
						
							|  |  |  |         result,
 | 
					
						
							|  |  |  |         inner_instructions.expect("cpi recording should be enabled"),
 | 
					
						
							|  |  |  |     )
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | #[test]
 | 
					
						
							|  |  |  | #[cfg(any(feature = "bpf_c", feature = "bpf_rust"))]
 | 
					
						
							|  |  |  | fn test_program_bpf_sanity() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let mut programs = Vec::new();
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_c")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[
 | 
					
						
							| 
									
										
										
										
											2020-09-15 16:42:20 -07:00
										 |  |  |             ("alloc", true),
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             ("bpf_to_bpf", true),
 | 
					
						
							|  |  |  |             ("multiple_static", true),
 | 
					
						
							|  |  |  |             ("noop", true),
 | 
					
						
							|  |  |  |             ("noop++", true),
 | 
					
						
							|  |  |  |             ("panic", false),
 | 
					
						
							|  |  |  |             ("relative_call", true),
 | 
					
						
							| 
									
										
										
										
											2020-09-25 09:01:22 -07:00
										 |  |  |             ("sanity", true),
 | 
					
						
							|  |  |  |             ("sanity++", true),
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:29:20 -07:00
										 |  |  |             ("sha256", true),
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             ("struct_pass", true),
 | 
					
						
							|  |  |  |             ("struct_ret", true),
 | 
					
						
							|  |  |  |         ]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_rust")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_128bit", true),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_alloc", true),
 | 
					
						
							| 
									
										
										
										
											2020-10-06 11:03:51 -07:00
										 |  |  |             ("solana_bpf_rust_custom_heap", true),
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             ("solana_bpf_rust_dep_crate", true),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_external_spend", false),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_iter", true),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_many_args", true),
 | 
					
						
							| 
									
										
										
										
											2020-11-05 22:20:54 -08:00
										 |  |  |             ("solana_bpf_rust_mem", true),
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             ("solana_bpf_rust_noop", true),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_panic", false),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_param_passing", true),
 | 
					
						
							| 
									
										
										
										
											2020-09-29 17:25:51 -07:00
										 |  |  |             ("solana_bpf_rust_rand", true),
 | 
					
						
							| 
									
										
										
										
											2020-10-06 23:52:13 -07:00
										 |  |  |             ("solana_bpf_rust_ristretto", true),
 | 
					
						
							| 
									
										
										
										
											2020-09-25 09:01:22 -07:00
										 |  |  |             ("solana_bpf_rust_sanity", true),
 | 
					
						
							| 
									
										
										
										
											2020-09-29 23:29:20 -07:00
										 |  |  |             ("solana_bpf_rust_sha256", true),
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             ("solana_bpf_rust_sysval", true),
 | 
					
						
							|  |  |  |         ]);
 | 
					
						
							| 
									
										
										
										
											2020-03-17 19:37:16 -07:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     for program in programs.iter() {
 | 
					
						
							|  |  |  |         println!("Test program: {:?}", program.0);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let GenesisConfigInfo {
 | 
					
						
							|  |  |  |             genesis_config,
 | 
					
						
							|  |  |  |             mint_keypair,
 | 
					
						
							|  |  |  |             ..
 | 
					
						
							|  |  |  |         } = create_genesis_config(50);
 | 
					
						
							|  |  |  |         let mut bank = Bank::new(&genesis_config);
 | 
					
						
							|  |  |  |         let (name, id, entrypoint) = solana_bpf_loader_program!();
 | 
					
						
							| 
									
										
										
										
											2020-10-29 16:17:36 -07:00
										 |  |  |         bank.add_builtin(&name, id, entrypoint);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let bank = Arc::new(bank);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Create bank with a specific slot, used by solana_bpf_rust_sysvar test
 | 
					
						
							|  |  |  |         let bank = Bank::new_from_parent(&bank, &Pubkey::default(), DEFAULT_SLOTS_PER_EPOCH + 1);
 | 
					
						
							|  |  |  |         let bank_client = BankClient::new(bank);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Call user program
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  |         let program_id =
 | 
					
						
							|  |  |  |             load_bpf_program(&bank_client, &bpf_loader::id(), &mint_keypair, program.0);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let account_metas = vec![
 | 
					
						
							|  |  |  |             AccountMeta::new(mint_keypair.pubkey(), true),
 | 
					
						
							|  |  |  |             AccountMeta::new(Keypair::new().pubkey(), false),
 | 
					
						
							|  |  |  |             AccountMeta::new(clock::id(), false),
 | 
					
						
							|  |  |  |             AccountMeta::new(fees::id(), false),
 | 
					
						
							|  |  |  |             AccountMeta::new(slot_hashes::id(), false),
 | 
					
						
							|  |  |  |             AccountMeta::new(stake_history::id(), false),
 | 
					
						
							|  |  |  |             AccountMeta::new(rent::id(), false),
 | 
					
						
							|  |  |  |         ];
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &1u8, account_metas);
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         if program.1 {
 | 
					
						
							| 
									
										
										
										
											2020-01-24 10:54:26 -08:00
										 |  |  |             assert!(result.is_ok());
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         } else {
 | 
					
						
							|  |  |  |             assert!(result.is_err());
 | 
					
						
							| 
									
										
										
										
											2020-01-22 09:11:56 -08:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2020-03-17 15:59:09 -07:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  | #[test]
 | 
					
						
							|  |  |  | #[cfg(any(feature = "bpf_c", feature = "bpf_rust"))]
 | 
					
						
							|  |  |  | fn test_program_bpf_loader_deprecated() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let mut programs = Vec::new();
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_c")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[("deprecated_loader")]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_rust")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[("solana_bpf_rust_deprecated_loader")]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for program in programs.iter() {
 | 
					
						
							|  |  |  |         println!("Test program: {:?}", program);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let GenesisConfigInfo {
 | 
					
						
							|  |  |  |             genesis_config,
 | 
					
						
							|  |  |  |             mint_keypair,
 | 
					
						
							|  |  |  |             ..
 | 
					
						
							|  |  |  |         } = create_genesis_config(50);
 | 
					
						
							|  |  |  |         let mut bank = Bank::new(&genesis_config);
 | 
					
						
							|  |  |  |         let (name, id, entrypoint) = solana_bpf_loader_deprecated_program!();
 | 
					
						
							| 
									
										
										
										
											2020-10-29 16:17:36 -07:00
										 |  |  |         bank.add_builtin(&name, id, entrypoint);
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  |         let bank_client = BankClient::new(bank);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let program_id = load_bpf_program(
 | 
					
						
							|  |  |  |             &bank_client,
 | 
					
						
							|  |  |  |             &bpf_loader_deprecated::id(),
 | 
					
						
							|  |  |  |             &mint_keypair,
 | 
					
						
							|  |  |  |             program,
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let account_metas = vec![AccountMeta::new(mint_keypair.pubkey(), true)];
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &1u8, account_metas);
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | #[test]
 | 
					
						
							|  |  |  | fn test_program_bpf_duplicate_accounts() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     let mut programs = Vec::new();
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_c")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[("dup_accounts")]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_rust")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[("solana_bpf_rust_dup_accounts")]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-03-17 15:59:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     for program in programs.iter() {
 | 
					
						
							|  |  |  |         println!("Test program: {:?}", program);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let GenesisConfigInfo {
 | 
					
						
							|  |  |  |             genesis_config,
 | 
					
						
							|  |  |  |             mint_keypair,
 | 
					
						
							|  |  |  |             ..
 | 
					
						
							|  |  |  |         } = create_genesis_config(50);
 | 
					
						
							|  |  |  |         let mut bank = Bank::new(&genesis_config);
 | 
					
						
							|  |  |  |         let (name, id, entrypoint) = solana_bpf_loader_program!();
 | 
					
						
							| 
									
										
										
										
											2020-10-29 16:17:36 -07:00
										 |  |  |         bank.add_builtin(&name, id, entrypoint);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let bank = Arc::new(bank);
 | 
					
						
							|  |  |  |         let bank_client = BankClient::new_shared(&bank);
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  |         let program_id = load_bpf_program(&bank_client, &bpf_loader::id(), &mint_keypair, program);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let payee_account = Account::new(10, 1, &program_id);
 | 
					
						
							| 
									
										
										
										
											2020-10-19 12:12:08 -07:00
										 |  |  |         let payee_pubkey = solana_sdk::pubkey::new_rand();
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         bank.store_account(&payee_pubkey, &payee_account);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let account = Account::new(10, 1, &program_id);
 | 
					
						
							| 
									
										
										
										
											2020-10-19 12:12:08 -07:00
										 |  |  |         let pubkey = solana_sdk::pubkey::new_rand();
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let account_metas = vec![
 | 
					
						
							|  |  |  |             AccountMeta::new(mint_keypair.pubkey(), true),
 | 
					
						
							|  |  |  |             AccountMeta::new(payee_pubkey, false),
 | 
					
						
							|  |  |  |             AccountMeta::new(pubkey, false),
 | 
					
						
							|  |  |  |             AccountMeta::new(pubkey, false),
 | 
					
						
							|  |  |  |         ];
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bank.store_account(&pubkey, &account);
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &1u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |         assert_eq!(data[0], 1);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bank.store_account(&pubkey, &account);
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &2u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |         assert_eq!(data[0], 2);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bank.store_account(&pubkey, &account);
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &3u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let data = bank_client.get_account_data(&pubkey).unwrap().unwrap();
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |         assert_eq!(data[0], 3);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bank.store_account(&pubkey, &account);
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &4u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let lamports = bank_client.get_balance(&pubkey).unwrap();
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |         assert_eq!(lamports, 11);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bank.store_account(&pubkey, &account);
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &5u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let lamports = bank_client.get_balance(&pubkey).unwrap();
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |         assert_eq!(lamports, 12);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bank.store_account(&pubkey, &account);
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &6u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let lamports = bank_client.get_balance(&pubkey).unwrap();
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |         assert_eq!(lamports, 13);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | #[test]
 | 
					
						
							|  |  |  | fn test_program_bpf_error_handling() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     let mut programs = Vec::new();
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_c")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[("error_handling")]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_rust")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[("solana_bpf_rust_error_handling")]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     for program in programs.iter() {
 | 
					
						
							|  |  |  |         println!("Test program: {:?}", program);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let GenesisConfigInfo {
 | 
					
						
							|  |  |  |             genesis_config,
 | 
					
						
							|  |  |  |             mint_keypair,
 | 
					
						
							|  |  |  |             ..
 | 
					
						
							|  |  |  |         } = create_genesis_config(50);
 | 
					
						
							|  |  |  |         let mut bank = Bank::new(&genesis_config);
 | 
					
						
							|  |  |  |         let (name, id, entrypoint) = solana_bpf_loader_program!();
 | 
					
						
							| 
									
										
										
										
											2020-10-29 16:17:36 -07:00
										 |  |  |         bank.add_builtin(&name, id, entrypoint);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let bank_client = BankClient::new(bank);
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  |         let program_id = load_bpf_program(&bank_client, &bpf_loader::id(), &mint_keypair, program);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let account_metas = vec![AccountMeta::new(mint_keypair.pubkey(), true)];
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &1u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &2u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             result.unwrap_err().unwrap(),
 | 
					
						
							|  |  |  |             TransactionError::InstructionError(0, InstructionError::InvalidAccountData)
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &3u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             result.unwrap_err().unwrap(),
 | 
					
						
							|  |  |  |             TransactionError::InstructionError(0, InstructionError::Custom(0))
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &4u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             result.unwrap_err().unwrap(),
 | 
					
						
							|  |  |  |             TransactionError::InstructionError(0, InstructionError::Custom(42))
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &5u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let result = result.unwrap_err().unwrap();
 | 
					
						
							|  |  |  |         if TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) != result
 | 
					
						
							|  |  |  |         {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  |             assert_eq!(
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |                 result,
 | 
					
						
							|  |  |  |                 TransactionError::InstructionError(0, InstructionError::InvalidError)
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  |             );
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let instruction = Instruction::new(program_id, &6u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let result = result.unwrap_err().unwrap();
 | 
					
						
							|  |  |  |         if TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) != result
 | 
					
						
							|  |  |  |         {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  |             assert_eq!(
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |                 result,
 | 
					
						
							|  |  |  |                 TransactionError::InstructionError(0, InstructionError::InvalidError)
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  |             );
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2020-06-23 11:19:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let instruction = Instruction::new(program_id, &7u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         let result = result.unwrap_err().unwrap();
 | 
					
						
							|  |  |  |         if TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) != result
 | 
					
						
							|  |  |  |         {
 | 
					
						
							| 
									
										
										
										
											2020-06-23 11:19:27 -07:00
										 |  |  |             assert_eq!(
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |                 result,
 | 
					
						
							|  |  |  |                 TransactionError::InstructionError(0, InstructionError::AccountBorrowFailed)
 | 
					
						
							| 
									
										
										
										
											2020-06-23 11:19:27 -07:00
										 |  |  |             );
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:47:22 -08:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &8u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             result.unwrap_err().unwrap(),
 | 
					
						
							|  |  |  |             TransactionError::InstructionError(0, InstructionError::InvalidInstructionData)
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(program_id, &9u8, account_metas.clone());
 | 
					
						
							|  |  |  |         let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             result.unwrap_err().unwrap(),
 | 
					
						
							|  |  |  |             TransactionError::InstructionError(0, InstructionError::MaxSeedLengthExceeded)
 | 
					
						
							|  |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2019-01-02 15:12:42 -08:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-04-28 14:33:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | #[test]
 | 
					
						
							|  |  |  | fn test_program_bpf_invoke() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							| 
									
										
										
										
											2020-04-28 14:33:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     const TEST_SUCCESS: u8 = 1;
 | 
					
						
							|  |  |  |     const TEST_PRIVILEGE_ESCALATION_SIGNER: u8 = 2;
 | 
					
						
							|  |  |  |     const TEST_PRIVILEGE_ESCALATION_WRITABLE: u8 = 3;
 | 
					
						
							| 
									
										
										
										
											2020-10-02 13:55:22 -07:00
										 |  |  |     const TEST_PPROGRAM_NOT_EXECUTABLE: u8 = 4;
 | 
					
						
							| 
									
										
										
										
											2020-05-26 01:02:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |     #[allow(dead_code)]
 | 
					
						
							|  |  |  |     #[derive(Debug)]
 | 
					
						
							|  |  |  |     enum Languages {
 | 
					
						
							|  |  |  |         C,
 | 
					
						
							|  |  |  |         Rust,
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     let mut programs = Vec::new();
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_c")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							| 
									
										
										
										
											2020-11-05 15:23:52 +08:00
										 |  |  |         programs.push((Languages::C, "invoke", "invoked", "noop"));
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     }
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_rust")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |         programs.push((
 | 
					
						
							|  |  |  |             Languages::Rust,
 | 
					
						
							|  |  |  |             "solana_bpf_rust_invoke",
 | 
					
						
							|  |  |  |             "solana_bpf_rust_invoked",
 | 
					
						
							| 
									
										
										
										
											2020-11-05 15:23:52 +08:00
										 |  |  |             "solana_bpf_rust_noop",
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |         ));
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |     }
 | 
					
						
							|  |  |  |     for program in programs.iter() {
 | 
					
						
							|  |  |  |         println!("Test program: {:?}", program);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let GenesisConfigInfo {
 | 
					
						
							|  |  |  |             genesis_config,
 | 
					
						
							|  |  |  |             mint_keypair,
 | 
					
						
							|  |  |  |             ..
 | 
					
						
							|  |  |  |         } = create_genesis_config(50);
 | 
					
						
							|  |  |  |         let mut bank = Bank::new(&genesis_config);
 | 
					
						
							|  |  |  |         let (name, id, entrypoint) = solana_bpf_loader_program!();
 | 
					
						
							| 
									
										
										
										
											2020-10-29 16:17:36 -07:00
										 |  |  |         bank.add_builtin(&name, id, entrypoint);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         let bank = Arc::new(bank);
 | 
					
						
							|  |  |  |         let bank_client = BankClient::new_shared(&bank);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 14:06:58 -07:00
										 |  |  |         let invoke_program_id =
 | 
					
						
							|  |  |  |             load_bpf_program(&bank_client, &bpf_loader::id(), &mint_keypair, program.1);
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |         let invoked_program_id =
 | 
					
						
							|  |  |  |             load_bpf_program(&bank_client, &bpf_loader::id(), &mint_keypair, program.2);
 | 
					
						
							| 
									
										
										
										
											2020-11-05 15:23:52 +08:00
										 |  |  |         let noop_program_id =
 | 
					
						
							|  |  |  |             load_bpf_program(&bank_client, &bpf_loader::id(), &mint_keypair, program.3);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let argument_keypair = Keypair::new();
 | 
					
						
							| 
									
										
										
										
											2020-08-17 13:38:42 -07:00
										 |  |  |         let account = Account::new(42, 100, &invoke_program_id);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         bank.store_account(&argument_keypair.pubkey(), &account);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let invoked_argument_keypair = Keypair::new();
 | 
					
						
							|  |  |  |         let account = Account::new(10, 10, &invoked_program_id);
 | 
					
						
							|  |  |  |         bank.store_account(&invoked_argument_keypair.pubkey(), &account);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let from_keypair = Keypair::new();
 | 
					
						
							| 
									
										
										
										
											2020-08-17 13:38:42 -07:00
										 |  |  |         let account = Account::new(84, 0, &solana_sdk::system_program::id());
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         bank.store_account(&from_keypair.pubkey(), &account);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 10:11:08 -07:00
										 |  |  |         let (derived_key1, bump_seed1) =
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             Pubkey::find_program_address(&[b"You pass butter"], &invoke_program_id);
 | 
					
						
							| 
									
										
										
										
											2020-10-13 10:11:08 -07:00
										 |  |  |         let (derived_key2, bump_seed2) =
 | 
					
						
							| 
									
										
										
										
											2020-10-09 10:33:12 -07:00
										 |  |  |             Pubkey::find_program_address(&[b"Lil'", b"Bits"], &invoked_program_id);
 | 
					
						
							| 
									
										
										
										
											2020-10-13 10:11:08 -07:00
										 |  |  |         let (derived_key3, bump_seed3) =
 | 
					
						
							| 
									
										
										
										
											2020-10-09 10:33:12 -07:00
										 |  |  |             Pubkey::find_program_address(&[derived_key2.as_ref()], &invoked_program_id);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let mint_pubkey = mint_keypair.pubkey();
 | 
					
						
							|  |  |  |         let account_metas = vec![
 | 
					
						
							|  |  |  |             AccountMeta::new(mint_pubkey, true),
 | 
					
						
							|  |  |  |             AccountMeta::new(argument_keypair.pubkey(), true),
 | 
					
						
							|  |  |  |             AccountMeta::new_readonly(invoked_program_id, false),
 | 
					
						
							|  |  |  |             AccountMeta::new(invoked_argument_keypair.pubkey(), true),
 | 
					
						
							|  |  |  |             AccountMeta::new_readonly(invoked_program_id, false),
 | 
					
						
							|  |  |  |             AccountMeta::new(argument_keypair.pubkey(), true),
 | 
					
						
							|  |  |  |             AccountMeta::new(derived_key1, false),
 | 
					
						
							|  |  |  |             AccountMeta::new(derived_key2, false),
 | 
					
						
							|  |  |  |             AccountMeta::new_readonly(derived_key3, false),
 | 
					
						
							|  |  |  |             AccountMeta::new_readonly(solana_sdk::system_program::id(), false),
 | 
					
						
							|  |  |  |             AccountMeta::new(from_keypair.pubkey(), true),
 | 
					
						
							|  |  |  |         ];
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // success cases
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(
 | 
					
						
							|  |  |  |             invoke_program_id,
 | 
					
						
							| 
									
										
										
										
											2020-10-13 10:11:08 -07:00
										 |  |  |             &[TEST_SUCCESS, bump_seed1, bump_seed2, bump_seed3],
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             account_metas.clone(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2020-11-05 15:23:52 +08:00
										 |  |  |         let noop_instruction = Instruction::new(
 | 
					
						
							|  |  |  |             noop_program_id,
 | 
					
						
							|  |  |  |             &(),
 | 
					
						
							|  |  |  |             vec![]
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let message = Message::new(&[instruction, noop_instruction], Some(&mint_pubkey));
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |         let tx = Transaction::new(
 | 
					
						
							|  |  |  |             &[
 | 
					
						
							|  |  |  |                 &mint_keypair,
 | 
					
						
							|  |  |  |                 &argument_keypair,
 | 
					
						
							|  |  |  |                 &invoked_argument_keypair,
 | 
					
						
							|  |  |  |                 &from_keypair,
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							|  |  |  |             message.clone(),
 | 
					
						
							|  |  |  |             bank.last_blockhash(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let (result, inner_instructions) = process_transaction_and_record_inner(&bank, tx);
 | 
					
						
							|  |  |  |         assert!(result.is_ok());
 | 
					
						
							|  |  |  |         let invoked_programs: Vec<Pubkey> = inner_instructions[0]
 | 
					
						
							|  |  |  |             .iter()
 | 
					
						
							|  |  |  |             .map(|ix| message.account_keys[ix.program_id_index as usize].clone())
 | 
					
						
							|  |  |  |             .collect();
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let expected_invoked_programs = match program.0 {
 | 
					
						
							|  |  |  |             Languages::C => vec![
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |                 solana_sdk::system_program::id(),
 | 
					
						
							|  |  |  |                 solana_sdk::system_program::id(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							| 
									
										
										
										
											2020-10-02 17:45:39 -07:00
										 |  |  |                 invoked_program_id.clone(),
 | 
					
						
							| 
									
										
										
										
											2020-10-09 10:33:12 -07:00
										 |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |             ],
 | 
					
						
							|  |  |  |             Languages::Rust => vec![
 | 
					
						
							|  |  |  |                 solana_sdk::system_program::id(),
 | 
					
						
							|  |  |  |                 solana_sdk::system_program::id(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |                 invoked_program_id.clone(),
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							|  |  |  |         };
 | 
					
						
							|  |  |  |         assert_eq!(invoked_programs, expected_invoked_programs);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 15:23:52 +08:00
										 |  |  |         let no_invoked_programs: Vec<Pubkey> = inner_instructions[1]
 | 
					
						
							|  |  |  |             .iter()
 | 
					
						
							|  |  |  |             .map(|ix| message.account_keys[ix.program_id_index as usize].clone())
 | 
					
						
							|  |  |  |             .collect();
 | 
					
						
							|  |  |  |         assert_eq!(no_invoked_programs.len(), 0);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         // failure cases
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(
 | 
					
						
							|  |  |  |             invoke_program_id,
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |             &[
 | 
					
						
							|  |  |  |                 TEST_PRIVILEGE_ESCALATION_SIGNER,
 | 
					
						
							|  |  |  |                 bump_seed1,
 | 
					
						
							|  |  |  |                 bump_seed2,
 | 
					
						
							|  |  |  |                 bump_seed3,
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             account_metas.clone(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let message = Message::new(&[instruction], Some(&mint_pubkey));
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |         let tx = Transaction::new(
 | 
					
						
							|  |  |  |             &[
 | 
					
						
							|  |  |  |                 &mint_keypair,
 | 
					
						
							|  |  |  |                 &argument_keypair,
 | 
					
						
							|  |  |  |                 &invoked_argument_keypair,
 | 
					
						
							|  |  |  |                 &from_keypair,
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							|  |  |  |             message.clone(),
 | 
					
						
							|  |  |  |             bank.last_blockhash(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let (result, inner_instructions) = process_transaction_and_record_inner(&bank, tx);
 | 
					
						
							|  |  |  |         let invoked_programs: Vec<Pubkey> = inner_instructions[0]
 | 
					
						
							|  |  |  |             .iter()
 | 
					
						
							|  |  |  |             .map(|ix| message.account_keys[ix.program_id_index as usize].clone())
 | 
					
						
							|  |  |  |             .collect();
 | 
					
						
							|  |  |  |         assert_eq!(invoked_programs, vec![invoked_program_id.clone()]);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         assert_eq!(
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |             result.unwrap_err(),
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             TransactionError::InstructionError(0, InstructionError::Custom(194969602))
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let instruction = Instruction::new(
 | 
					
						
							|  |  |  |             invoke_program_id,
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |             &[
 | 
					
						
							|  |  |  |                 TEST_PRIVILEGE_ESCALATION_WRITABLE,
 | 
					
						
							|  |  |  |                 bump_seed1,
 | 
					
						
							|  |  |  |                 bump_seed2,
 | 
					
						
							|  |  |  |                 bump_seed3,
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             account_metas.clone(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let message = Message::new(&[instruction], Some(&mint_pubkey));
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |         let tx = Transaction::new(
 | 
					
						
							|  |  |  |             &[
 | 
					
						
							|  |  |  |                 &mint_keypair,
 | 
					
						
							|  |  |  |                 &argument_keypair,
 | 
					
						
							|  |  |  |                 &invoked_argument_keypair,
 | 
					
						
							|  |  |  |                 &from_keypair,
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							|  |  |  |             message.clone(),
 | 
					
						
							|  |  |  |             bank.last_blockhash(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let (result, inner_instructions) = process_transaction_and_record_inner(&bank, tx);
 | 
					
						
							|  |  |  |         let invoked_programs: Vec<Pubkey> = inner_instructions[0]
 | 
					
						
							|  |  |  |             .iter()
 | 
					
						
							|  |  |  |             .map(|ix| message.account_keys[ix.program_id_index as usize].clone())
 | 
					
						
							|  |  |  |             .collect();
 | 
					
						
							|  |  |  |         assert_eq!(invoked_programs, vec![invoked_program_id.clone()]);
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |         assert_eq!(
 | 
					
						
							| 
									
										
										
										
											2020-09-24 22:36:22 +08:00
										 |  |  |             result.unwrap_err(),
 | 
					
						
							| 
									
										
										
										
											2020-08-14 12:32:45 -07:00
										 |  |  |             TransactionError::InstructionError(0, InstructionError::Custom(194969602))
 | 
					
						
							|  |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2020-08-17 13:38:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-02 13:55:22 -07:00
										 |  |  |         let instruction = Instruction::new(
 | 
					
						
							|  |  |  |             invoke_program_id,
 | 
					
						
							| 
									
										
										
										
											2020-10-14 18:06:41 -07:00
										 |  |  |             &[
 | 
					
						
							|  |  |  |                 TEST_PPROGRAM_NOT_EXECUTABLE,
 | 
					
						
							|  |  |  |                 bump_seed1,
 | 
					
						
							|  |  |  |                 bump_seed2,
 | 
					
						
							|  |  |  |                 bump_seed3,
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							| 
									
										
										
										
											2020-10-02 13:55:22 -07:00
										 |  |  |             account_metas.clone(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let message = Message::new(&[instruction], Some(&mint_pubkey));
 | 
					
						
							|  |  |  |         let tx = Transaction::new(
 | 
					
						
							|  |  |  |             &[
 | 
					
						
							|  |  |  |                 &mint_keypair,
 | 
					
						
							|  |  |  |                 &argument_keypair,
 | 
					
						
							|  |  |  |                 &invoked_argument_keypair,
 | 
					
						
							|  |  |  |                 &from_keypair,
 | 
					
						
							|  |  |  |             ],
 | 
					
						
							|  |  |  |             message.clone(),
 | 
					
						
							|  |  |  |             bank.last_blockhash(),
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         let (result, inner_instructions) = process_transaction_and_record_inner(&bank, tx);
 | 
					
						
							|  |  |  |         let invoked_programs: Vec<Pubkey> = inner_instructions[0]
 | 
					
						
							|  |  |  |             .iter()
 | 
					
						
							|  |  |  |             .map(|ix| message.account_keys[ix.program_id_index as usize].clone())
 | 
					
						
							|  |  |  |             .collect();
 | 
					
						
							|  |  |  |         assert_eq!(invoked_programs, vec![argument_keypair.pubkey().clone()]);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             result.unwrap_err(),
 | 
					
						
							|  |  |  |             TransactionError::InstructionError(0, InstructionError::AccountNotExecutable)
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Check final state
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 13:38:42 -07:00
										 |  |  |         assert_eq!(43, bank.get_balance(&derived_key1));
 | 
					
						
							|  |  |  |         let account = bank.get_account(&derived_key1).unwrap();
 | 
					
						
							|  |  |  |         assert_eq!(invoke_program_id, account.owner);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             MAX_PERMITTED_DATA_INCREASE,
 | 
					
						
							|  |  |  |             bank.get_account(&derived_key1).unwrap().data.len()
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         for i in 0..20 {
 | 
					
						
							|  |  |  |             assert_eq!(i as u8, account.data[i]);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2020-04-28 14:33:56 -07:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-01-02 15:12:42 -08:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:07:09 -07:00
										 |  |  | #[cfg(feature = "bpf_rust")]
 | 
					
						
							|  |  |  | #[test]
 | 
					
						
							|  |  |  | fn test_program_bpf_call_depth() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     println!("Test program: solana_bpf_rust_call_depth");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let GenesisConfigInfo {
 | 
					
						
							|  |  |  |         genesis_config,
 | 
					
						
							|  |  |  |         mint_keypair,
 | 
					
						
							|  |  |  |         ..
 | 
					
						
							|  |  |  |     } = create_genesis_config(50);
 | 
					
						
							|  |  |  |     let mut bank = Bank::new(&genesis_config);
 | 
					
						
							|  |  |  |     let (name, id, entrypoint) = solana_bpf_loader_program!();
 | 
					
						
							| 
									
										
										
										
											2020-10-29 16:17:36 -07:00
										 |  |  |     bank.add_builtin(&name, id, entrypoint);
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:07:09 -07:00
										 |  |  |     let bank_client = BankClient::new(bank);
 | 
					
						
							|  |  |  |     let program_id = load_bpf_program(
 | 
					
						
							|  |  |  |         &bank_client,
 | 
					
						
							|  |  |  |         &bpf_loader::id(),
 | 
					
						
							|  |  |  |         &mint_keypair,
 | 
					
						
							|  |  |  |         "solana_bpf_rust_call_depth",
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let instruction = Instruction::new(
 | 
					
						
							|  |  |  |         program_id,
 | 
					
						
							| 
									
										
										
										
											2020-10-28 13:16:13 -07:00
										 |  |  |         &(BpfComputeBudget::default().max_call_depth - 1),
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:07:09 -07:00
										 |  |  |         vec![],
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  |     let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |     assert!(result.is_ok());
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-04 18:46:26 +01:00
										 |  |  |     let instruction = Instruction::new(
 | 
					
						
							|  |  |  |         program_id,
 | 
					
						
							|  |  |  |         &BpfComputeBudget::default().max_call_depth,
 | 
					
						
							|  |  |  |         vec![],
 | 
					
						
							|  |  |  |     );
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:07:09 -07:00
										 |  |  |     let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |     assert!(result.is_err());
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  | #[test]
 | 
					
						
							|  |  |  | fn assert_instruction_count() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let mut programs = Vec::new();
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_c")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[
 | 
					
						
							|  |  |  |             ("bpf_to_bpf", 13),
 | 
					
						
							|  |  |  |             ("multiple_static", 8),
 | 
					
						
							| 
									
										
										
										
											2020-09-25 17:02:48 -07:00
										 |  |  |             ("noop", 57),
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |             ("relative_call", 10),
 | 
					
						
							| 
									
										
										
										
											2020-09-25 17:02:48 -07:00
										 |  |  |             ("sanity", 1140),
 | 
					
						
							|  |  |  |             ("sanity++", 1140),
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |             ("struct_pass", 8),
 | 
					
						
							|  |  |  |             ("struct_ret", 22),
 | 
					
						
							|  |  |  |         ]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     #[cfg(feature = "bpf_rust")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         programs.extend_from_slice(&[
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_128bit", 543),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_alloc", 19082),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_dep_crate", 2),
 | 
					
						
							| 
									
										
										
										
											2020-10-06 11:03:51 -07:00
										 |  |  |             ("solana_bpf_rust_external_spend", 538),
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |             ("solana_bpf_rust_iter", 723),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_many_args", 231),
 | 
					
						
							| 
									
										
										
										
											2020-10-06 23:52:13 -07:00
										 |  |  |             ("solana_bpf_rust_noop", 488),
 | 
					
						
							| 
									
										
										
										
											2020-10-06 11:03:51 -07:00
										 |  |  |             ("solana_bpf_rust_param_passing", 46),
 | 
					
						
							| 
									
										
										
										
											2020-10-06 23:52:13 -07:00
										 |  |  |             ("solana_bpf_rust_ristretto", 19399),
 | 
					
						
							|  |  |  |             ("solana_bpf_rust_sanity", 1965),
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |         ]);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for program in programs.iter() {
 | 
					
						
							|  |  |  |         println!("Test program: {:?}", program.0);
 | 
					
						
							| 
									
										
										
										
											2020-10-19 12:12:08 -07:00
										 |  |  |         let program_id = solana_sdk::pubkey::new_rand();
 | 
					
						
							|  |  |  |         let key = solana_sdk::pubkey::new_rand();
 | 
					
						
							| 
									
										
										
										
											2020-09-01 17:25:55 -07:00
										 |  |  |         let mut account = RefCell::new(Account::default());
 | 
					
						
							|  |  |  |         let parameter_accounts = vec![KeyedAccount::new(&key, false, &mut account)];
 | 
					
						
							|  |  |  |         let count = run_program(program.0, &program_id, ¶meter_accounts[..], &[]).unwrap();
 | 
					
						
							|  |  |  |         println!("  {} : {:?} ({:?})", program.0, count, program.1,);
 | 
					
						
							|  |  |  |         assert!(count <= program.1);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-19 12:17:46 -07:00
										 |  |  | #[cfg(any(feature = "bpf_rust"))]
 | 
					
						
							|  |  |  | #[test]
 | 
					
						
							|  |  |  | fn test_program_bpf_instruction_introspection() {
 | 
					
						
							|  |  |  |     solana_logger::setup();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let GenesisConfigInfo {
 | 
					
						
							|  |  |  |         genesis_config,
 | 
					
						
							|  |  |  |         mint_keypair,
 | 
					
						
							|  |  |  |         ..
 | 
					
						
							|  |  |  |     } = create_genesis_config(50_000);
 | 
					
						
							|  |  |  |     let mut bank = Bank::new(&genesis_config);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let (name, id, entrypoint) = solana_bpf_loader_program!();
 | 
					
						
							| 
									
										
										
										
											2020-10-29 16:17:36 -07:00
										 |  |  |     bank.add_builtin(&name, id, entrypoint);
 | 
					
						
							| 
									
										
										
										
											2020-09-19 12:17:46 -07:00
										 |  |  |     let bank = Arc::new(bank);
 | 
					
						
							|  |  |  |     let bank_client = BankClient::new_shared(&bank);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let program_id = load_bpf_program(
 | 
					
						
							|  |  |  |         &bank_client,
 | 
					
						
							|  |  |  |         &bpf_loader::id(),
 | 
					
						
							|  |  |  |         &mint_keypair,
 | 
					
						
							|  |  |  |         "solana_bpf_rust_instruction_introspection",
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Passing transaction
 | 
					
						
							|  |  |  |     let account_metas = vec![AccountMeta::new_readonly(
 | 
					
						
							|  |  |  |         solana_sdk::sysvar::instructions::id(),
 | 
					
						
							|  |  |  |         false,
 | 
					
						
							|  |  |  |     )];
 | 
					
						
							|  |  |  |     let instruction0 = Instruction::new(program_id, &[0u8, 0u8], account_metas.clone());
 | 
					
						
							|  |  |  |     let instruction1 = Instruction::new(program_id, &[0u8, 1u8], account_metas.clone());
 | 
					
						
							|  |  |  |     let instruction2 = Instruction::new(program_id, &[0u8, 2u8], account_metas);
 | 
					
						
							|  |  |  |     let message = Message::new(
 | 
					
						
							|  |  |  |         &[instruction0, instruction1, instruction2],
 | 
					
						
							|  |  |  |         Some(&mint_keypair.pubkey()),
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  |     let result = bank_client.send_and_confirm_message(&[&mint_keypair], message);
 | 
					
						
							|  |  |  |     assert!(result.is_ok());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // writable special instructions11111 key, should not be allowed
 | 
					
						
							|  |  |  |     let account_metas = vec![AccountMeta::new(
 | 
					
						
							|  |  |  |         solana_sdk::sysvar::instructions::id(),
 | 
					
						
							|  |  |  |         false,
 | 
					
						
							|  |  |  |     )];
 | 
					
						
							|  |  |  |     let instruction = Instruction::new(program_id, &0u8, account_metas);
 | 
					
						
							|  |  |  |     let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |     assert_eq!(
 | 
					
						
							|  |  |  |         result.unwrap_err().unwrap(),
 | 
					
						
							|  |  |  |         TransactionError::InvalidAccountIndex
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // No accounts, should error
 | 
					
						
							|  |  |  |     let instruction = Instruction::new(program_id, &0u8, vec![]);
 | 
					
						
							|  |  |  |     let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
 | 
					
						
							|  |  |  |     assert!(result.is_err());
 | 
					
						
							|  |  |  |     assert_eq!(
 | 
					
						
							|  |  |  |         result.unwrap_err().unwrap(),
 | 
					
						
							|  |  |  |         TransactionError::InstructionError(
 | 
					
						
							|  |  |  |             0,
 | 
					
						
							|  |  |  |             solana_sdk::instruction::InstructionError::NotEnoughAccountKeys
 | 
					
						
							|  |  |  |         )
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  |     assert!(bank
 | 
					
						
							|  |  |  |         .get_account(&solana_sdk::sysvar::instructions::id())
 | 
					
						
							|  |  |  |         .is_none());
 | 
					
						
							|  |  |  | }
 |