identity_iota_core/rebased/migration/
multicontroller.rs1use std::collections::HashMap;
5use std::collections::HashSet;
6
7use crate::rebased::iota::types::Bag;
8use crate::rebased::iota::types::Number;
9use iota_interaction::types::base_types::ObjectID;
10use iota_interaction::types::collection_types::Entry;
11use iota_interaction::types::collection_types::VecMap;
12use iota_interaction::types::collection_types::VecSet;
13use iota_interaction::types::id::UID;
14use serde::Deserialize;
15use serde::Serialize;
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(
20 try_from = "IotaProposal::<T>",
21 into = "IotaProposal::<T>",
22 bound(serialize = "T: Serialize + Clone")
23)]
24pub struct Proposal<T> {
25 id: UID,
26 expiration_epoch: Option<u64>,
27 votes: u64,
28 voters: HashSet<ObjectID>,
29 pub(crate) action: T,
30}
31
32impl<T> Proposal<T> {
33 pub fn id(&self) -> ObjectID {
35 *self.id.object_id()
36 }
37
38 pub fn votes(&self) -> u64 {
40 self.votes
41 }
42
43 pub(crate) fn votes_mut(&mut self) -> &mut u64 {
44 &mut self.votes
45 }
46
47 pub fn action(&self) -> &T {
49 &self.action
50 }
51
52 pub fn into_action(self) -> T {
54 self.action
55 }
56
57 pub fn voters(&self) -> &HashSet<ObjectID> {
59 &self.voters
60 }
61
62 pub fn expiration_epoch(&self) -> Option<u64> {
64 self.expiration_epoch
65 }
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69struct IotaProposal<T> {
70 id: UID,
71 expiration_epoch: Option<Number<u64>>,
72 votes: Number<u64>,
73 voters: VecSet<ObjectID>,
74 action: T,
75}
76
77impl<T> TryFrom<IotaProposal<T>> for Proposal<T> {
78 type Error = <u64 as TryFrom<Number<u64>>>::Error;
79 fn try_from(proposal: IotaProposal<T>) -> Result<Self, Self::Error> {
80 let IotaProposal {
81 id,
82 expiration_epoch,
83 votes,
84 voters,
85 action,
86 } = proposal;
87 let expiration_epoch = expiration_epoch.map(TryInto::try_into).transpose()?;
88 let votes = votes.try_into()?;
89 let voters = voters.contents.into_iter().collect();
90
91 Ok(Self {
92 id,
93 expiration_epoch,
94 votes,
95 voters,
96 action,
97 })
98 }
99}
100
101impl<T> From<Proposal<T>> for IotaProposal<T> {
102 fn from(value: Proposal<T>) -> Self {
103 let Proposal {
104 id,
105 expiration_epoch,
106 votes,
107 voters,
108 action,
109 } = value;
110 let contents = voters.into_iter().collect();
111 IotaProposal {
112 id,
113 expiration_epoch: expiration_epoch.map(Into::into),
114 votes: votes.into(),
115 voters: VecSet { contents },
116 action,
117 }
118 }
119}
120
121#[derive(Clone, Debug, Serialize, Deserialize)]
123#[serde(try_from = "IotaMulticontroller::<T>")]
124pub struct Multicontroller<T> {
125 controlled_value: T,
126 controllers: HashMap<ObjectID, u64>,
127 threshold: u64,
128 active_proposals: HashSet<ObjectID>,
129 proposals: Bag,
130}
131
132impl<T> Multicontroller<T> {
133 pub fn controlled_value(&self) -> &T {
135 &self.controlled_value
136 }
137
138 pub fn threshold(&self) -> u64 {
140 self.threshold
141 }
142
143 pub fn proposals(&self) -> &HashSet<ObjectID> {
145 &self.active_proposals
146 }
147
148 pub(crate) fn proposals_bag_id(&self) -> ObjectID {
149 *self.proposals.id.object_id()
150 }
151
152 pub fn controller_voting_power(&self, controller_cap_id: ObjectID) -> Option<u64> {
154 self.controllers.get(&controller_cap_id).copied()
155 }
156
157 pub fn into_inner(self) -> T {
159 self.controlled_value
160 }
161
162 pub(crate) fn controllers(&self) -> &HashMap<ObjectID, u64> {
163 &self.controllers
164 }
165
166 pub fn has_member(&self, cap_id: ObjectID) -> bool {
168 self.controllers.contains_key(&cap_id)
169 }
170}
171
172impl<T> TryFrom<IotaMulticontroller<T>> for Multicontroller<T> {
173 type Error = <u64 as TryFrom<Number<u64>>>::Error;
174 fn try_from(value: IotaMulticontroller<T>) -> Result<Self, Self::Error> {
175 let IotaMulticontroller {
176 controlled_value,
177 controllers,
178 threshold,
179 active_proposals,
180 proposals,
181 } = value;
182 let controllers = controllers
183 .contents
184 .into_iter()
185 .map(|Entry { key: id, value: vp }| (u64::try_from(vp).map(|vp| (id, vp))))
186 .collect::<Result<_, _>>()?;
187
188 Ok(Multicontroller {
189 controlled_value,
190 controllers,
191 threshold: threshold.try_into()?,
192 active_proposals,
193 proposals,
194 })
195 }
196}
197
198#[derive(Debug, Serialize, Deserialize)]
199struct IotaMulticontroller<T> {
200 controlled_value: T,
201 controllers: VecMap<ObjectID, Number<u64>>,
202 threshold: Number<u64>,
203 active_proposals: HashSet<ObjectID>,
204 proposals: Bag,
205}