1use {
4 miraland_program::{
5 account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError,
6 pubkey::Pubkey,
7 },
8 std::str::from_utf8,
9};
10
11pub fn process_instruction(
13 _program_id: &Pubkey,
14 accounts: &[AccountInfo],
15 input: &[u8],
16) -> ProgramResult {
17 let account_info_iter = &mut accounts.iter();
18 let mut missing_required_signature = false;
19 for account_info in account_info_iter {
20 if let Some(address) = account_info.signer_key() {
21 msg!("Signed by {:?}", address);
22 } else {
23 missing_required_signature = true;
24 }
25 }
26 if missing_required_signature {
27 return Err(ProgramError::MissingRequiredSignature);
28 }
29
30 let memo = from_utf8(input).map_err(|err| {
31 msg!("Invalid UTF-8, from byte {}", err.valid_up_to());
32 ProgramError::InvalidInstructionData
33 })?;
34 msg!("Memo (len {}): {:?}", memo.len(), memo);
35
36 Ok(())
37}
38
39#[cfg(test)]
40mod tests {
41 use {
42 super::*,
43 miraland_program::{
44 account_info::IntoAccountInfo, program_error::ProgramError, pubkey::Pubkey,
45 },
46 miraland_sdk::account::Account,
47 };
48
49 #[test]
50 fn test_utf8_memo() {
51 let program_id = Pubkey::new_from_array([0; 32]);
52
53 let string = b"letters and such";
54 assert_eq!(Ok(()), process_instruction(&program_id, &[], string));
55
56 let emoji = "🐆".as_bytes();
57 let bytes = [0xF0, 0x9F, 0x90, 0x86];
58 assert_eq!(emoji, bytes);
59 assert_eq!(Ok(()), process_instruction(&program_id, &[], emoji));
60
61 let mut bad_utf8 = bytes;
62 bad_utf8[3] = 0xFF; assert_eq!(
64 Err(ProgramError::InvalidInstructionData),
65 process_instruction(&program_id, &[], &bad_utf8)
66 );
67 }
68
69 #[test]
70 fn test_signers() {
71 let program_id = Pubkey::new_from_array([0; 32]);
72 let memo = "🐆".as_bytes();
73
74 let pubkey0 = Pubkey::new_unique();
75 let pubkey1 = Pubkey::new_unique();
76 let pubkey2 = Pubkey::new_unique();
77 let mut account0 = Account::default();
78 let mut account1 = Account::default();
79 let mut account2 = Account::default();
80
81 let signed_account_infos = vec![
82 (&pubkey0, true, &mut account0).into_account_info(),
83 (&pubkey1, true, &mut account1).into_account_info(),
84 (&pubkey2, true, &mut account2).into_account_info(),
85 ];
86 assert_eq!(
87 Ok(()),
88 process_instruction(&program_id, &signed_account_infos, memo)
89 );
90
91 assert_eq!(Ok(()), process_instruction(&program_id, &[], memo));
92
93 let unsigned_account_infos = vec![
94 (&pubkey0, false, &mut account0).into_account_info(),
95 (&pubkey1, false, &mut account1).into_account_info(),
96 (&pubkey2, false, &mut account2).into_account_info(),
97 ];
98 assert_eq!(
99 Err(ProgramError::MissingRequiredSignature),
100 process_instruction(&program_id, &unsigned_account_infos, memo)
101 );
102
103 let partially_signed_account_infos = vec![
104 (&pubkey0, true, &mut account0).into_account_info(),
105 (&pubkey1, false, &mut account1).into_account_info(),
106 (&pubkey2, true, &mut account2).into_account_info(),
107 ];
108 assert_eq!(
109 Err(ProgramError::MissingRequiredSignature),
110 process_instruction(&program_id, &partially_signed_account_infos, memo)
111 );
112 }
113}