mpl_token_auth_rules/state/v2/constraint/
all.rs

1use solana_program::{msg, program_error::ProgramError};
2
3use crate::{
4    error::RuleSetError,
5    state::{try_from_bytes, RuleResult},
6    state::{
7        v2::{Constraint, ConstraintType, RuleV2, HEADER_SECTION, U64_BYTES},
8        Header,
9    },
10};
11
12/// Constraint representing a group AND, where every rule contained must pass.
13pub struct All<'a> {
14    /// The number of rules contained under All.
15    pub size: &'a u64,
16    /// The vector of 'RuleV2' contained under All.
17    pub rules: Vec<RuleV2<'a>>,
18}
19
20impl<'a> All<'a> {
21    /// Deserialize a constraint from a byte array.
22    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, RuleSetError> {
23        let size = try_from_bytes::<u64>(0, U64_BYTES, bytes)?;
24
25        let mut rules = Vec::with_capacity(*size as usize);
26        let mut offset = U64_BYTES;
27
28        for _ in 0..*size {
29            let rule = RuleV2::from_bytes(&bytes[offset..])?;
30            offset += rule.length();
31            rules.push(rule);
32        }
33
34        Ok(Self { size, rules })
35    }
36
37    /// Serialize a constraint into a byte array.
38    pub fn serialize(rules: &[&[u8]]) -> Result<Vec<u8>, RuleSetError> {
39        // length of the assert
40        let length = (U64_BYTES
41            + rules
42                .iter()
43                .map(|v| v.len())
44                .reduce(|accum, item| accum + item)
45                .ok_or(RuleSetError::DataIsEmpty)
46                .unwrap()) as u32;
47
48        let mut data = Vec::with_capacity(HEADER_SECTION + length as usize);
49
50        // Header
51        Header::serialize(ConstraintType::All, length, &mut data);
52
53        // Constraint
54        // - size
55        let size = rules.len() as u64;
56        data.extend(u64::to_le_bytes(size));
57        // - rules
58        rules.iter().for_each(|x| data.extend(x.iter()));
59
60        Ok(data)
61    }
62}
63
64impl<'a> Constraint<'a> for All<'a> {
65    fn constraint_type(&self) -> ConstraintType {
66        ConstraintType::All
67    }
68
69    fn validate(
70        &self,
71        accounts: &std::collections::HashMap<
72            solana_program::pubkey::Pubkey,
73            &solana_program::account_info::AccountInfo,
74        >,
75        payload: &crate::payload::Payload,
76        update_rule_state: bool,
77        rule_set_state_pda: &Option<&solana_program::account_info::AccountInfo>,
78        rule_authority: &Option<&solana_program::account_info::AccountInfo>,
79    ) -> RuleResult {
80        msg!("Validating All");
81
82        let mut last: Option<ProgramError> = None;
83
84        for rule in &self.rules {
85            let result = rule.validate(
86                accounts,
87                payload,
88                update_rule_state,
89                rule_set_state_pda,
90                rule_authority,
91            );
92            // Return failure on the first failing rule.
93            match result {
94                RuleResult::Success(err) => last = Some(err),
95                _ => return result,
96            }
97        }
98
99        // Return pass if and only if all rules passed.
100        RuleResult::Success(last.unwrap_or_else(|| RuleSetError::UnexpectedRuleSetFailure.into()))
101    }
102}