mpl_token_auth_rules/state/v2/constraint/
additional_signer.rs

1use solana_program::{
2    msg,
3    pubkey::{Pubkey, PUBKEY_BYTES},
4};
5
6use crate::{
7    error::RuleSetError,
8    state::{try_from_bytes, RuleResult},
9    state::{
10        v2::{Constraint, ConstraintType, HEADER_SECTION},
11        Header,
12    },
13};
14
15/// Constraint representing the requirement that An additional signer must be present.
16///
17/// This constraint does not require any `Payload` values, but the additional signer account
18/// must be provided to `Validate` via the `additional_rule_accounts` argument so that whether
19/// it is a signer can be retrieved from its `AccountInfo` struct.
20pub struct AdditionalSigner<'a> {
21    /// The public key that must have also signed the transaction.
22    pub account: &'a Pubkey,
23}
24
25impl<'a> AdditionalSigner<'a> {
26    /// Deserialize a constraint from a byte array.
27    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, RuleSetError> {
28        let account = try_from_bytes::<Pubkey>(0, PUBKEY_BYTES, bytes)?;
29        Ok(Self { account })
30    }
31
32    /// Serialize a constraint into a byte array.
33    pub fn serialize(account: Pubkey) -> Result<Vec<u8>, RuleSetError> {
34        let mut data = Vec::with_capacity(HEADER_SECTION + PUBKEY_BYTES);
35
36        // Header
37        Header::serialize(
38            ConstraintType::AdditionalSigner,
39            PUBKEY_BYTES as u32,
40            &mut data,
41        );
42
43        // Constraint
44        // - rule
45        data.extend(account.as_ref());
46
47        Ok(data)
48    }
49}
50
51impl<'a> Constraint<'a> for AdditionalSigner<'a> {
52    fn constraint_type(&self) -> ConstraintType {
53        ConstraintType::AdditionalSigner
54    }
55
56    fn validate(
57        &self,
58        accounts: &std::collections::HashMap<
59            solana_program::pubkey::Pubkey,
60            &solana_program::account_info::AccountInfo,
61        >,
62        _payload: &crate::payload::Payload,
63        _update_rule_state: bool,
64        _rule_set_state_pda: &Option<&solana_program::account_info::AccountInfo>,
65        _rule_authority: &Option<&solana_program::account_info::AccountInfo>,
66    ) -> RuleResult {
67        msg!("Validating AdditionalSigner");
68
69        if let Some(signer) = accounts.get(self.account) {
70            if signer.is_signer {
71                RuleResult::Success(self.constraint_type().to_error())
72            } else {
73                RuleResult::Failure(self.constraint_type().to_error())
74            }
75        } else {
76            RuleResult::Error(RuleSetError::MissingAccount.into())
77        }
78    }
79}