dpp/data_contract/change_control_rules/
mod.rs

1pub mod authorized_action_takers;
2pub mod v0;
3
4use crate::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers;
5use crate::data_contract::change_control_rules::v0::ChangeControlRulesV0;
6use crate::data_contract::group::Group;
7use crate::data_contract::GroupContractPosition;
8use crate::group::action_taker::{ActionGoal, ActionTaker};
9#[cfg(feature = "json-conversion")]
10use crate::serialization::JsonConvertible;
11#[cfg(feature = "value-conversion")]
12use crate::serialization::ValueConvertible;
13use bincode::{Decode, Encode};
14use derive_more::From;
15use platform_value::Identifier;
16use serde::{Deserialize, Serialize};
17use std::collections::BTreeMap;
18use std::fmt;
19
20#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
21#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
22#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, PartialEq, Eq, From)]
23#[serde(tag = "$formatVersion")]
24pub enum ChangeControlRules {
25    #[serde(rename = "0")]
26    V0(ChangeControlRulesV0),
27}
28
29impl ChangeControlRules {
30    pub fn admin_action_takers(&self) -> &AuthorizedActionTakers {
31        match self {
32            ChangeControlRules::V0(v0) => &v0.admin_action_takers,
33        }
34    }
35    pub fn authorized_to_make_change_action_takers(&self) -> &AuthorizedActionTakers {
36        match self {
37            ChangeControlRules::V0(v0) => &v0.authorized_to_make_change,
38        }
39    }
40
41    pub fn set_admin_action_takers(&mut self, admin_action_takers: AuthorizedActionTakers) {
42        match self {
43            ChangeControlRules::V0(v0) => {
44                v0.admin_action_takers = admin_action_takers;
45            }
46        }
47    }
48
49    pub fn set_authorized_to_make_change_action_takers(
50        &mut self,
51        authorized_to_make_change: AuthorizedActionTakers,
52    ) {
53        match self {
54            ChangeControlRules::V0(v0) => {
55                v0.authorized_to_make_change = authorized_to_make_change;
56            }
57        }
58    }
59
60    pub fn can_make_change(
61        &self,
62        contract_owner_id: &Identifier,
63        main_group: Option<GroupContractPosition>,
64        groups: &BTreeMap<GroupContractPosition, Group>,
65        action_taker: &ActionTaker,
66        goal: ActionGoal,
67    ) -> bool {
68        match self {
69            ChangeControlRules::V0(v0) => {
70                v0.can_make_change(contract_owner_id, main_group, groups, action_taker, goal)
71            }
72        }
73    }
74
75    pub fn can_change_authorized_action_takers(
76        &self,
77        controlling_action_takers: &AuthorizedActionTakers,
78        contract_owner_id: &Identifier,
79        main_group: Option<GroupContractPosition>,
80        groups: &BTreeMap<GroupContractPosition, Group>,
81        action_taker: &ActionTaker,
82        goal: ActionGoal,
83    ) -> bool {
84        match self {
85            ChangeControlRules::V0(v0) => v0.can_change_authorized_action_takers(
86                controlling_action_takers,
87                contract_owner_id,
88                main_group,
89                groups,
90                action_taker,
91                goal,
92            ),
93        }
94    }
95
96    pub fn can_change_admin_action_takers(
97        &self,
98        admin_action_takers: &AuthorizedActionTakers,
99        contract_owner_id: &Identifier,
100        main_group: Option<GroupContractPosition>,
101        groups: &BTreeMap<GroupContractPosition, Group>,
102        action_taker: &ActionTaker,
103        goal: ActionGoal,
104    ) -> bool {
105        match self {
106            ChangeControlRules::V0(v0) => v0.can_change_admin_action_takers(
107                admin_action_takers,
108                contract_owner_id,
109                main_group,
110                groups,
111                action_taker,
112                goal,
113            ),
114        }
115    }
116    pub fn can_change_to(
117        &self,
118        other: &ChangeControlRules,
119        contract_owner_id: &Identifier,
120        main_group: Option<GroupContractPosition>,
121        groups: &BTreeMap<GroupContractPosition, Group>,
122        action_taker: &ActionTaker,
123        goal: ActionGoal,
124    ) -> bool {
125        match (self, other) {
126            (ChangeControlRules::V0(v0), ChangeControlRules::V0(v0_other)) => v0.can_change_to(
127                v0_other,
128                contract_owner_id,
129                main_group,
130                groups,
131                action_taker,
132                goal,
133            ),
134        }
135    }
136}
137
138impl fmt::Display for ChangeControlRules {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        match self {
141            ChangeControlRules::V0(v0) => {
142                write!(f, "{}", v0) //just pass through
143            }
144        }
145    }
146}
147
148#[cfg(all(test, feature = "json-conversion"))]
149mod tests {
150    use super::*;
151    use crate::serialization::JsonConvertible;
152
153    #[test]
154    fn change_control_rules_json_round_trip() {
155        let rules = ChangeControlRules::V0(ChangeControlRulesV0 {
156            authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
157            admin_action_takers: AuthorizedActionTakers::NoOne,
158            changing_authorized_action_takers_to_no_one_allowed: true,
159            changing_admin_action_takers_to_no_one_allowed: false,
160            self_changing_admin_action_takers_allowed: true,
161        });
162
163        let json = rules.to_json().expect("to_json should succeed");
164
165        // Verify boolean fields
166        assert_eq!(
167            json["changingAuthorizedActionTakersToNoOneAllowed"]
168                .as_bool()
169                .unwrap(),
170            true
171        );
172        assert_eq!(
173            json["changingAdminActionTakersToNoOneAllowed"]
174                .as_bool()
175                .unwrap(),
176            false
177        );
178        assert_eq!(
179            json["selfChangingAdminActionTakersAllowed"]
180                .as_bool()
181                .unwrap(),
182            true
183        );
184
185        // round-trip
186        let restored = ChangeControlRules::from_json(json).expect("from_json should succeed");
187        assert_eq!(rules, restored);
188    }
189
190    #[test]
191    fn change_control_rules_with_group_json_round_trip() {
192        let rules = ChangeControlRules::V0(ChangeControlRulesV0 {
193            authorized_to_make_change: AuthorizedActionTakers::Group(3),
194            admin_action_takers: AuthorizedActionTakers::Identity(Identifier::from([0xFFu8; 32])),
195            changing_authorized_action_takers_to_no_one_allowed: false,
196            changing_admin_action_takers_to_no_one_allowed: false,
197            self_changing_admin_action_takers_allowed: false,
198        });
199
200        let json = rules.to_json().expect("to_json should succeed");
201        let restored = ChangeControlRules::from_json(json).expect("from_json should succeed");
202        assert_eq!(rules, restored);
203    }
204}