1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use anchor_lang::{
    err,
    solana_program::{msg, pubkey::Pubkey},
    Result,
};

use crate::{
    errors::SystemProgramError, sdk::compressed_account::PackedCompressedAccountWithMerkleContext,
};

pub fn input_compressed_accounts_signer_check(
    input_compressed_accounts_with_merkle_context: &[PackedCompressedAccountWithMerkleContext],
    authority: &Pubkey,
) -> Result<()> {
    input_compressed_accounts_with_merkle_context
        .iter()
        .try_for_each(
            |compressed_account_with_context: &PackedCompressedAccountWithMerkleContext| {
                if compressed_account_with_context.compressed_account.owner == *authority
                    && compressed_account_with_context
                        .compressed_account
                        .data
                        .is_none()
                {
                    Ok(())
                } else {
                    msg!(
                        "signer check failed compressed account owner {} != authority {} or data is not none {} (only programs can own compressed accounts with data)",
                        compressed_account_with_context.compressed_account.owner,
                        authority,
                        compressed_account_with_context.compressed_account.data.is_none()
                    );
                    err!(SystemProgramError::SignerCheckFailed)
                }
            },
        )
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::sdk::compressed_account::CompressedAccount;

    #[test]
    fn test_input_compressed_accounts_signer_check() {
        let authority = Pubkey::new_unique();
        let compressed_account_with_context = PackedCompressedAccountWithMerkleContext {
            compressed_account: CompressedAccount {
                owner: authority,
                ..CompressedAccount::default()
            },
            ..PackedCompressedAccountWithMerkleContext::default()
        };

        assert_eq!(
            input_compressed_accounts_signer_check(
                &vec![compressed_account_with_context.clone()],
                &authority
            ),
            Ok(())
        );
        let invalid_compressed_account_with_context = PackedCompressedAccountWithMerkleContext {
            compressed_account: CompressedAccount {
                owner: Pubkey::new_unique(),
                ..CompressedAccount::default()
            },
            ..PackedCompressedAccountWithMerkleContext::default()
        };
        assert_eq!(
            input_compressed_accounts_signer_check(
                &vec![
                    compressed_account_with_context,
                    invalid_compressed_account_with_context
                ],
                &authority
            ),
            Err(SystemProgramError::SignerCheckFailed.into())
        );
    }
}